use crate::error::Error; use env_logger::Builder; use log::LevelFilter; use syslog::Facility; pub const DEFAULT_LOG_SYSTEM: LogSystem = LogSystem::SysLog; pub const DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::Warn; #[derive(Debug, PartialEq, Eq)] pub enum LogSystem { SysLog, StdErr, } fn get_loglevel(log_level: Option<&str>) -> Result { let level = match log_level { Some(v) => match v { "error" => LevelFilter::Error, "warn" => LevelFilter::Warn, "info" => LevelFilter::Info, "debug" => LevelFilter::Debug, "trace" => LevelFilter::Trace, _ => { return Err(format!("{}: invalid log level", v).into()); } }, None => DEFAULT_LOG_LEVEL, }; Ok(level) } fn set_log_syslog(log_level: LevelFilter) -> Result<(), Error> { syslog::init( Facility::LOG_DAEMON, log_level, Some(env!("CARGO_PKG_NAME")), )?; Ok(()) } fn set_log_stderr(log_level: LevelFilter) -> Result<(), Error> { let mut builder = Builder::from_env("ACMED_LOG_LEVEL"); builder.filter_level(log_level); builder.init(); Ok(()) } pub fn set_log_system( log_level: Option<&str>, has_syslog: bool, has_stderr: bool, ) -> Result<(LogSystem, LevelFilter), Error> { let log_level = get_loglevel(log_level)?; let logtype = if has_syslog { LogSystem::SysLog } else if has_stderr { LogSystem::StdErr } else { DEFAULT_LOG_SYSTEM }; match logtype { LogSystem::SysLog => set_log_syslog(log_level)?, LogSystem::StdErr => set_log_stderr(log_level)?, }; Ok((logtype, log_level)) } #[cfg(test)] mod tests { use super::{set_log_system, DEFAULT_LOG_LEVEL, DEFAULT_LOG_SYSTEM}; #[test] fn test_invalid_level() { let ret = set_log_system(Some("invalid"), false, false); assert!(ret.is_err()); } #[test] fn test_default_values() { let ret = set_log_system(None, false, false); assert!(ret.is_ok()); let (logtype, log_level) = ret.unwrap(); assert_eq!(logtype, DEFAULT_LOG_SYSTEM); assert_eq!(log_level, DEFAULT_LOG_LEVEL); } }