rapx/utils/
log.rs

1use chrono::Local;
2use fern::colors::{Color, ColoredLevelConfig};
3use fern::{self, Dispatch};
4use log::LevelFilter;
5
6fn log_level() -> LevelFilter {
7    if let Ok(s) = std::env::var("RAPX_LOG") {
8        match s.parse() {
9            Ok(level) => return level,
10            Err(err) => eprintln!("RAPX_LOG is invalid: {err}"),
11        }
12    }
13    LevelFilter::Info
14}
15
16/// Detect `RAPX_LOG` environment variable first; if it's not set,
17/// default to INFO level.
18pub fn init_log() -> Result<(), fern::InitError> {
19    let dispatch = Dispatch::new().level(log_level());
20
21    let color_line = ColoredLevelConfig::new()
22        .error(Color::Red)
23        .warn(Color::Yellow)
24        .info(Color::White)
25        .debug(Color::Blue)
26        .trace(Color::Cyan);
27
28    let color_level = color_line.info(Color::Green);
29    let stderr_dispatch = Dispatch::new()
30        .format(move |callback, args, record| {
31            let now = Local::now();
32            callback.finish(format_args!(
33                "{}{}|RAPx|{}{}|: {}\x1B[0m",
34                format_args!(
35                    "\x1B[{}m",
36                    color_line.get_color(&record.level()).to_fg_str()
37                ),
38                now.format("%H:%M:%S"),
39                color_level.color(record.level()),
40                format_args!(
41                    "\x1B[{}m",
42                    color_line.get_color(&record.level()).to_fg_str()
43                ),
44                args
45            ))
46        })
47        .chain(std::io::stderr());
48
49    /* Note that we cannot dispatch to stdout due to some bugs */
50    dispatch.chain(stderr_dispatch).apply()?;
51    Ok(())
52}
53
54#[macro_export]
55macro_rules! rap_trace {
56    ($($arg:tt)+) => (
57        ::log::trace!(target: "RAPx", $($arg)+)
58    );
59}
60
61#[macro_export]
62macro_rules! rap_debug {
63    ($($arg:tt)+) => (
64        ::log::debug!(target: "RAPx", $($arg)+)
65    );
66}
67
68#[macro_export]
69macro_rules! rap_info {
70    (green, $($arg:tt)+) => (
71        ::log::info!(target: "RAPx", "\x1B[32m{}\x1B[0m", format_args!($($arg)+))
72    );
73    (yellow, $($arg:tt)+) => (
74        ::log::info!(target: "RAPx", "\x1B[33m{}\x1B[0m", format_args!($($arg)+))
75    );
76    (red, $($arg:tt)+) => (
77        ::log::info!(target: "RAPx", "\x1B[31m{}\x1B[0m", format_args!($($arg)+))
78    );
79    ($($arg:tt)+) => (
80        ::log::info!(target: "RAPx", $($arg)+)
81    );
82}
83
84#[macro_export]
85macro_rules! rap_warn {
86    (green, $($arg:tt)+) => (
87        ::log::warn!(target: "RAPx", "\x1B[32m{}\x1B[0m", format_args!($($arg)+))
88    );
89    (yellow, $($arg:tt)+) => (
90        ::log::warn!(target: "RAPx", "\x1B[33m{}\x1B[0m", format_args!($($arg)+))
91    );
92    (red, $($arg:tt)+) => (
93        ::log::warn!(target: "RAPx", "\x1B[31m{}\x1B[0m", format_args!($($arg)+))
94    );
95    ($($arg:tt)+) => (
96        ::log::warn!(target: "RAPx", $($arg)+)
97    );
98}
99
100#[macro_export]
101macro_rules! rap_error {
102    (green, $($arg:tt)+) => (
103        ::log::error!(target: "RAPx", "\x1B[32m{}\x1B[0m", format_args!($($arg)+))
104    );
105    (yellow, $($arg:tt)+) => (
106        ::log::error!(target: "RAPx", "\x1B[33m{}\x1B[0m", format_args!($($arg)+))
107    );
108    (red, $($arg:tt)+) => (
109        ::log::error!(target: "RAPx", "\x1B[31m{}\x1B[0m", format_args!($($arg)+))
110    );
111    ($($arg:tt)+) => (
112        ::log::error!(target: "RAPx", $($arg)+)
113    );
114}
115
116pub fn rap_error_and_exit(msg: impl AsRef<str>) -> ! {
117    rap_error!("{}", msg.as_ref());
118    std::process::exit(1)
119}
120
121// Re-export span utilities so existing imports from utils::log keep working.
122pub use super::span::*;