mirror of
https://github.com/containers/youki
synced 2024-11-23 17:32:15 +01:00
Cleanup logger implementation
This commit is contained in:
parent
69b5d76fe4
commit
e7d0e90529
@ -1,6 +1,4 @@
|
|||||||
//! Default Youki Logger
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
|
||||||
use log::{LevelFilter, Log, Metadata, Record};
|
use log::{LevelFilter, Log, Metadata, Record};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -11,27 +9,13 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
pub static LOG_FILE: OnceCell<Option<File>> = OnceCell::new();
|
pub static LOG_FILE: OnceCell<Option<File>> = OnceCell::new();
|
||||||
const LOG_LEVEL_ENV_NAME: &str = "YOUKI_INTEGRATION_LOG_LEVEL";
|
const LOG_LEVEL_ENV_NAME: &str = "YOUKI_INTEGRATION_LOG_LEVEL";
|
||||||
const LOG_FORMAT_TEXT: &str = "text";
|
|
||||||
const LOG_FORMAT_JSON: &str = "json";
|
|
||||||
enum LogFormat {
|
|
||||||
Text,
|
|
||||||
Json,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If in debug mode, default level is debug to get maximum logging
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
const DEFAULT_LOG_LEVEL: &str = "debug";
|
|
||||||
|
|
||||||
/// If not in debug mode, default level is warn to get important logs
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
const DEFAULT_LOG_LEVEL: &str = "warn";
|
|
||||||
|
|
||||||
/// Initialize the logger, must be called before accessing the logger
|
/// Initialize the logger, must be called before accessing the logger
|
||||||
/// Multiple parts might call this at once, but the actual initialization
|
/// Multiple parts might call this at once, but the actual initialization
|
||||||
/// is done only once due to use of OnceCell
|
/// is done only once due to use of OnceCell
|
||||||
pub fn init(log_file: Option<PathBuf>, log_format: Option<String>) -> Result<()> {
|
pub fn init(log_file: Option<PathBuf>, debug: bool) -> Result<()> {
|
||||||
let level = detect_log_level(true).context("failed to parse log level")?;
|
let level = detect_log_level(debug).context("failed to parse log level")?;
|
||||||
let format = detect_log_format(log_format).context("failed to detect log format")?;
|
|
||||||
let _ = LOG_FILE.get_or_init(|| -> Option<File> {
|
let _ = LOG_FILE.get_or_init(|| -> Option<File> {
|
||||||
log_file.map(|path| {
|
log_file.map(|path| {
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
@ -43,7 +27,7 @@ pub fn init(log_file: Option<PathBuf>, log_format: Option<String>) -> Result<()>
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let logger = IntegrationLogger::new(level.to_level(), format);
|
let logger = IntegrationLogger::new(level.to_level());
|
||||||
log::set_boxed_logger(Box::new(logger))
|
log::set_boxed_logger(Box::new(logger))
|
||||||
.map(|()| log::set_max_level(level))
|
.map(|()| log::set_max_level(level))
|
||||||
.expect("set logger failed");
|
.expect("set logger failed");
|
||||||
@ -51,35 +35,27 @@ pub fn init(log_file: Option<PathBuf>, log_format: Option<String>) -> Result<()>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detect_log_format(log_format: Option<String>) -> Result<LogFormat> {
|
|
||||||
match log_format.as_deref() {
|
|
||||||
None | Some(LOG_FORMAT_TEXT) => Ok(LogFormat::Text),
|
|
||||||
Some(LOG_FORMAT_JSON) => Ok(LogFormat::Json),
|
|
||||||
Some(unknown) => bail!("unknown log format: {}", unknown),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn detect_log_level(is_debug: bool) -> Result<LevelFilter> {
|
fn detect_log_level(is_debug: bool) -> Result<LevelFilter> {
|
||||||
let filter: Cow<str> = if is_debug {
|
let filter: Cow<str> = if is_debug {
|
||||||
"debug".into()
|
"debug".into()
|
||||||
} else if let Ok(level) = std::env::var(LOG_LEVEL_ENV_NAME) {
|
} else if let Ok(level) = std::env::var(LOG_LEVEL_ENV_NAME) {
|
||||||
level.into()
|
level.into()
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_LOG_LEVEL.into()
|
"off".into()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(LevelFilter::from_str(filter.as_ref())?)
|
Ok(LevelFilter::from_str(filter.as_ref())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IntegrationLogger {
|
struct IntegrationLogger {
|
||||||
/// Indicates level up to which logs are to be printed
|
/// Indicates level up to which logs are to be printed
|
||||||
level: Option<log::Level>,
|
level: Option<log::Level>,
|
||||||
format: LogFormat,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntegrationLogger {
|
impl IntegrationLogger {
|
||||||
/// Create new logger
|
/// Create new logger
|
||||||
pub fn new(level: Option<log::Level>, format: LogFormat) -> Self {
|
pub fn new(level: Option<log::Level>) -> Self {
|
||||||
Self { level, format }
|
Self { level }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,10 +73,7 @@ impl Log for IntegrationLogger {
|
|||||||
/// Function to carry out logging
|
/// Function to carry out logging
|
||||||
fn log(&self, record: &Record) {
|
fn log(&self, record: &Record) {
|
||||||
if self.enabled(record.metadata()) {
|
if self.enabled(record.metadata()) {
|
||||||
let log_msg = match self.format {
|
let log_msg =text_format(record);
|
||||||
LogFormat::Text => text_format(record),
|
|
||||||
LogFormat::Json => json_format(record),
|
|
||||||
};
|
|
||||||
// if log file is set, write to it, else write to stderr
|
// if log file is set, write to it, else write to stderr
|
||||||
if let Some(mut log_file) = LOG_FILE.get().unwrap().as_ref() {
|
if let Some(mut log_file) = LOG_FILE.get().unwrap().as_ref() {
|
||||||
let _ = writeln!(log_file, "{}", log_msg);
|
let _ = writeln!(log_file, "{}", log_msg);
|
||||||
@ -120,15 +93,6 @@ impl Log for IntegrationLogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_format(record: &log::Record) -> String {
|
|
||||||
serde_json::to_string(&serde_json::json!({
|
|
||||||
"level": record.level().to_string(),
|
|
||||||
"time": chrono::Local::now().to_rfc3339(),
|
|
||||||
"message": record.args(),
|
|
||||||
}))
|
|
||||||
.expect("serde::to_string with string keys will not fail")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn text_format(record: &log::Record) -> String {
|
fn text_format(record: &log::Record) -> String {
|
||||||
let log_msg = match (record.file(), record.line()) {
|
let log_msg = match (record.file(), record.line()) {
|
||||||
(Some(file), Some(line)) => format!(
|
(Some(file), Some(line)) => format!(
|
||||||
|
@ -17,14 +17,20 @@ use tests::cgroups;
|
|||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(version = "0.0.1", author = "youki team")]
|
#[clap(version = "0.0.1", author = "youki team")]
|
||||||
struct Opts {
|
struct Opts {
|
||||||
/// path for the container runtime to be tested
|
/// Path for the container runtime to be tested
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
runtime: PathBuf,
|
runtime: PathBuf,
|
||||||
/// selected tests to be run, format should be
|
/// Selected tests to be run, format should be
|
||||||
/// space separated groups, eg
|
/// space separated groups, eg
|
||||||
/// -t group1::test1,test3 group2 group3::test5
|
/// -t group1::test1,test3 group2 group3::test5
|
||||||
#[clap(short, long, multiple_values = true, value_delimiter = ' ')]
|
#[clap(short, long, multiple_values = true, value_delimiter = ' ')]
|
||||||
tests: Option<Vec<String>>,
|
tests: Option<Vec<String>>,
|
||||||
|
/// Enables debug output
|
||||||
|
#[clap(short, long)]
|
||||||
|
debug: bool,
|
||||||
|
/// Logs to the specified file
|
||||||
|
#[clap(long)]
|
||||||
|
log: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse test string given in commandline option as pair of testgroup name and tests belonging to that
|
// parse test string given in commandline option as pair of testgroup name and tests belonging to that
|
||||||
@ -45,7 +51,7 @@ fn parse_tests(tests: &[String]) -> Vec<(&str, Option<Vec<&str>>)> {
|
|||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let opts: Opts = Opts::parse();
|
let opts: Opts = Opts::parse();
|
||||||
|
|
||||||
if let Err(e) = logger::init(None, None) {
|
if let Err(e) = logger::init(opts.log, opts.debug) {
|
||||||
eprintln!("logger could not be initialized: {:?}", e);
|
eprintln!("logger could not be initialized: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user