Skip to content

Commit

Permalink
feat: Implement conversion for level types
Browse files Browse the repository at this point in the history
Implement `From<Verbosity>` for `LevelFilter` and `Option<Level>` for
both `log` and `tracing` crates.

This makes it possible to just directly set the log filter:

E.g.:
```rust
env_logger::Builder::new().filter_level(cli.verbosity.into()).init();
// or
tracing_subscriber::fmt().with_max_level(cli.verbosity).init();
```
  • Loading branch information
joshka committed Nov 26, 2024
1 parent 02d8ea5 commit 3b7b26c
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 6 deletions.
4 changes: 2 additions & 2 deletions examples/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use clap_verbosity_flag::Verbosity;
#[derive(Debug, Parser)]
struct Cli {
#[command(flatten)]
verbose: Verbosity,
verbosity: Verbosity,
}

fn main() {
let cli = Cli::parse();

env_logger::Builder::new()
.filter_level(cli.verbose.log_level_filter())
.filter_level(cli.verbosity.into())
.init();

log::error!("Engines exploded");
Expand Down
4 changes: 2 additions & 2 deletions examples/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use clap_verbosity_flag::Verbosity;
#[derive(Debug, Parser)]
struct Cli {
#[command(flatten)]
verbose: Verbosity,
verbosity: Verbosity,
}

fn main() {
let cli = Cli::parse();

tracing_subscriber::fmt()
.with_max_level(cli.verbose.tracing_level_filter())
.with_max_level(cli.verbosity)
.init();

tracing::error!("Engines exploded");
Expand Down
56 changes: 55 additions & 1 deletion src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// information.
pub use log::{Level, LevelFilter};

use crate::VerbosityFilter;
use crate::{LogLevel, Verbosity, VerbosityFilter};

impl From<VerbosityFilter> for LevelFilter {
fn from(filter: VerbosityFilter) -> Self {
Expand Down Expand Up @@ -57,6 +57,18 @@ impl From<Option<Level>> for VerbosityFilter {
}
}

impl<L: LogLevel> From<Verbosity<L>> for LevelFilter {
fn from(v: Verbosity<L>) -> Self {
v.log_level_filter()
}
}

impl<L: LogLevel> From<Verbosity<L>> for Option<Level> {
fn from(v: Verbosity<L>) -> Self {
v.log_level()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -88,4 +100,46 @@ mod tests {
assert_eq!(v.log_level(), Some(Level::Trace));
assert_eq!(v.log_level_filter(), LevelFilter::Trace);
}

#[test]
fn into_opt_level() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(Option::<Level>::from(v), None);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::Error));

let v = Verbosity::<WarnLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::Warn));

let v = Verbosity::<InfoLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::Info));

let v = Verbosity::<DebugLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::Debug));

let v = Verbosity::<TraceLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::Trace));
}

#[test]
fn into_level_filter() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::Off);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::Error);

let v = Verbosity::<WarnLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::Warn);

let v = Verbosity::<InfoLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::Info);

let v = Verbosity::<DebugLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::Debug);

let v = Verbosity::<TraceLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::Trace);
}
}
56 changes: 55 additions & 1 deletion src/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// more information.
pub use tracing_core::{Level, LevelFilter};

use crate::VerbosityFilter;
use crate::{LogLevel, Verbosity, VerbosityFilter};

impl From<VerbosityFilter> for LevelFilter {
fn from(filter: VerbosityFilter) -> Self {
Expand Down Expand Up @@ -57,6 +57,18 @@ impl From<Option<Level>> for VerbosityFilter {
}
}

impl<L: LogLevel> From<Verbosity<L>> for LevelFilter {
fn from(v: Verbosity<L>) -> Self {
v.tracing_level_filter()
}
}

impl<L: LogLevel> From<Verbosity<L>> for Option<Level> {
fn from(v: Verbosity<L>) -> Self {
v.tracing_level()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -88,4 +100,46 @@ mod tests {
assert_eq!(v.tracing_level(), Some(Level::TRACE));
assert_eq!(v.tracing_level_filter(), LevelFilter::TRACE);
}

#[test]
fn into_opt_level() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(Option::<Level>::from(v), None);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::ERROR));

let v = Verbosity::<WarnLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::WARN));

let v = Verbosity::<InfoLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::INFO));

let v = Verbosity::<DebugLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::DEBUG));

let v = Verbosity::<TraceLevel>::default();
assert_eq!(Option::<Level>::from(v), Some(Level::TRACE));
}

#[test]
fn into_level_filter() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::OFF);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::ERROR);

let v = Verbosity::<WarnLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::WARN);

let v = Verbosity::<InfoLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::INFO);

let v = Verbosity::<DebugLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::DEBUG);

let v = Verbosity::<TraceLevel>::default();
assert_eq!(LevelFilter::from(v), LevelFilter::TRACE);
}
}

0 comments on commit 3b7b26c

Please sign in to comment.