1
0
mirror of https://github.com/containers/youki synced 2024-11-23 09:21:57 +01:00

make complex loglevel decision easy to understand. (#482)

* make complex loglevel decision easy to understand.

* guard env val for unit tests.

* make some unit tests serial to handle env val.
This commit is contained in:
utam0k 2021-11-28 13:50:46 +09:00 committed by GitHub
parent bb684e8e9c
commit 54cbd15fa8
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23

@ -8,6 +8,8 @@ use std::io::Write;
use std::path::PathBuf;
use std::str::FromStr;
const LOG_LEVEL_ENV_NAME: &str = "YOUKI_LOG_LEVEL";
/// If in debug mode, default level is debug to get maximum logging
#[cfg(debug_assertions)]
const DEFAULT_LOG_LEVEL: &str = "debug";
@ -27,13 +29,7 @@ pub fn init(
log_file: Option<PathBuf>,
log_format: Option<String>,
) -> Result<()> {
let filter: Cow<str> = if log_debug_flag {
"debug".into()
} else if let Ok(level) = std::env::var("YOUKI_LOG_LEVEL") {
level.into()
} else {
DEFAULT_LOG_LEVEL.into()
};
let log_level = detect_log_level(log_debug_flag);
let formatter = match log_format.as_deref() {
None | Some(LOG_FORMAT_TEXT) => text_write,
Some(LOG_FORMAT_JSON) => json_write,
@ -51,7 +47,7 @@ pub fn init(
env_logger::Target::Stderr
};
env_logger::Builder::new()
.filter_level(LevelFilter::from_str(filter.as_ref()).context("failed to parse log level")?)
.filter_level(log_level.context("failed to parse log level")?)
.format(formatter)
.target(target)
.init();
@ -59,6 +55,17 @@ pub fn init(
Ok(())
}
fn detect_log_level(is_debug: bool) -> Result<LevelFilter> {
let filter: Cow<str> = if is_debug {
"debug".into()
} else if let Ok(level) = std::env::var(LOG_LEVEL_ENV_NAME) {
level.into()
} else {
DEFAULT_LOG_LEVEL.into()
};
Ok(LevelFilter::from_str(filter.as_ref())?)
}
fn json_write<F: 'static>(f: &mut F, record: &log::Record) -> std::io::Result<()>
where
F: Write,
@ -93,3 +100,56 @@ where
Ok(())
}
#[cfg(test)]
mod tests {
use serial_test::serial;
use super::*;
use std::env;
struct LogLevelGuard {
original_level: Option<String>,
}
impl LogLevelGuard {
fn new(level: &str) -> Result<Self> {
let original_level = env::var(LOG_LEVEL_ENV_NAME).ok();
env::set_var(LOG_LEVEL_ENV_NAME, level);
Ok(Self { original_level })
}
}
impl Drop for LogLevelGuard {
fn drop(self: &mut LogLevelGuard) {
if let Some(level) = self.original_level.as_ref() {
env::set_var(LOG_LEVEL_ENV_NAME, level);
} else {
env::remove_var(LOG_LEVEL_ENV_NAME);
}
}
}
#[test]
fn test_detect_log_level_is_debug() {
let _guard = LogLevelGuard::new("error").unwrap();
assert_eq!(detect_log_level(true).unwrap(), LevelFilter::Debug)
}
#[test]
#[serial]
fn test_detect_log_level_default() {
let _guard = LogLevelGuard::new("error").unwrap();
env::remove_var(LOG_LEVEL_ENV_NAME);
if cfg!(debug_assertions) {
assert_eq!(detect_log_level(false).unwrap(), LevelFilter::Debug)
} else {
assert_eq!(detect_log_level(false).unwrap(), LevelFilter::Warn)
}
}
#[test]
#[serial]
fn test_detect_log_level_from_env() {
let _guard = LogLevelGuard::new("error").unwrap();
assert_eq!(detect_log_level(false).unwrap(), LevelFilter::Error)
}
}