#[cfg(feature = "env")]
use std::env::var as env_var;
use std::error::Error as StdError;
use std::fmt::Display;
use std::str::FromStr;
pub type CLapLoggerResult<T> = Result<T, Error>;
#[derive(Debug)]
pub enum Error {
NoLogLevelSupplied,
CouldNotParseLogLevel(log::ParseLevelError),
}
#[cfg(feature = "env")]
pub enum EnvLogLevelHandling {
OverwriteDefault(String),
OverwriteArgument(String),
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::NoLogLevelSupplied => write!(f, "No loglevel specified. Please Report."),
Error::CouldNotParseLogLevel(e) => write!(f, "Failed to parse loglevel: {}", e),
}
}
}
impl StdError for Error {}
#[cfg(feature = "env")]
pub enum PrintEnvWarning {
Yes,
No,
}
pub trait ClapInitLogger {
fn init_logger(self) -> CLapLoggerResult<Self>
where
Self: Sized;
fn get_loglevel(&self) -> CLapLoggerResult<log::LevelFilter>;
#[cfg(feature = "env")]
fn init_logger_env(
self,
env_loglevel_handling: EnvLogLevelHandling,
print_hint: PrintEnvWarning,
) -> CLapLoggerResult<Self>
where
Self: Sized;
#[cfg(feature = "env")]
fn get_loglevel_env(
&self,
env_loglevel_handling: EnvLogLevelHandling,
print_env_warning: PrintEnvWarning,
) -> CLapLoggerResult<log::LevelFilter>;
}
impl ClapInitLogger for clap::ArgMatches {
fn init_logger(self) -> CLapLoggerResult<Self> {
env_logger::builder()
.filter_level(self.get_loglevel()?)
.init();
Ok(self)
}
fn get_loglevel(&self) -> CLapLoggerResult<log::LevelFilter> {
let levelfilter = match self.value_of("loglevel") {
Some(r) => r,
None => return Err(Error::NoLogLevelSupplied),
};
match log::LevelFilter::from_str(levelfilter) {
Ok(r) => Ok(r),
Err(e) => Err(Error::CouldNotParseLogLevel(e)), }
}
#[cfg(feature = "env")]
fn init_logger_env(
self,
env_loglevel_handling: EnvLogLevelHandling,
print_hint: PrintEnvWarning,
) -> CLapLoggerResult<Self> {
env_logger::builder()
.filter_level(self.get_loglevel(env_loglevel_handling, print_hint)?)
.init();
Ok(self)
}
#[cfg(feature = "env")]
fn get_loglevel_env(
&self,
env_loglevel_handling: EnvLogLevelHandling,
print_env_warning: PrintEnvWarning,
) -> CLapLoggerResult<log::LevelFilter> {
let loglevel_set: bool = self.occurrences_of("loglevel") > 0;
let loglevel = match log::LevelFilter::from_str(match self.value_of("loglevel") {
Some(r) => r,
None => return Err(Error::NoLogLevelSupplied),
}) {
Ok(r) => r,
Err(e) => {
return Err(Error::CouldNotParseLogLevel(e));
} };
fn print_err(key: &str, value: &str) {
if print_env_warning == PrintEnvWarning::Yes {
println!(
"Invalid Loglevel: {}={}. Using default loglevel ...",
key, value
);
}
}
match env_loglevel_handling {
EnvLogLevelHandling::Ignore => Ok(loglevel),
EnvLogLevelHandling::OverwriteDefault(e) => {
if loglevel_set {
Ok(loglevel)
}
let env: String = env_var(e.as_str()).unwrap_or("".to_string());
log::LevelFilter::from_str(&env).unwrap_or_else({
print_err(&e, &env);
loglevel
})
}
EnvLogLevelHandling::OverwriteArgument(e) => {
let env: String = env_var(e.as_str()).unwrap_or("".to_string());
log::LevelFilter::from_str(&env).unwrap_or_else({
print_err(&e, &env);
loglevel
})
} } } }