ptero/log.rs
1use colored::Colorize;
2use fern::{
3 colors::{Color, ColoredLevelConfig},
4 Dispatch,
5};
6use log::{Level, LevelFilter};
7/// Converts verbosity number to [LevelFilter](log::LevelFilter) enum.
8/// Used for configuring the logging level.
9/// # Arguments
10///
11/// * `verbosity` - verbosity level described by number `u8`
12///
13/// # Examples
14/// ## Converts verbosity number
15/// ```
16/// use ptero::log::verbosity_to_level_filter;
17/// use log::{LevelFilter};
18///
19/// assert_eq!(verbosity_to_level_filter(0), LevelFilter::Off);
20/// assert_eq!(verbosity_to_level_filter(1), LevelFilter::Warn);
21/// assert_eq!(verbosity_to_level_filter(2), LevelFilter::Info);
22/// assert_eq!(verbosity_to_level_filter(3), LevelFilter::Debug);
23/// ```
24/// ## Unrecognized verbosity defaults to trace
25/// ```
26/// use ptero::log::verbosity_to_level_filter;
27/// use log::{LevelFilter};
28///
29/// assert_eq!(verbosity_to_level_filter(4), LevelFilter::Trace);
30/// assert_eq!(verbosity_to_level_filter(100), LevelFilter::Trace);
31/// assert_eq!(verbosity_to_level_filter(255), LevelFilter::Trace);
32/// ```
33pub fn verbosity_to_level_filter(verbosity: u8) -> LevelFilter {
34 match verbosity {
35 0 => LevelFilter::Off,
36 1 => LevelFilter::Warn,
37 2 => LevelFilter::Info,
38 3 => LevelFilter::Debug,
39 _ => LevelFilter::Trace,
40 }
41}
42
43/// Returns pre-configured [ColoredLevelConfig](fern::colors::ColoredLevelConfig) used to color
44/// logging level.
45fn get_logging_colors() -> ColoredLevelConfig {
46 ColoredLevelConfig::new()
47 .error(Color::Red)
48 .warn(Color::BrightYellow)
49 .debug(Color::Magenta)
50 .trace(Color::BrightBlack)
51}
52
53/// Returns text which will be shown before the message. Used only in stdout formatter.
54fn get_level_text(level: &Level) -> &str {
55 match level {
56 Level::Error => "ERROR",
57 Level::Warn => " WARN",
58 Level::Info => " INFO",
59 Level::Debug => "DEBUG",
60 Level::Trace => "TRACE",
61 }
62}
63
64/// Returns pre-configured stdout logger.
65/// It only shows info relevant to user like message and logging level.
66/// Uses coloring unlike file logger.
67///
68/// # Arguments
69/// * `log_level` - level filter which is used to restrict amount of logs to user
70pub fn get_stdout_logger() -> Dispatch {
71 let colors = get_logging_colors();
72
73 fern::Dispatch::new()
74 .format(move |out, message, record| {
75 out.finish(format_args!(
76 "{color_line}{level_txt}\x1B[0m [{module}]: {message}",
77 level_txt = get_level_text(&record.level()),
78 color_line =
79 format_args!("\x1B[{}m", colors.get_color(&record.level()).to_fg_str()),
80 message = message,
81 module = &record.target().dimmed(),
82 ));
83 })
84 .chain(std::io::stderr())
85}
86
87/// Returns pre-configured file logger.
88/// This logger does not used coloring and adds additional info like date time or module path.
89/// It doesn't restrict logging - saves everything beginning from `TRACE` level.
90///
91/// # Arguments
92/// * `log_path` - path to the log file which will be used to store logs
93pub fn get_file_logger(log_path: &str) -> Dispatch {
94 fern::Dispatch::new()
95 .format(move |out, message, record| {
96 out.finish(format_args!(
97 "{}[{}][{}] - {}",
98 chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
99 &record.target(),
100 &record.level(),
101 message,
102 ));
103 })
104 .chain(fern::log_file(&log_path).unwrap())
105}