#logging #log-file #log #log-level #log-error #log-debug #debugging-logging

ftail

Ftail is simple logging implementation for the log crate with support for multiple drivers

3 releases

0.1.2 Sep 17, 2024
0.1.1 Sep 14, 2024
0.1.0 Sep 13, 2024

#189 in Debugging

Download history 244/week @ 2024-09-09 235/week @ 2024-09-16 59/week @ 2024-09-23 24/week @ 2024-09-30 18/week @ 2024-10-07 46/week @ 2024-10-14 14/week @ 2024-10-28 12/week @ 2024-11-04

73 downloads per month

MIT license

48KB
1K SLoC

Ftail

Ftail is simple logging implementation for the log crate with support for multiple drivers.

Usage

Add the following dependencies to your Cargo.toml file:

[dependencies]
ftail = "0.1"

Add the following code to your main.rs or lib.rs file:

use ftail::Ftail;
use log::LevelFilter;

Ftail::new()
    .console(LevelFilter::Debug)
    .daily_file("logs", LevelFilter::Error)
    .init()?;

// log messages anywhere in your code
log::trace!("This is a trace message");
log::debug!("This is a debug message");
log::info!(target: "foo", "bar");
log::warn!("This is a warning message");
log::error!("This is an error message");

You can set the following configuration options:

  • .datetime_format("%Y-%m-%d %H:%M:%S.3f") to set the datetime format
  • .timezone(ftail::Tz::UTC) to set the timezone [requires feature timezone]
  • .max_file_size(100) to set the maximum file size in MB (will move older logs to .old{N})
  • .filter_levels(vec![Level::Debug, Level::Error]) only log messages with the specified levels
  • .filter_targets(vec!["foo", "bar"]) only log messages with the specified targets

Drivers

Console

Logs to the standard output without any formatting.

The stdout driver takes the following parameters:

  • level: the minumum log level to log
Ftail::new()
    .console(LevelFilter::Trace)
    .init()?;
13-09-2024 17:35:18 TRACE console This is a trace message
13-09-2024 17:35:18 DEBUG console This is a debug message
13-09-2024 17:35:18 INFO foo bar
13-09-2024 17:35:18 WARN console This is a warning message
13-09-2024 17:35:18 ERROR console This is an error message

Formatted Console

Logs to the standard output with formatted and colored output.

The console driver takes the following parameters:

  • level: the minumum log level to log
Ftail::new()
    .formatted_console(LevelFilter::Trace)
    .init()?;
2024-09-13 17:35:37 · TRACE
This is a trace message
examples\formatted_console\src/main.rs:9

2024-09-13 17:35:37 · DEBUG
This is a debug message
examples\formatted_console\src/main.rs:11

2024-09-13 17:35:37 · INFO
bar
examples\formatted_console\src/main.rs:13

2024-09-13 17:35:37 · WARN
This is a warning message
examples\formatted_console\src/main.rs:15

2024-09-13 17:35:37 · ERROR
This is an error message
examples\formatted_console\src/main.rs:17

Single file

Logs to the single log file logs/demo.log.

The single_file driver takes the following parameters:

  • path: the path to the log file
  • append: whether to append to the log file or overwrite it
  • level: the minumum log level to log
Ftail::new()
    .single_file("logs/demo.log", true, LevelFilter::Trace)
    .init()?;

Daily file

Logs to a daily log file in the logs directory. The log files have the following format: YYYY-MM-DD.log.

The daily_file driver takes the following parameters:

  • dir: the directory to store the log files
  • level: the minumum log level to log
Ftail::new()
    .daily_file("logs", LevelFilter::Trace)
    .init()?;

Custom driver

Create your own log driver.

Ftail::new()
    .custom(
        |config: ftail::Config| Box::new(CustomLogger { config }) as Box<dyn Log + Send + Sync>,
        LevelFilter::Debug,
    )
    .datetime_format("%H:%M:%S%.3f")
    .init()?;

// the custom logger implementation
struct CustomLogger {
    config: Config,
}

impl Log for CustomLogger {
    fn enabled(&self, metadata: &log::Metadata) -> bool {
        if self.config.level_filter == LevelFilter::Off {
            return true;
        }

        metadata.level() <= self.config.level_filter
    }

    fn log(&self, record: &log::Record) {
        if !self.enabled(record.metadata()) {
            return;
        }

        let time = chrono::Local::now()
            .format(&self.config.datetime_format)
            .to_string();

        println!("{} [{}] {}", time.black(), record.level().bold(), record.args());
    }

    fn flush(&self) {}
}
19:37:22.402 [DEBUG] This is a debug message
19:37:22.403 [INFO] bar
19:37:22.403 [WARN] This is a warning message
19:37:22.403 [ERROR] This is an error message

Dependencies

~1–1.4MB
~21K SLoC