Skip to content

Commit

Permalink
Move everything up into lib and generically implement the Option<Leve…
Browse files Browse the repository at this point in the history
…l> call

Use macros to reduce repetition in impls
  • Loading branch information
joshka committed Nov 14, 2024
1 parent dddcca0 commit b56d5c0
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 134 deletions.
14 changes: 11 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub struct Verbosity<L: LogLevel = ErrorLevel> {
impl<L: LogLevel> Verbosity<L>
where
VerbosityFilter: From<L::LevelFilter>,
<L as LogLevel>::LevelFilter: From<VerbosityFilter>,
Option<<L as LogLevel>::Level>: From<VerbosityFilter>,
{
/// Create a new verbosity instance by explicitly setting the values
pub fn new(verbose: u8, quiet: u8) -> Self {
Expand Down Expand Up @@ -141,12 +141,19 @@ where
.with_offset(self.verbosity_offset())
.into()
}

/// Get the log level.
///
/// `None` means all output is disabled.
pub fn log_level(&self) -> Option<L::Level> {
self.verbosity_filter().into()
}
}

impl<L: LogLevel> fmt::Display for Verbosity<L>
where
VerbosityFilter: From<L::LevelFilter>,
<L as LogLevel>::LevelFilter: From<VerbosityFilter>,
Option<<L as LogLevel>::Level>: From<VerbosityFilter>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.verbosity_filter())
Expand All @@ -155,7 +162,8 @@ where

/// Customize the default log-level and associated help
pub trait LogLevel {
type LevelFilter;
type LevelFilter: From<VerbosityFilter> + Into<VerbosityFilter>;
type Level;

/// Baseline level filter before applying `--verbose` and `--quiet`
fn default() -> Self::LevelFilter;
Expand Down
112 changes: 45 additions & 67 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
pub use log::Level;
pub use log::LevelFilter;
use log::{Level, LevelFilter};

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

impl<L: LogLevel<LevelFilter = LevelFilter>> Verbosity<L> {
/// Get the log level.
///
/// `None` means all output is disabled.
pub fn log_level(&self) -> Option<Level> {
self.log_level_filter().to_level()
}
}
use crate::{LogLevel, VerbosityFilter};

impl From<VerbosityFilter> for LevelFilter {
fn from(verbosity: VerbosityFilter) -> Self {
Expand All @@ -24,6 +14,7 @@ impl From<VerbosityFilter> for LevelFilter {
}
}
}

impl From<LevelFilter> for VerbosityFilter {
fn from(level: LevelFilter) -> Self {
match level {
Expand All @@ -37,68 +28,55 @@ impl From<LevelFilter> for VerbosityFilter {
}
}

/// Default to [`log::Level::Error`]
#[derive(Copy, Clone, Debug, Default)]
pub struct ErrorLevel;

impl LogLevel for ErrorLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::Error
}
}

/// Default to [`log::Level::Warn`]
#[derive(Copy, Clone, Debug, Default)]
pub struct WarnLevel;

impl LogLevel for WarnLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::Warn
}
}

/// Default to [`log::Level::Info`]
#[derive(Copy, Clone, Debug, Default)]
pub struct InfoLevel;

impl LogLevel for InfoLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::Info
impl From<VerbosityFilter> for Option<Level> {
fn from(verbosity: VerbosityFilter) -> Self {
match verbosity {
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),
}
}
}

/// Default to [`log::Level::Debug`]
#[derive(Copy, Clone, Debug, Default)]
pub struct DebugLevel;

impl LogLevel for DebugLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::Debug
impl From<Option<Level>> for VerbosityFilter {
fn from(level: Option<Level>) -> Self {
match level {
None => VerbosityFilter::Off,
Some(Level::Error) => VerbosityFilter::Error,
Some(Level::Warn) => VerbosityFilter::Warn,
Some(Level::Info) => VerbosityFilter::Info,
Some(Level::Debug) => VerbosityFilter::Debug,
Some(Level::Trace) => VerbosityFilter::Trace,
}
}
}

/// Default to [`log::Level::Trace`]
#[derive(Copy, Clone, Debug, Default)]
pub struct TraceLevel;
macro_rules! log_levels {
($($name:ident $level:ident,)*) => {
$(
#[doc = concat!("Log level that sets the default filter to [`log::LevelFilter::", stringify!($level), "`].")]
#[derive(Copy, Clone, Debug, Default)]
pub struct $name;

impl LogLevel for TraceLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::Trace
}
impl LogLevel for $name {
type LevelFilter = LevelFilter;
type Level = Level;
fn default() -> Self::LevelFilter {
LevelFilter::$level
}
}
)*
};
}

/// Default to no logging (i.e. `None` or [`log::LevelFilter::Off`])
#[derive(Copy, Clone, Debug, Default)]
pub struct OffLevel;

impl LogLevel for OffLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::Off
}
log_levels! {
ErrorLevel Error,
WarnLevel Warn,
InfoLevel Info,
DebugLevel Debug,
TraceLevel Trace,
OffLevel Off,
}
107 changes: 43 additions & 64 deletions src/tracing.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
use crate::{LogLevel, Verbosity, VerbosityFilter};
use tracing_core::{Level, LevelFilter};

impl<L: LogLevel<LevelFilter = LevelFilter>> Verbosity<L> {
/// Get the level.
///
/// `None` means all output is disabled.
pub fn tracing_level(&self) -> Option<Level> {
self.log_level_filter().into()
}
}
use crate::{LogLevel, VerbosityFilter};

impl From<VerbosityFilter> for LevelFilter {
fn from(verbosity: VerbosityFilter) -> Self {
Expand Down Expand Up @@ -36,68 +28,55 @@ impl From<LevelFilter> for VerbosityFilter {
}
}

/// Default to [`log::Level::Error`]
#[derive(Copy, Clone, Debug, Default)]
pub struct ErrorLevel;

impl LogLevel for ErrorLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::ERROR
}
}

/// Default to [`log::Level::Warn`]
#[derive(Copy, Clone, Debug, Default)]
pub struct WarnLevel;

impl LogLevel for WarnLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::WARN
}
}

/// Default to [`log::Level::Info`]
#[derive(Copy, Clone, Debug, Default)]
pub struct InfoLevel;

impl LogLevel for InfoLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::INFO
impl From<VerbosityFilter> for Option<Level> {
fn from(verbosity: VerbosityFilter) -> Self {
match verbosity {
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),
}
}
}

/// Default to [`log::Level::Debug`]
#[derive(Copy, Clone, Debug, Default)]
pub struct DebugLevel;

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

/// Default to [`log::Level::Trace`]
#[derive(Copy, Clone, Debug, Default)]
pub struct TraceLevel;
macro_rules! log_levels {
($($name:ident $level:ident,)*) => {
$(
#[doc = concat!("Log level that sets the default filter to [`tracing_core::LevelFilter::", stringify!($level), "`].")]
#[derive(Copy, Clone, Debug, Default)]
pub struct $name;

impl LogLevel for TraceLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::TRACE
}
impl LogLevel for $name {
type LevelFilter = LevelFilter;
type Level = Level;
fn default() -> Self::LevelFilter {
LevelFilter::$level
}
}
)*
};
}

/// Default to no logging (i.e. `None` or [`log::LevelFilter::Off`])
#[derive(Copy, Clone, Debug, Default)]
pub struct OffLevel;

impl LogLevel for OffLevel {
type LevelFilter = LevelFilter;
fn default() -> Self::LevelFilter {
LevelFilter::OFF
}
log_levels! {
ErrorLevel ERROR,
WarnLevel WARN,
InfoLevel INFO,
DebugLevel DEBUG,
TraceLevel TRACE,
OffLevel OFF,
}

0 comments on commit b56d5c0

Please sign in to comment.