cli_log/
init.rs

1use {
2    crate::file_logger::FileLogger,
3    log::LevelFilter,
4    std::{
5        env,
6        fs::File,
7        str::FromStr,
8        sync::Mutex,
9    },
10};
11
12/// Configure the application log according to env variable, without failing
13/// in case of io error.
14///
15/// If the log file cannot be created, the error is printed to stderr, then
16/// the application proceeds without logging.
17pub fn init(
18    app_name: &str,
19    app_version: &str,
20) {
21    if let Err(e) = try_init(app_name, app_version) {
22        eprintln!("Failed to initialize log: {}", e);
23    }
24}
25
26/// Configure the application log according to env variable.
27///
28/// If an io error occurs, it is returned, and all logging is disabled
29/// (but there won't be any panic or error on log calls).
30///
31/// The caller can decide to print the error and not, to continue or not.
32pub fn try_init(
33    app_name: &str,
34    app_version: &str,
35) -> std::io::Result<()> {
36    let env_var_name = format!("{}_LOG", app_name.to_ascii_uppercase().replace('-', "_"),);
37    let level = env::var(env_var_name).unwrap_or_else(|_| "off".to_string());
38    if level == "off" {
39        return Ok(());
40    }
41    if let Ok(level) = LevelFilter::from_str(&level) {
42        let log_file_name = format!("{}.log", app_name);
43        let file = File::create(log_file_name)?;
44        log::set_max_level(level);
45        let logger = FileLogger {
46            file: Mutex::new(file),
47            level,
48        };
49        log::set_boxed_logger(Box::new(logger)).unwrap();
50        log::info!(
51            "Starting {} v{} with log level {}",
52            app_name,
53            app_version,
54            level
55        );
56    }
57    Ok(())
58}
59
60/// Configure the application log according to env variable, without failing
61/// in case of io error.
62///
63/// If the log file cannot be created, the error is printed to stderr, then
64/// the application proceeds without logging.
65///
66/// Example:
67///
68/// ```
69/// cli_log::init_cli_log!();
70/// ```
71/// You may specify an altername application name instead
72/// of your crate name:
73///
74/// ```
75/// cli_log::init_cli_log!("my-app");
76/// ```
77///
78/// The application name will also be used to derive the
79/// env variable name giving the log level, for example
80/// `MY_APP_LOG=info` for an application named `my-app`.
81///
82/// The point of using this macro instead of the init function is to ensure
83/// `env!(CARGO_PKG_NAME)` and  `env!(CARGO_PKG_VERSION)` are expanded for
84/// the outer package, not for cli-log
85#[macro_export]
86macro_rules! init_cli_log {
87    () => {
88        cli_log::init(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
89    };
90    ($app_name: expr) => {
91        cli_log::init($app_name, env!("CARGO_PKG_VERSION"));
92    };
93}
94
95/// Configure the application log according to env variable.
96///
97/// If an io error occurs, it is returned, and all logging is disabled
98/// (but there won't be any panic or error on log calls).
99///
100/// The caller can decide to print the error and not, to continue or not.
101///
102/// Example:
103///
104/// ```
105/// cli_log::try_init_cli_log!().expect("Failed to initialize log");
106/// ```
107/// You may specify an altername application name instead
108/// of your crate name:
109///
110/// ```
111/// if Err(e) = cli_log::try_init_cli_log!("my-app") {
112///      eprintln!("Running without log because of error: {}", e);
113/// }
114/// ```
115///
116/// The application name will also be used to derive the
117/// env variable name giving the log level, for example
118/// `MY_APP_LOG=info` for an application named `my-app`.
119///
120/// The point of using this macro instead of the init function is to ensure
121/// `env!(CARGO_PKG_NAME)` and  `env!(CARGO_PKG_VERSION)` are expanded for
122/// the outer package, not for cli-log
123#[macro_export]
124macro_rules! try_init_cli_log {
125    () => {
126        cli_log::try_init(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
127    };
128    ($app_name: expr) => {
129        cli_log::try_init($app_name, env!("CARGO_PKG_VERSION"));
130    };
131}