From d5061b629afecc32724060a874990b8d33408c30 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 15:45:58 +0800 Subject: [PATCH 01/11] Add an optional logger param Signed-off-by: tison --- src/__private_api.rs | 23 +++++--- src/macros.rs | 126 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 22 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 11bc2fc1c..1331568bf 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -1,7 +1,7 @@ //! WARNING: this is not part of the crate's public API and is subject to change at any time use self::sealed::KVs; -use crate::{Level, Metadata, Record}; +use crate::{Level, Log, Metadata, Record}; use std::fmt::Arguments; use std::panic::Location; pub use std::{format_args, module_path, stringify}; @@ -34,7 +34,8 @@ impl<'a> KVs<'a> for () { // Log implementation. -fn log_impl( +fn log_impl( + logger: &L, args: Arguments, level: Level, &(target, module_path, loc): &(&str, &'static str, &'static Location), @@ -58,22 +59,30 @@ fn log_impl( #[cfg(feature = "kv")] builder.key_values(&kvs); - crate::logger().log(&builder.build()); + logger.log(&builder.build()); } -pub fn log<'a, K>( +pub fn log<'a, K, L>( + logger: &L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), kvs: K, ) where K: KVs<'a>, + L: Log, { - log_impl(args, level, target_module_path_and_loc, kvs.into_kvs()) + log_impl( + logger, + args, + level, + target_module_path_and_loc, + kvs.into_kvs(), + ) } -pub fn enabled(level: Level, target: &str) -> bool { - crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) +pub fn enabled(logger: &L, level: Level, target: &str) -> bool { + logger.enabled(&Metadata::builder().level(level).target(target).build()) } #[track_caller] diff --git a/src/macros.rs b/src/macros.rs index 87693f2b1..d68881fb0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,11 +29,13 @@ /// ``` #[macro_export] macro_rules! log { - // log!(target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ + // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); + (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ + let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_>( + logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -42,11 +44,13 @@ macro_rules! log { } }); - // log!(target: "my_target", Level::Info, "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); + (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( + logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -55,8 +59,20 @@ macro_rules! log { } }); + // log!(logger: my_logger, Level::Info, "a log event") + (logger: $logger:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $crate::__private_api::module_path!(), $lvl, $($arg)+) + }); + + // log!(target: "my_target", Level::Info, "a log event") + (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $crate::logger(), target: $target, $lvl, $($arg)+) + }); + // log!(Level::Info, "a log event") - ($lvl:expr, $($arg:tt)+) => ($crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+)); + ($lvl:expr, $($arg:tt)+) => ({ + $crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+) + }); } /// Logs a message at the error level. @@ -75,9 +91,23 @@ macro_rules! log { /// ``` #[macro_export] macro_rules! error { + // error!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // error!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Error, $($arg)+) + }); + + // error!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // error!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Error, $($arg)+) + }); + // error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // error!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Error, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Error, $($arg)+) + }); // error!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Error, $($arg)+)) @@ -99,9 +129,23 @@ macro_rules! error { /// ``` #[macro_export] macro_rules! warn { + // warn!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // warn!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Warn, $($arg)+) + }); + + // warn!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // warn!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Warn, $($arg)+) + }); + // warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // warn!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Warn, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Warn, $($arg)+) + }); // warn!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Warn, $($arg)+)) @@ -125,9 +169,23 @@ macro_rules! warn { /// ``` #[macro_export] macro_rules! info { + // info!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // info!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Info, $($arg)+) + }); + + // info!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // info!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Info, $($arg)+) + }); + // info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // info!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Info, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Info, $($arg)+) + }); // info!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Info, $($arg)+)) @@ -150,9 +208,23 @@ macro_rules! info { /// ``` #[macro_export] macro_rules! debug { + // debug!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // debug!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Debug, $($arg)+) + }); + + // debug!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // debug!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Debug, $($arg)+) + }); + // debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // debug!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Debug, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Debug, $($arg)+) + }); // debug!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Debug, $($arg)+)) @@ -177,9 +249,23 @@ macro_rules! debug { /// ``` #[macro_export] macro_rules! trace { + // trace!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // trace!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Trace, $($arg)+) + }); + + // trace!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // trace!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Trace, $($arg)+) + }); + // trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // trace!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Trace, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Trace, $($arg)+) + }); // trace!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Trace, $($arg)+)) @@ -213,15 +299,25 @@ macro_rules! trace { /// ``` #[macro_export] macro_rules! log_enabled { - (target: $target:expr, $lvl:expr) => {{ + (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ + let logger = &$logger; let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() - && $crate::__private_api::enabled(lvl, $target) - }}; - ($lvl:expr) => { + && $crate::__private_api::enabled(logger, lvl, $target) + }); + + (logger: $logger:expr, $lvl:expr) => ({ + $crate::log_enabled!(logger: $logger, target: $crate::__private_api::module_path!(), $lvl) + }); + + (target: $target:expr, $lvl:expr) => ({ + $crate::log_enabled!(logger: $crate::logger(), target: $target, $lvl) + }); + + ($lvl:expr) => ({ $crate::log_enabled!(target: $crate::__private_api::module_path!(), $lvl) - }; + }); } // These macros use a pattern of #[cfg]s to produce nicer error From 2851f2bac373edd1c3cf1317dc72ae912ab67e53 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 16:03:23 +0800 Subject: [PATCH 02/11] fixup MSRV Signed-off-by: tison --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros.rs b/src/macros.rs index d68881fb0..d901e24a7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -34,7 +34,7 @@ macro_rules! log { let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api::log::<&_>( + $crate::__private_api::log( logger, $crate::__private_api::format_args!($($arg)+), lvl, From a3f72c8fbe31eb06e7aa3451da6246470c0eade4 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 16:06:19 +0800 Subject: [PATCH 03/11] separate logger Signed-off-by: tison --- tests/integration.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index 7bf456e02..ca104d8ae 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -53,31 +53,31 @@ fn main() { last_log_location: Mutex::new(None), }); let a = me.clone(); - set_boxed_logger(Box::new(Logger(me))).unwrap(); + let logger = Logger(me); - test_filter(&a, LevelFilter::Off); - test_filter(&a, LevelFilter::Error); - test_filter(&a, LevelFilter::Warn); - test_filter(&a, LevelFilter::Info); - test_filter(&a, LevelFilter::Debug); - test_filter(&a, LevelFilter::Trace); + test_filter(&logger, &a, LevelFilter::Off); + test_filter(&logger, &a, LevelFilter::Error); + test_filter(&logger, &a, LevelFilter::Warn); + test_filter(&logger, &a, LevelFilter::Info); + test_filter(&logger, &a, LevelFilter::Debug); + test_filter(&logger, &a, LevelFilter::Trace); - test_line_numbers(&a); + test_line_numbers(&logger, &a); } } -fn test_filter(a: &State, filter: LevelFilter) { +fn test_filter(logger: &dyn Log, a: &State, filter: LevelFilter) { // tests to ensure logs with a level beneath 'max_level' are filtered out log::set_max_level(filter); - error!(""); + error!(logger: logger, ""); last(a, t(Level::Error, filter)); - warn!(""); + warn!(logger: logger, ""); last(a, t(Level::Warn, filter)); - info!(""); + info!(logger: logger, ""); last(a, t(Level::Info, filter)); - debug!(""); + debug!(logger: logger, ""); last(a, t(Level::Debug, filter)); - trace!(""); + trace!(logger: logger, ""); last(a, t(Level::Trace, filter)); fn t(lvl: Level, filter: LevelFilter) -> Option { @@ -93,10 +93,10 @@ fn test_filter(a: &State, filter: LevelFilter) { } } -fn test_line_numbers(state: &State) { +fn test_line_numbers(logger: &dyn Log, state: &State) { log::set_max_level(LevelFilter::Trace); - info!(""); // ensure check_line function follows log macro + info!(logger: logger, ""); // ensure check_line function follows log macro check_log_location(&state); #[track_caller] From dd835fe38e484a8b5bd9acf6d0465c36d70acfcc Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 17:42:57 +0800 Subject: [PATCH 04/11] fixup msrv tests Signed-off-by: tison --- src/macros.rs | 2 +- tests/macros.rs | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index d901e24a7..3135aaf46 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -34,7 +34,7 @@ macro_rules! log { let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api::log( + $crate::__private_api::log::<&_, _>( logger, $crate::__private_api::format_args!($($arg)+), lvl, diff --git a/tests/macros.rs b/tests/macros.rs index 20da6ac44..ba2815dbb 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -1,4 +1,4 @@ -use log::{log, log_enabled}; +use log::{log, log_enabled, Log, Metadata, Record}; macro_rules! all_log_macros { ($($arg:tt)*) => ({ @@ -10,6 +10,16 @@ macro_rules! all_log_macros { }); } +struct NopLogger; + +impl Log for NopLogger { + fn enabled(&self, _: &Metadata) -> bool { + false + } + fn log(&self, _: &Record) {} + fn flush(&self) {} +} + #[test] fn no_args() { for lvl in log::Level::iter() { @@ -28,6 +38,12 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); + + let nop = NopLogger; + all_log_macros!(logger: nop, "hello"); + all_log_macros!(logger: nop, "hello",); + all_log_macros!(logger: nop, target: "my_target", "hello"); + all_log_macros!(logger: nop, target: "my_target", "hello",); } #[test] @@ -115,6 +131,9 @@ fn kv_no_args() { log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } + let nop = NopLogger; + all_log_macros!(logger: nop, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: nop, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); From cde258593221716c7b64c049d6619b49b30dd4de Mon Sep 17 00:00:00 2001 From: tison Date: Thu, 27 Feb 2025 21:50:48 +0800 Subject: [PATCH 05/11] allows us to pass zero-sized logger Signed-off-by: tison --- src/__private_api.rs | 6 +++--- src/macros.rs | 6 +++--- tests/macros.rs | 14 ++++++-------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 1331568bf..57f038120 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -35,7 +35,7 @@ impl<'a> KVs<'a> for () { // Log implementation. fn log_impl( - logger: &L, + logger: L, args: Arguments, level: Level, &(target, module_path, loc): &(&str, &'static str, &'static Location), @@ -63,7 +63,7 @@ fn log_impl( } pub fn log<'a, K, L>( - logger: &L, + logger: L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), @@ -81,7 +81,7 @@ pub fn log<'a, K, L>( ) } -pub fn enabled(logger: &L, level: Level, target: &str) -> bool { +pub fn enabled(logger: L, level: Level, target: &str) -> bool { logger.enabled(&Metadata::builder().level(level).target(target).build()) } diff --git a/src/macros.rs b/src/macros.rs index 272c42f42..e9cf962b7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -32,7 +32,7 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ - let logger = &$logger; + let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_, _>( @@ -47,7 +47,7 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - let logger = &$logger; + let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( @@ -306,7 +306,7 @@ macro_rules! trace { #[macro_export] macro_rules! log_enabled { (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ - let logger = &$logger; + let logger = $logger; let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() diff --git a/tests/macros.rs b/tests/macros.rs index ba2815dbb..e4023ea22 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -39,11 +39,10 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); - let nop = NopLogger; - all_log_macros!(logger: nop, "hello"); - all_log_macros!(logger: nop, "hello",); - all_log_macros!(logger: nop, target: "my_target", "hello"); - all_log_macros!(logger: nop, target: "my_target", "hello",); + all_log_macros!(logger: NopLogger, "hello"); + all_log_macros!(logger: NopLogger, "hello",); + all_log_macros!(logger: NopLogger, target: "my_target", "hello"); + all_log_macros!(logger: NopLogger, target: "my_target", "hello",); } #[test] @@ -131,9 +130,8 @@ fn kv_no_args() { log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - let nop = NopLogger; - all_log_macros!(logger: nop, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - all_log_macros!(logger: nop, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: NopLogger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: NopLogger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); From 2bb47d65a5c6f94bdc1d694bec4824431201e31a Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 28 Feb 2025 11:41:32 +0800 Subject: [PATCH 06/11] use a zero-sized GlobalLogger Signed-off-by: tison --- src/lib.rs | 24 +++++++++++++++++++++++- src/macros.rs | 4 ++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a862b5fa9..2dd300874 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1204,7 +1204,7 @@ pub trait Log: Sync + Send { fn flush(&self); } -// Just used as a dummy initial value for LOGGER +/// A dummy initial value for LOGGER. struct NopLogger; impl Log for NopLogger { @@ -1216,6 +1216,28 @@ impl Log for NopLogger { fn flush(&self) {} } +/// The global logger proxy. +/// +/// This zero-sized type implements the [`Log`] trait by forwarding calls +/// to the logger registered with the `set_boxed_logger` or `set_logger` +/// methods if there is one, or a nop logger as default. +#[derive(Copy, Clone, Default, Debug)] +pub struct GlobalLogger; + +impl Log for GlobalLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + logger().enabled(metadata) + } + + fn log(&self, record: &Record) { + logger().log(record) + } + + fn flush(&self) { + logger().flush() + } +} + impl Log for &'_ T where T: ?Sized + Log, diff --git a/src/macros.rs b/src/macros.rs index e9cf962b7..e962b1b62 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -67,7 +67,7 @@ macro_rules! log { // log!(target: "my_target", Level::Info, "a log event") (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $crate::logger(), target: $target, $lvl, $($arg)+) + $crate::log!(logger: $crate::GlobalLogger, target: $target, $lvl, $($arg)+) }); // log!(Level::Info, "a log event") @@ -318,7 +318,7 @@ macro_rules! log_enabled { }); (target: $target:expr, $lvl:expr) => ({ - $crate::log_enabled!(logger: $crate::logger(), target: $target, $lvl) + $crate::log_enabled!(logger: $crate::GlobalLogger, target: $target, $lvl) }); ($lvl:expr) => ({ From 11af9f190acd102c1db194205c7ec18b2a15a7b6 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 17 Mar 2025 22:23:34 +0800 Subject: [PATCH 07/11] move logger expr to execute conditionally Signed-off-by: tison --- src/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index e962b1b62..9d2a1810e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -32,9 +32,9 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ - let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { + let logger = $logger; $crate::__private_api::log::<&_, _>( logger, $crate::__private_api::format_args!($($arg)+), @@ -47,9 +47,9 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { + let logger = $logger; $crate::__private_api::log( logger, $crate::__private_api::format_args!($($arg)+), From da3dd1feb86f8c57029e90cd1c422c3a0dd7343e Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 17 Mar 2025 22:50:34 +0800 Subject: [PATCH 08/11] add docs Signed-off-by: tison --- src/macros.rs | 91 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 9d2a1810e..49166fe02 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,20 +13,56 @@ /// This macro will generically log with the specified `Level` and `format!` /// based argument list. /// -/// # Examples -/// /// ``` /// use log::{log, Level}; /// -/// # fn main() { /// let data = (42, "Forty-two"); /// let private_data = "private"; /// /// log!(Level::Error, "Received errors: {}, {}", data.0, data.1); -/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}", -/// data.0, data.1, private_data); -/// # } /// ``` +/// +/// Optionally, you can specify a `target` argument to attach a specific target +/// to the log record. By default, the target is the module path of the caller. +/// +/// ``` +/// use log::{log, Level}; +/// +/// let data = (42, "Forty-two"); +/// let private_data = "private"; +/// +/// log!( +/// target: "app_events", +/// Level::Error, +/// "Received errors: {}, {}", +/// data.0, data.1 +/// ); +/// ``` +/// +/// And optionally, you can specify a `logger` argument to use a specific logger +/// instead of the default global logger. +/// +/// ``` +/// # struct MyLogger {} +/// # impl Log for MyLogger { +/// # fn enabled(&self, _metadata: &log::Metadata) -> bool { +/// # false +/// # } +/// # fn log(&self, _record: &log::Record) {} +/// # fn flush(&self) {} +/// # } +/// use log::{log, Level, Log}; +/// +/// let data = (42, "Forty-two"); +/// let private_data = "private"; +/// +/// let my_logger = MyLogger {}; +/// log!( +/// logger: &my_logger, +/// Level::Error, +/// "Received errors: {}, {}", +/// data.0, data.1 +/// ); #[macro_export] #[clippy::format_args] macro_rules! log { @@ -81,14 +117,14 @@ macro_rules! log { /// # Examples /// /// ``` -/// use log::error; +/// use log::{error, GlobalLogger}; /// -/// # fn main() { /// let (err_info, port) = ("No connection", 22); +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// error!("Error: {err_info} on port {port}"); /// error!(target: "app_events", "App Error: {err_info}, Port: {port}"); -/// # } +/// error!(logger: my_logger, "App Error: {err_info}, Port: {port}"); /// ``` #[macro_export] #[clippy::format_args] @@ -120,14 +156,14 @@ macro_rules! error { /// # Examples /// /// ``` -/// use log::warn; +/// use log::{warn, GlobalLogger}; /// -/// # fn main() { /// let warn_description = "Invalid Input"; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// warn!("Warning! {warn_description}!"); /// warn!(target: "input_events", "App received warning: {warn_description}"); -/// # } +/// warn!(logger: my_logger, "App received warning: {warn_description}"); /// ``` #[macro_export] #[clippy::format_args] @@ -159,16 +195,23 @@ macro_rules! warn { /// # Examples /// /// ``` -/// use log::info; +/// use log::{info, GlobalLogger}; /// -/// # fn main() { /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed); -/// info!(target: "connection_events", "Successful connection, port: {}, speed: {}", -/// conn_info.port, conn_info.speed); -/// # } +/// info!( +/// target: "connection_events", +/// "Successful connection, port: {}, speed: {}", +/// conn_info.port, conn_info.speed +/// ); +/// info!( +/// logger: my_logger, +/// "Successful connection, port: {}, speed: {}", +/// conn_info.port, conn_info.speed +/// ); /// ``` #[macro_export] #[clippy::format_args] @@ -200,15 +243,15 @@ macro_rules! info { /// # Examples /// /// ``` -/// use log::debug; +/// use log::{debug, GlobalLogger}; /// -/// # fn main() { /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// debug!("New position: x: {}, y: {}", pos.x, pos.y); /// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y); -/// # } +/// debug!(logger: my_logger, "New position: x: {}, y: {}", pos.x, pos.y); /// ``` #[macro_export] #[clippy::format_args] @@ -240,17 +283,19 @@ macro_rules! debug { /// # Examples /// /// ``` -/// use log::trace; +/// use log::{trace, GlobalLogger}; /// -/// # fn main() { /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// trace!("Position is: x: {}, y: {}", pos.x, pos.y); /// trace!(target: "app_events", "x is {} and y is {}", /// if pos.x >= 0.0 { "positive" } else { "negative" }, /// if pos.y >= 0.0 { "positive" } else { "negative" }); -/// # } +/// trace!(logger: my_logger, "x is {} and y is {}", +/// if pos.x >= 0.0 { "positive" } else { "negative" }, +/// if pos.y >= 0.0 { "positive" } else { "negative" }); /// ``` #[macro_export] #[clippy::format_args] From 0bf505d472664531baac462f23985aa37ebfef7c Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 17 Mar 2025 22:54:27 +0800 Subject: [PATCH 09/11] more docs Signed-off-by: tison --- src/macros.rs | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 49166fe02..5207c0d75 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -117,10 +117,10 @@ macro_rules! log { /// # Examples /// /// ``` -/// use log::{error, GlobalLogger}; +/// use log::error; /// +/// # let my_logger = log::GlobalLogger; /// let (err_info, port) = ("No connection", 22); -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// error!("Error: {err_info} on port {port}"); /// error!(target: "app_events", "App Error: {err_info}, Port: {port}"); @@ -156,10 +156,10 @@ macro_rules! error { /// # Examples /// /// ``` -/// use log::{warn, GlobalLogger}; +/// use log::warn; /// +/// # let my_logger = log::GlobalLogger; /// let warn_description = "Invalid Input"; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// warn!("Warning! {warn_description}!"); /// warn!(target: "input_events", "App received warning: {warn_description}"); @@ -195,11 +195,11 @@ macro_rules! warn { /// # Examples /// /// ``` -/// use log::{info, GlobalLogger}; +/// use log::info; /// +/// # let my_logger = log::GlobalLogger; /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed); /// info!( @@ -243,11 +243,11 @@ macro_rules! info { /// # Examples /// /// ``` -/// use log::{debug, GlobalLogger}; +/// use log::debug; /// +/// # let my_logger = log::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// debug!("New position: x: {}, y: {}", pos.x, pos.y); /// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y); @@ -283,11 +283,11 @@ macro_rules! debug { /// # Examples /// /// ``` -/// use log::{trace, GlobalLogger}; +/// use log::trace; /// +/// # let my_logger = log::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// trace!("Position is: x: {}, y: {}", pos.x, pos.y); /// trace!(target: "app_events", "x is {} and y is {}", @@ -331,22 +331,25 @@ macro_rules! trace { /// # Examples /// /// ``` -/// use log::Level::Debug; -/// use log::{debug, log_enabled}; +/// use log::{debug, log_enabled, Level}; /// -/// # fn foo() { -/// if log_enabled!(Debug) { +/// # struct Data { x: u32, y: u32 } +/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } +/// # let my_logger = log::GlobalLogger; +/// if log_enabled!(Level::Debug) { /// let data = expensive_call(); /// debug!("expensive debug data: {} {}", data.x, data.y); /// } -/// if log_enabled!(target: "Global", Debug) { +/// +/// if log_enabled!(target: "Global", Level::Debug) { +/// let data = expensive_call(); +/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y); +/// } +/// +/// if log_enabled!(logger: my_logger, Level::Debug) { /// let data = expensive_call(); /// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y); /// } -/// # } -/// # struct Data { x: u32, y: u32 } -/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } -/// # fn main() {} /// ``` #[macro_export] macro_rules! log_enabled { From 66a7ab7ff093c5da9c599cd2cd39b11fed3470e3 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 19 Mar 2025 07:07:46 +0800 Subject: [PATCH 10/11] address comment Signed-off-by: tison --- src/macros.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 5207c0d75..0de7d5cde 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -70,9 +70,8 @@ macro_rules! log { (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - let logger = $logger; $crate::__private_api::log::<&_, _>( - logger, + $logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -85,9 +84,8 @@ macro_rules! log { (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - let logger = $logger; $crate::__private_api::log( - logger, + $logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -354,11 +352,10 @@ macro_rules! trace { #[macro_export] macro_rules! log_enabled { (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ - let logger = $logger; let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() - && $crate::__private_api::enabled(logger, lvl, $target) + && $crate::__private_api::enabled($logger, lvl, $target) }); (logger: $logger:expr, $lvl:expr) => ({ From 088f9f35ea3dd3ea6b75d8346e8a9dbcf406b430 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 21 Mar 2025 15:18:31 +0800 Subject: [PATCH 11/11] address comments Signed-off-by: tison --- src/__private_api.rs | 26 ++++++++++++++++++++++++-- src/lib.rs | 22 ---------------------- src/macros.rs | 20 ++++++++++---------- tests/macros.rs | 16 ++++++++-------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 57f038120..e2744bef6 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -1,7 +1,7 @@ //! WARNING: this is not part of the crate's public API and is subject to change at any time use self::sealed::KVs; -use crate::{Level, Log, Metadata, Record}; +use crate::{logger, Level, Log, Metadata, Record}; use std::fmt::Arguments; use std::panic::Location; pub use std::{format_args, module_path, stringify}; @@ -34,6 +34,28 @@ impl<'a> KVs<'a> for () { // Log implementation. +/// The global logger proxy. +/// +/// This zero-sized type implements the [`Log`] trait by forwarding calls +/// to the logger registered with the `set_boxed_logger` or `set_logger` +/// methods if there is one, or a nop logger as default. +#[derive(Copy, Clone, Default, Debug)] +pub struct GlobalLogger; + +impl Log for GlobalLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + logger().enabled(metadata) + } + + fn log(&self, record: &Record) { + logger().log(record) + } + + fn flush(&self) { + logger().flush() + } +} + fn log_impl( logger: L, args: Arguments, @@ -63,7 +85,7 @@ fn log_impl( } pub fn log<'a, K, L>( - logger: L, + logger: &L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), diff --git a/src/lib.rs b/src/lib.rs index 2dd300874..054ce9c21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1216,28 +1216,6 @@ impl Log for NopLogger { fn flush(&self) {} } -/// The global logger proxy. -/// -/// This zero-sized type implements the [`Log`] trait by forwarding calls -/// to the logger registered with the `set_boxed_logger` or `set_logger` -/// methods if there is one, or a nop logger as default. -#[derive(Copy, Clone, Default, Debug)] -pub struct GlobalLogger; - -impl Log for GlobalLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - logger().enabled(metadata) - } - - fn log(&self, record: &Record) { - logger().log(record) - } - - fn flush(&self) { - logger().flush() - } -} - impl Log for &'_ T where T: ?Sized + Log, diff --git a/src/macros.rs b/src/macros.rs index 0de7d5cde..a20e8172b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -71,7 +71,7 @@ macro_rules! log { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_, _>( - $logger, + &($logger), $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -85,7 +85,7 @@ macro_rules! log { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( - $logger, + &($logger), $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -101,7 +101,7 @@ macro_rules! log { // log!(target: "my_target", Level::Info, "a log event") (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $crate::GlobalLogger, target: $target, $lvl, $($arg)+) + $crate::log!(logger: $crate::__private_api::GlobalLogger, target: $target, $lvl, $($arg)+) }); // log!(Level::Info, "a log event") @@ -117,7 +117,7 @@ macro_rules! log { /// ``` /// use log::error; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// let (err_info, port) = ("No connection", 22); /// /// error!("Error: {err_info} on port {port}"); @@ -156,7 +156,7 @@ macro_rules! error { /// ``` /// use log::warn; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// let warn_description = "Invalid Input"; /// /// warn!("Warning! {warn_description}!"); @@ -195,7 +195,7 @@ macro_rules! warn { /// ``` /// use log::info; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; /// @@ -243,7 +243,7 @@ macro_rules! info { /// ``` /// use log::debug; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; /// @@ -283,7 +283,7 @@ macro_rules! debug { /// ``` /// use log::trace; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; /// @@ -333,7 +333,7 @@ macro_rules! trace { /// /// # struct Data { x: u32, y: u32 } /// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// if log_enabled!(Level::Debug) { /// let data = expensive_call(); /// debug!("expensive debug data: {} {}", data.x, data.y); @@ -363,7 +363,7 @@ macro_rules! log_enabled { }); (target: $target:expr, $lvl:expr) => ({ - $crate::log_enabled!(logger: $crate::GlobalLogger, target: $target, $lvl) + $crate::log_enabled!(logger: $crate::__private_api::GlobalLogger, target: $target, $lvl) }); ($lvl:expr) => ({ diff --git a/tests/macros.rs b/tests/macros.rs index e4023ea22..35b8c8981 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -10,9 +10,9 @@ macro_rules! all_log_macros { }); } -struct NopLogger; +struct Logger; -impl Log for NopLogger { +impl Log for Logger { fn enabled(&self, _: &Metadata) -> bool { false } @@ -39,10 +39,10 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); - all_log_macros!(logger: NopLogger, "hello"); - all_log_macros!(logger: NopLogger, "hello",); - all_log_macros!(logger: NopLogger, target: "my_target", "hello"); - all_log_macros!(logger: NopLogger, target: "my_target", "hello",); + all_log_macros!(logger: Logger, "hello"); + all_log_macros!(logger: Logger, "hello",); + all_log_macros!(logger: Logger, target: "my_target", "hello"); + all_log_macros!(logger: Logger, target: "my_target", "hello",); } #[test] @@ -130,8 +130,8 @@ fn kv_no_args() { log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - all_log_macros!(logger: NopLogger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - all_log_macros!(logger: NopLogger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: Logger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: Logger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello");