diff --git a/Cargo.toml b/Cargo.toml index b64111b9f..11691fa02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,10 @@ features = ["std", "serde", "kv_unstable_sval"] name = "filters" harness = false +[[test]] +name = "macros" +harness = true + [features] max_level_off = [] max_level_error = [] diff --git a/src/lib.rs b/src/lib.rs index 147e04201..6b78905f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1373,10 +1373,39 @@ pub fn logger() -> &'static Log { // WARNING: this is not part of the crate's public API and is subject to change at any time #[doc(hidden)] +#[cfg(not(feature = "kv_unstable"))] pub fn __private_api_log( args: fmt::Arguments, level: Level, &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + kvs: Option<&[(&str, &str)]>, +) { + if kvs.is_some() { + panic!( + "key-value support is experimental and must be enabled using the `kv_unstable` feature" + ) + } + + logger().log( + &Record::builder() + .args(args) + .level(level) + .target(target) + .module_path_static(Some(module_path)) + .file_static(Some(file)) + .line(Some(line)) + .build(), + ); +} + +// WARNING: this is not part of the crate's public API and is subject to change at any time +#[cfg(feature = "kv_unstable")] +#[doc(hidden)] +pub fn __private_api_log( + args: fmt::Arguments<'_>, + level: Level, + &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + kvs: Option<&[(&str, &kv::ToValue)]>, ) { logger().log( &Record::builder() @@ -1386,6 +1415,7 @@ pub fn __private_api_log( .module_path_static(Some(module_path)) .file_static(Some(file)) .line(Some(line)) + .key_values(&kvs) .build(), ); } diff --git a/src/macros.rs b/src/macros.rs index bb40b7107..de19ef23c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,17 +29,63 @@ /// ``` #[macro_export(local_inner_macros)] macro_rules! log { - (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + // log!(target: "...", "...") + (target: $target:expr, $lvl:expr, $e:expr) => { + $crate::log_impl!(target: $target, $lvl, ($e)); + }; + + // log!(target: "...", "...", args...) + (target: $target:expr, $lvl:expr, $e:expr, $($rest:tt)*) => { + $crate::log_impl!(target: $target, $lvl, ($e) $($rest)*); + }; + + // log!("...", args...) + ($lvl:expr, $($arg:tt)+) => ($crate::log!(target: __log_module_path!(), $lvl, $($arg)+)) +} + +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! log_impl { + // End of macro input + (target: $target:expr, $lvl:expr, ($($arg:expr),*)) => { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( - __log_format_args!($($arg)+), + __log_format_args!($($arg),*), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), + None, + ); + } + }; + + // // Trailing k-v pairs containing no trailing comma + (target: $target:expr, $lvl:expr, ($($arg:expr),*) { $($key:ident : $value:expr),* }) => { + let lvl = log::Level::Info; + if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { + $crate::__private_api_log( + __log_format_args!($($arg),*), + lvl, + &(__log_module_path!(), __log_module_path!(), __log_file!(), __log_line!()), + Some(&[$((__log_stringify!($key), &$value)),*]) ); } - }); - ($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+)) + }; + + // Trailing k-v pairs with trailing comma + (target: $target:expr, $lvl:expr, ($($e:expr),*) { $($key:ident : $value:expr,)* }) => { + $crate::log_impl!(target: $target, $lvl, ($($e),*) { $($key : $value),* }); + }; + + // Last expression arg with no trailing comma + (target: $target:expr, $lvl:expr, ($($e:expr),*) $arg:expr) => { + $crate::log_impl!(target: $target, $lvl, ($($e,)* $arg)); + }; + + // Expression arg + (target: $target:expr, $lvl:expr, ($($e:expr),*) $arg:expr, $($rest:tt)*) => { + $crate::log_impl!(target: $target, $lvl, ($($e,)* $arg) $($rest)*); + }; } /// Logs a message at the error level. @@ -248,3 +294,11 @@ macro_rules! __log_line { line!() }; } + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_stringify { + ($($args:tt)*) => { + stringify!($($args)*) + }; +} diff --git a/tests/macros.rs b/tests/macros.rs new file mode 100644 index 000000000..f41c52ed3 --- /dev/null +++ b/tests/macros.rs @@ -0,0 +1,23 @@ +#[macro_use] +extern crate log; + +#[test] +fn base() { + info!("hello"); + info!("hello",); +} + +#[test] +fn with_args() { + info!("hello {}", "cats"); + info!("hello {}", "cats",); + info!("hello {}", "cats",); +} + +#[test] +fn kv() { + info!("hello {}", "cats", { + cat_1: "chashu", + cat_2: "nori", + }); +}