Expand description
Rasant is a lightweight, high performance and flexible Rust library for structured logging, inspired by the likes of zap and zerolog.
It offers nanosecond precision, stackable logging and outstanding performance: on modern systems, Rasant can process and dispatch logs to multiple sinks in tens of nanoseconds, being normally bottlenecked by I/O operations. Can’t wait that long? There’s built-in async support!
§Main Features
- Minimal dependencies.
- Blazing fast performance, with zero allocations on most operations.
- Leveled, structured contextual logging with nanosecond precision.
- Simple API, with support for stacked logging.
- Configurable log filters.
- Thread safe.
- Highly configurable log sinks.
- Text and JSON log output.
- Support for dynamic async logging with constant lock time.
§Examples
§Basic Logging
Loggers can be easily initialized using sink defaults, and accessed via methods…
use rasant;
use rasant::Value;
let mut log = rasant::Logger::new();
log.add_sink(rasant::sink::stderr::default()).set_level(rasant::Level::Info);
log.set("program_name", "test");
log.info("hello world!");
log.warn_with("here's some context", [("line", Value::from(7))]);
log.debug("and i'm ignored :(");…or the much nicer macro API:
use rasant as r;
let mut log = r::Logger::new();
log.add_sink(r::sink::stderr::default()).set_level(r::Level::Info);
r::set!(log, program_name="test");
r::info!(log, "hello world!");
r::warn!(log, "here's some context", line = 7);
r::debug!(log, "and i'm ignored :(");2026-04-03 17:16:03.773 +0200 [INF] hello world! program_name="test"
2026-04-03 17:16:03.773 +0200 [WRN] here's some context program_name="test" line=7§Attributes
Rasant supports multiple attribute types (a.k.a Values): single Scalar values,
lists and maps.
use rasant as r;
let mut log = r::Logger::new();
log.add_sink(r::sink::stderr::default()).set_level(r::Level::Info);
r::info!(log, "a single", value = 123.456);
let simple_list = [1, 2, 3, 4];
r::info!(log, "lists can be simple", list = r::list!(simple_list));
r::info!(log, "or have mixed types", list = r::list!("string!", 123.456, 789012 as usize));
r::info!(log, "and so can maps!", map = r::map!("key #1" => 123, 456 => 789.012));2026-05-04 03:58:41.189 +0200 [INF] a single value=123.456
2026-05-04 03:58:41.189 +0200 [INF] lists can be simple list=[1, 2, 3, 4]
2026-05-04 03:58:41.189 +0200 [INF] or have mixed types list=["string!", 123.456, 0xc0a14]
2026-05-04 03:58:41.189 +0200 [INF] and so can maps! map={"key #1": 123, 456: 789.012}§Stacking
All Loggers can be cheaply cloned, inheriting all settings from its
parents - including Levels, sinks, filters
and fixed attributes, allowing for very flexible setups.
For example, to have all errors (or higher) within a thread logged to
stderr:
use rasant as r;
use std::thread;
let mut log = r::Logger::new();
log.add_sink(r::sink::stdout::default()).set_level(r::Level::Info);
r::info!(log, "main logs to stdout only");
let mut thread_log = log.clone();
thread::spawn(move || {
thread_log.add_sink(r::sink::stderr::default()).set_level(r::Level::Error);
r::set!(thread_log, thread_id = thread::current().id());
r::info!(thread_log, "this will not log anything");
r::fatal!(thread_log, "but this will log to both stdout and stderr");
});§Configuring Sinks
sinks can be configured to tweak multiple parameters, including time and
overall output format.
use rasant as r;
let mut log = r::Logger::new();
log.set_level(r::Level::Info).add_sink(
r::sink::stdout::new(r::sink::stdout::StdoutConfig {
formatter_cfg: r::FormatterConfig {
format: r::OutputFormat::Json,
time_format: r::TimeFormat::UtcNanosDateTime,
..r::FormatterConfig::default()
},
..r::sink::stdout::StdoutConfig::default()
})
);
r::info!(log, "hello!");{"time":"2026-04-03 16:03:04.481888522","level":"info","message":"hello!"}§Asynchronous Logging
Loggers can dynamically enable/disable async writes.
When in async mode, log operations have a slightly longer (as details are copied into a queue) but fixed lock time, making it ideal f.ex. for writing to slow storage without compromising overall performance.
use rasant as r;
let mut log = r::Logger::new();
log.set_level(r::Level::Info).add_sink(r::sink::stdout::default());
r::info!(log, "this is writen synchronously");
log.set_async(true);
r::info!(log, "and these write");
r::warn!(log, "asynchronously, but");
r::info!(log, "in order!");§Filtering
Loggers can apply configurable runtime filters on log operations.
Supported filters include:
- Multiple log levels.
- Log message contents.
- Log attributes presence.
- Log attribute value contents.
- Several log output sampling criteria.
Note that filters are evaluated at logging time, and will
introduce (minimal) latency, regardless of Loggers having async mode
enabled.
use rasant as r;
use std::time::Duration;
// Log a maximum of 10 Debug, Warning and Fatal updates per second, to keep SREs happy.
let mut log = r::Logger::new();
log
.add_sink(r::sink::stdout::default())
.set_all_levels()
.add_filter(
r::filter::level::In::new(
r::filter::level::InConfig {
levels: [r::Level::Debug, r::Level::Warning, r::Level::Fatal],
}))
.add_filter(
r::filter::sample::Burst::new(
r::filter::sample::BurstConfig {
period: Duration::from_millis(1000),
max_updates: 10,
}));
r::info!(log, "this will not log");
r::debug!(log, "but");
r::fatal!(log, "these");
r::warn!(log, "will");§Concepts
Rasant is a structured logging library: it logs messages with a set of associated key-Value
pairs, in formats (f.ex. JSON) which are intended to
be easily machine-readable.
§Methodology
Rasant is built around individual Logger logging instances and sinks, which are
configurable destinations for log updates. When a log operation is performed, its level
is compared to the one defined for the Logger and, if applicable, the log is written
on all its sinks.
Once a sink is added to a Logger, it cannot be removed nor modified.
§Attributes
§Types
Attributes are the defining quality of a structured logging system, expressed
as key-value pairs. In Rasant, keys are &str, and Values are a dedicated
type, supporting different configuration of Scalars.
Scalars are the base unit for attribute values, mapping to basic data types: integers, floats and strings.Valueis a structured collection ofScalars.
Rasant supports three basic Value types:
Value::Scalaris a singleScalar, and the most commonly used type.Value::Listis an ordered set ofScalars.Value::Mapis an ordered set of key-valueScalars.
§Scope
Attributes can be set for Loggers as a whole, affecting all log operations, or for
individual log writes, which can optionally provide extra attributes with additional
information.
Upon key collisions, attribute values for the log call take precedence and override
Logger settings, but without modifying it.
§Memory Management
Rasant keeps all items associated with a Logger (keys, attribute values, their
Scalars and all strings) in a group of owned vector arrays. No other heap
allocation is ever performed.
These vectors will grow in size when needed - but never resize down. In practice, this means that after just a few log calls vectors will grow to the size required for normal operation, at which point all Rasant operations become effectively zero-allocation.
The vectored nature of Logger storage also makes cloning and dropping these
extremely efficient.
§Cloning and Stacking
Loggers can be cheaply cloned, extended and dropped. When a Logger is cloned, it
inherits all settings from the original, including levels, filters,
sinks (owned + inherited) and attributes.
This allows for very flexible logging setups. New Loggers can just be extensions of
an original with extra arguments, have newly defined sinks, log levels, filters and/or
async modes - or all of the above.
In general, programs using Rasant will instantiate a single root logger via Logger::new(),
and spawn nested clones as required.
§Asynchronous Operation
By default, log operations lock until writes are propagated to all sinks associated
with a given Logger.
To improve performance when slow and/or a high number of sinks is involved, Rasant
supports dynamic asynchronous logging.
Loggers can be switched to asynchronous mode via Logger::set_async. When enabled, log
operations defer writes by pushing them into a processing queue, and return immediately.
Rasant will spawn a single thread to handle all asynchronous write operations, and
close it automatically once no async Loggers are present, and all their deferred
writes have been flushed.
§Log Filters
Loggers supports optional, configurable filters for log updates. These are evaluated,
in order, on every log operation, blocking sink writes unless the configured criteria for all
filters is met. Multiple filters can be stacked to combine their behavior.
filters are evaluated after normal level checks, so their output is affected by each
Loggers log level. When using level-based filters (f.ex. Levels),
consider enabling set_all_levels() to avoid
unexpected interactions.
Note that filters are evaluated at logging time, even for Loggers in
asynchronous mode; as a result, every filter will introduce additional latency
on all log operations for that Logger.
§Error Handling
For performance’s sake, very few operations in Rasant’s public API return errors, and will panic upon failures instead.
Pretty much all errors related to logging are unrecoverable anyway - these will either
happen at initialization time, or when trying to write to a sink.
§Repository
This project is currently hosted at GitHub.
§License
Rasant is distrubuted under the MIT license.
Modules§
- filter
- Log filters for use with Rasant Logger instances.
- sink
- Log sinks for use with Rasant
crate::Loggerinstances.
Macros§
- debug
- Logs an update with debug level.
- error
- Logs an update with error level.
- fatal
- Logs an update with fatal level.
- info
- Logs an update with info level.
- list
- Creates a List from types which can be cast to a collection of Scalars.
- map
- Creates a Map from key/value types which can be cast to collections of Scalars.
- panic
- Logs an update with panic level.
- set
- Sets a number of attributes for a given logger.
- trace
- Logs an update with trace level.
- warn
- Logs an update with warning level.
Structs§
- Attribute
String - A string container for any of the types supported in attributes:
String, static&str, or an index within a string container. - Formatter
Config - Configuration struct for output formatting.
- Logger
- Base logger structure for Rasant.
Enums§
- Level
- Log level definition.
- Output
Format - Supported log output format for all sinks.
- Scalar
Scalardefinitions for all log operations. Scalars are the basic data units for Rasant, representing a single type.- Time
Format ntime::Format, re-exported for convenience. Defines a format forTimestampstring serialization.- Value
- Value definition for all log operations.
These are associated with a single
&strkey in attribute maps for Loggers.
Traits§
- Attribute
String Seek - Defines a trait to resolve indexed
AttributeStrings from a container.