Skip to content

Commit

Permalink
feat: Add support for tracing crate
Browse files Browse the repository at this point in the history
It is no longer necessary to have to depend on both log and tracing-log
to use clap-verbosity-flag with the tracing crate. This commit adds
support for the tracing crate directly.

- Add `tracing-core` as a dependency
- Add `tracing` as a feature
- Add `tracing` module
- Remove `tracing-log` as a dependency for the `tracing` example
  • Loading branch information
joshka committed Nov 18, 2024
1 parent 61c1bc6 commit 53b0316
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,18 @@ codecov = { repository = "clap-rs/clap-verbosity-flag" }
[features]
default = ["log"]
log = ["dep:log"]
tracing = ["dep:tracing-core"]

[dependencies]
log = { version = "0.4.1", optional = true }
clap = { version = "4.0.0", default-features = false, features = ["std", "derive"] }
log = { version = "0.4.1", optional = true }
tracing-core = { version = "0.1", optional = true }

[dev-dependencies]
clap = { version = "4.5.4", default-features = false, features = ["help", "usage"] }
env_logger = "0.11.3"
tracing = "0.1"
tracing-subscriber = "0.3"
tracing-log = "0.2"

[lints]
workspace = true
Expand All @@ -141,4 +142,4 @@ required-features = ["log"]

[[example]]
name = "tracing"
required-features = ["log"]
required-features = ["tracing"]
3 changes: 1 addition & 2 deletions examples/tracing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use clap::Parser;
use clap_verbosity_flag::Verbosity;
use tracing_log::AsTrace;

/// Foo
#[derive(Debug, Parser)]
Expand All @@ -13,7 +12,7 @@ fn main() {
let cli = Cli::parse();

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

tracing::error!("Engines exploded");
Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ use std::fmt;

#[cfg(feature = "log")]
pub mod log;
#[cfg(feature = "tracing")]
pub mod tracing;

/// Logging flags to `#[command(flatten)]` into your CLI
#[derive(clap::Args, Debug, Clone, Default)]
Expand Down Expand Up @@ -139,6 +141,21 @@ impl<L: LogLevel> Verbosity<L> {
}
}

#[cfg(feature = "tracing")]
impl<L: LogLevel> Verbosity<L> {
/// Get the tracing level.
///
/// `None` means all output is disabled.
pub fn tracing_level(&self) -> Option<tracing_core::Level> {
self.filter().into()
}

/// Get the tracing level filter.
pub fn tracing_level_filter(&self) -> tracing_core::LevelFilter {
self.filter().into()
}
}

impl<L: LogLevel> fmt::Display for Verbosity<L> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.filter().fmt(f)
Expand Down
91 changes: 91 additions & 0 deletions src/tracing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// These re-exports of the tracing crate types it easy to use this crate without having to depend on
// the tracing crate directly. See <https://github.com/clap-rs/clap-verbosity-flag/issues/54> for
// more information.
pub use tracing_core::{Level, LevelFilter};

use crate::VerbosityFilter;

impl From<VerbosityFilter> for LevelFilter {
fn from(filter: VerbosityFilter) -> Self {
match filter {
VerbosityFilter::Off => LevelFilter::OFF,
VerbosityFilter::Error => LevelFilter::ERROR,
VerbosityFilter::Warn => LevelFilter::WARN,
VerbosityFilter::Info => LevelFilter::INFO,
VerbosityFilter::Debug => LevelFilter::DEBUG,
VerbosityFilter::Trace => LevelFilter::TRACE,
}
}
}

impl From<LevelFilter> for VerbosityFilter {
fn from(level: LevelFilter) -> Self {
match level {
LevelFilter::OFF => Self::Off,
LevelFilter::ERROR => Self::Error,
LevelFilter::WARN => Self::Warn,
LevelFilter::INFO => Self::Info,
LevelFilter::DEBUG => Self::Debug,
LevelFilter::TRACE => Self::Trace,
}
}
}

impl From<VerbosityFilter> for Option<Level> {
fn from(filter: VerbosityFilter) -> Self {
match filter {
VerbosityFilter::Off => None,
VerbosityFilter::Error => Some(Level::ERROR),
VerbosityFilter::Warn => Some(Level::WARN),
VerbosityFilter::Info => Some(Level::INFO),
VerbosityFilter::Debug => Some(Level::DEBUG),
VerbosityFilter::Trace => Some(Level::TRACE),
}
}
}

impl From<Option<Level>> for VerbosityFilter {
fn from(level: Option<Level>) -> Self {
match level {
None => Self::Off,
Some(Level::ERROR) => Self::Error,
Some(Level::WARN) => Self::Warn,
Some(Level::INFO) => Self::Info,
Some(Level::DEBUG) => Self::Debug,
Some(Level::TRACE) => Self::Trace,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{DebugLevel, ErrorLevel, InfoLevel, OffLevel, TraceLevel, Verbosity, WarnLevel};

#[test]
fn tracing_level() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(v.tracing_level(), None);
assert_eq!(v.tracing_level_filter(), LevelFilter::OFF);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(v.tracing_level(), Some(Level::ERROR));
assert_eq!(v.tracing_level_filter(), LevelFilter::ERROR);

let v = Verbosity::<WarnLevel>::default();
assert_eq!(v.tracing_level(), Some(Level::WARN));
assert_eq!(v.tracing_level_filter(), LevelFilter::WARN);

let v = Verbosity::<InfoLevel>::default();
assert_eq!(v.tracing_level(), Some(Level::INFO));
assert_eq!(v.tracing_level_filter(), LevelFilter::INFO);

let v = Verbosity::<DebugLevel>::default();
assert_eq!(v.tracing_level(), Some(Level::DEBUG));
assert_eq!(v.tracing_level_filter(), LevelFilter::DEBUG);

let v = Verbosity::<TraceLevel>::default();
assert_eq!(v.tracing_level(), Some(Level::TRACE));
assert_eq!(v.tracing_level_filter(), LevelFilter::TRACE);
}
}

0 comments on commit 53b0316

Please sign in to comment.