A simple async rotation logger library for Rust. It can be safely used across threads by passing a logger instance as an argument or via macros.
Define how log strings and timestamps are formatted:
let formatter = MessageFormatter::new(
"::",
"{timestamp:-6:30:right}{splitter}{modules:_:_:left}{splitter}{message}",
"%Y-%m-%d %H:%M:%S.%f",
);The configuration consists of three parts:
-
Splitter symbol — a character used to separate fields in the log line.
-
Format string — defines the layout of each log line using masks. Each mask (except
splitter) is surrounded by curly braces and supports formatting options separated by:.Available masks:
timestamp— where the timestamp will be printed.splitter— where the splitter character will be inserted.modules— the source modules of the log entry (joined by the splitter).message— the log message itself.
Formatting syntax inside curly braces:
{<mask>:<string_length>:<column_width>:<text_halign>}string_length— limits string length. Positive value trims from the end; negative value trims from the start.column_width— fixed column width. Content is sliced if it doesn't fit.text_halign— horizontal alignment:left,right, orcenter.
Any formatting option can be omitted using
_:{<mask>:_:<column_width>:_} -
Timestamp format — a
chrono-compatible format string used for thetimestampmask.
Choose where logs are written: file, console, or auto (console in debug mode, file in release mode).
let output = OutputChannel::file(
"./".into(),
10,
FileSize::from_megabytes(5),
"new_logger".into(),
"log".into(),
);The first argument enables or disables the logger. When disabled, all log methods remain available but do nothing internally.
let settings = Settings::new(true, 5, output, formatter);A logger instance can be safely .clone()d and passed to other threads.
let logger = Logger::new(settings);
let logger_01 = logger.clone();
let logger_02 = logger.clone();Start the async logger. You can join on its handle or keep another long-lived thread alive.
let joiner = logger.run_async();Pass cloned instances into spawned threads:
let _ = thread::spawn(move || {
logger_02.log(&vec!["THREAD2".into(), "MAIN".into()], "Starting...");
let mut counter = 0;
loop {
logger_02.log(
&vec!["THREAD2".into(), "WORKER".into()],
format!("Processing Job: {counter}").as_str(),
);
counter += 2;
sleep(Duration::from_millis(400));
}
});For a complete example, see Demo.