1#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
6#[macro_export]
23macro_rules! log {
24 ($($input:tt)+) => {
25 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}], $($input)+)
26 };
27}
28
29#[doc(hidden)]
30#[macro_export]
31macro_rules! __log_impl {
32 (logger: $logger:expr, kv: $kv:tt, $level:expr, $($arg:tt)+) => ({
33 let logger = &$logger;
34 if $crate::STATIC_LEVEL_FILTER.__test_const($level) && logger.should_log($level) {
35 $crate::__log(logger, $level, $crate::source_location_current!(), $crate::__kv!($kv), format_args!($($arg)+));
36 }
37 });
38}
39
40#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
42#[macro_export]
57macro_rules! critical {
58 ($($input:tt)+) => {
59 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}, $crate::Level::Critical], $($input)+)
60 };
61}
62
63#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
65#[macro_export]
80macro_rules! error {
81 ($($input:tt)+) => {
82 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}, $crate::Level::Error], $($input)+)
83 };
84}
85
86#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
88#[macro_export]
103macro_rules! warn {
104 ($($input:tt)+) => {
105 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}, $crate::Level::Warn], $($input)+)
106 };
107}
108
109#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
111#[macro_export]
127macro_rules! info {
128 ($($input:tt)+) => {
129 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}, $crate::Level::Info], $($input)+)
130 };
131}
132
133#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
135#[macro_export]
151macro_rules! debug {
152 ($($input:tt)+) => {
153 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}, $crate::Level::Debug], $($input)+)
154 };
155}
156
157#[doc = include_str!("./include/doc/log-macro-named-opt-params.md")]
159#[macro_export]
175macro_rules! trace {
176 ($($input:tt)+) => {
177 $crate::__normalize_forward!(__log_impl => default[logger: $crate::default_logger(), kv: {}, $crate::Level::Trace], $($input)+)
178 };
179}
180
181#[doc(hidden)]
182#[macro_export]
183macro_rules! __kv {
184 ({}) => (&[]);
185 ({ $($ttm:tt)+ }) => {
186 $crate::__kv!(@{} $($ttm)+)
187 };
188
189 (@{$($done:tt)*} $k:ident $(= $v:expr)? $(,$($rest:tt)*)?) => ($crate::__kv!(@{$($done)* $k [ ] $(= $v)?,} $($($rest)*)?));
190 (@{$($done:tt)*} $k:ident : $(= $v:expr)? $(,$($rest:tt)*)?) => ($crate::__kv!(@{$($done)* $k [: ] $(= $v)?,} $($($rest)*)?));
191 (@{$($done:tt)*} $k:ident :? $(= $v:expr)? $(,$($rest:tt)*)?) => ($crate::__kv!(@{$($done)* $k [:?] $(= $v)?,} $($($rest)*)?));
192 (@{$($done:tt)*} $k:ident :sval $(= $v:expr)? $(,$($rest:tt)*)?) => ($crate::__kv!(@{$($done)* $k [:sval] $(= $v)?,} $($($rest)*)?));
193 (@{$($done:tt)*} $k:ident :serde $(= $v:expr)? $(,$($rest:tt)*)?) => ($crate::__kv!(@{$($done)* $k [:serde] $(= $v)?,} $($($rest)*)?));
194 (@{$( $k:ident [$($modifier:tt)*] $(= $v:expr)? ),+ $(,)?}) => {
195 &[$(($crate::kv::Key::__from_static_str(stringify!($k)), $crate::__kv_value!($k [$($modifier)*] $(= $v)?))),+]
196 };
197}
198
199#[doc(hidden)]
200#[macro_export]
201macro_rules! __kv_value {
202 ($k:ident [$($modifier:tt)*]) => { $crate::__kv_value!($k [$($modifier)*] = $k) };
203 ($k:ident [ ] = $v:expr) => { $crate::kv::Value::from(&$v) };
204 ($k:ident [: ] = $v:expr) => { $crate::kv::Value::capture_display(&$v) };
205 ($k:ident [:?] = $v:expr) => { $crate::kv::Value::capture_debug(&$v) };
206 ($k:ident [:sval] = $v:expr) => { $crate::kv::Value::capture_sval2(&$v) };
207 ($k:ident [:serde] = $v:expr) => { $crate::kv::Value::capture_serde1(&$v) };
208}
209
210#[cfg(test)]
211mod tests {
212 use std::{
213 fmt::{self, Debug, Display},
214 sync::Arc,
215 vec,
216 };
217
218 use crate::{
219 kv::Key,
220 prelude::*,
221 sink::{GetSinkProp, Sink, SinkProp},
222 test_utils::{self, *},
223 utils::RefStr,
224 Record,
225 };
226
227 #[test]
228 fn syntax_and_records() {
229 let test_sink = Arc::new(TestSink::new());
230 let test = Arc::new(build_test_logger(|b| {
231 b.sink(test_sink.clone()).level_filter(LevelFilter::All)
232 }));
233
234 struct Mods;
235 impl Debug for Mods {
236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237 write!(f, "debug")
238 }
239 }
240 impl Display for Mods {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 write!(f, "display")
243 }
244 }
245 let (int, mod1, mod2) = (114514, Mods, Mods);
246
247 const LEVEL_ARG: Level = Level::Info;
248
249 let assert_records = |kv: &[(&'static str, &str)], payload| {
250 let records = test_sink.records();
251 assert_eq!(records.len(), Level::count() + 1);
252 test_sink.clear();
253
254 records
255 .into_iter()
256 .zip([
257 LEVEL_ARG,
258 Level::Trace,
259 Level::Debug,
260 Level::Info,
261 Level::Warn,
262 Level::Error,
263 Level::Critical,
264 ])
265 .for_each(|(record, expected_level)| {
266 assert_eq!(record.level(), expected_level);
267 assert_eq!(
268 record
269 .key_values()
270 .into_iter()
271 .map(|(k, v)| (k.inner(), v.to_string()))
272 .collect::<Vec<_>>(),
273 kv.iter()
274 .map(|(k, v)| (RefStr::new_ref(k), v.to_string()))
275 .collect::<Vec<_>>()
276 );
277 assert_eq!(record.payload(), payload);
278 });
279 };
280
281 log!(logger: test, LEVEL_ARG, "logger param only");
282 trace!(logger: test, "logger param only");
283 debug!(logger: test, "logger param only");
284 info!(logger: test, "logger param only");
285 warn!(logger: test, "logger param only");
286 error!(logger: test, "logger param only");
287 critical!(logger: test, "logger param only");
288 assert_records(&[], "logger param only");
289
290 log!(logger: test, kv: {}, LEVEL_ARG, "empty kv param");
291 trace!(logger: test, kv: {}, "empty kv param");
292 debug!(logger: test, kv: {}, "empty kv param");
293 info!(logger: test, kv: {}, "empty kv param");
294 warn!(logger: test, kv: {}, "empty kv param");
295 error!(logger: test, kv: {}, "empty kv param");
296 critical!(logger: test, kv: {}, "empty kv param");
297 assert_records(&[], "empty kv param");
298
299 log!(logger: test, kv: { int = 114514 }, LEVEL_ARG, "kv capture value directly");
300 trace!(logger: test, kv: { int = 114514 }, "kv capture value directly");
301 debug!(logger: test, kv: { int = 114514 }, "kv capture value directly");
302 info!(logger: test, kv: { int = 114514 }, "kv capture value directly");
303 warn!(logger: test, kv: { int = 114514 }, "kv capture value directly");
304 error!(logger: test, kv: { int = 114514 }, "kv capture value directly");
305 critical!(logger: test, kv: { int = 114514 }, "kv capture value directly");
306 assert_records(&[("int", "114514")], "kv capture value directly");
307
308 log!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, LEVEL_ARG, "kv capture value using modifiers");
309 trace!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, "kv capture value using modifiers");
310 debug!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, "kv capture value using modifiers");
311 info!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, "kv capture value using modifiers");
312 warn!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, "kv capture value using modifiers");
313 error!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, "kv capture value using modifiers");
314 critical!(logger: test, kv: { int = 114514, mod1: = Mods, mod2:? = Mods }, "kv capture value using modifiers");
315 assert_records(
316 &[("int", "114514"), ("mod1", "display"), ("mod2", "debug")],
317 "kv capture value using modifiers",
318 );
319
320 log!(logger: test, kv: { int }, LEVEL_ARG, "kv shorthand");
321 trace!(logger: test, kv: { int }, "kv shorthand");
322 debug!(logger: test, kv: { int }, "kv shorthand");
323 info!(logger: test, kv: { int }, "kv shorthand");
324 warn!(logger: test, kv: { int }, "kv shorthand");
325 error!(logger: test, kv: { int }, "kv shorthand");
326 critical!(logger: test, kv: { int }, "kv shorthand");
327 assert_records(&[("int", "114514")], "kv shorthand");
328
329 log!(logger: test, kv: { int, mod1:, mod2:? }, LEVEL_ARG, "kv shorthand modifiers");
330 trace!(logger: test, kv: { int, mod1:, mod2:? }, "kv shorthand modifiers");
331 debug!(logger: test, kv: { int, mod1:, mod2:? }, "kv shorthand modifiers");
332 info!(logger: test, kv: { int, mod1:, mod2:? }, "kv shorthand modifiers");
333 warn!(logger: test, kv: { int, mod1:, mod2:? }, "kv shorthand modifiers");
334 error!(logger: test, kv: { int, mod1:, mod2:? }, "kv shorthand modifiers");
335 critical!(logger: test, kv: { int, mod1:, mod2:? }, "kv shorthand modifiers");
336 assert_records(
337 &[("int", "114514"), ("mod1", "display"), ("mod2", "debug")],
338 "kv shorthand modifiers",
339 );
340
341 log!(logger: test, LEVEL_ARG, "params arbitrary order: logger, format, kv", kv: { mod1: });
342 trace!(logger: test, "params arbitrary order: logger, format, kv", kv: { mod1: });
343 debug!(logger: test, "params arbitrary order: logger, format, kv", kv: { mod1: });
344 info!(logger: test, "params arbitrary order: logger, format, kv", kv: { mod1: });
345 warn!(logger: test, "params arbitrary order: logger, format, kv", kv: { mod1: });
346 error!(logger: test, "params arbitrary order: logger, format, kv", kv: { mod1: });
347 critical!(logger: test, "params arbitrary order: logger, format, kv", kv: { mod1: });
348 assert_records(
349 &[("mod1", "display")],
350 "params arbitrary order: logger, format, kv",
351 );
352
353 log!(LEVEL_ARG, "params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
354 trace!("params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
355 debug!("params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
356 info!("params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
357 warn!("params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
358 error!("params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
359 critical!("params arbitrary order = format, kv, logger", kv: { mod1:? }, logger: test);
360 assert_records(
361 &[("mod1", "debug")],
362 "params arbitrary order = format, kv, logger",
363 );
364
365 let runtime_level = Level::Info;
366 log!(logger: test, runtime_level, "runtime level");
367 }
368
369 #[test]
370 fn kv_types() {
371 struct Asserter {
372 prop: SinkProp,
373 }
374
375 impl GetSinkProp for Asserter {
376 fn prop(&self) -> &SinkProp {
377 &self.prop
378 }
379 }
380
381 impl Sink for Asserter {
382 fn should_log(&self, _: Level) -> bool {
383 true
384 }
385 fn flush(&self) -> crate::Result<()> {
386 Ok(())
387 }
388
389 fn log(&self, record: &Record) -> crate::Result<()> {
390 let kvs = record.key_values();
391 let value = kvs.get(Key::from_str("v")).unwrap();
392 assert_eq!(kvs.len(), 1);
393
394 match record.payload() {
395 "1" => assert!(value.to_i64().is_some()),
396 "2" => assert!(value.to_str().is_some()),
397 "3" => assert!(value.to_i64().is_some()),
398 "4" => assert!(value.to_i64().is_some()),
399 "5" => assert!(value.is::<Vec<i32>>()),
400 "6" => assert!(value.is::<Data>()),
401 "7" => assert!(value.is::<Data>()),
402 _ => panic!(),
403 }
404 Ok(())
405 }
406 }
407
408 let asserter = test_utils::build_test_logger(|b| {
409 b.sink(Arc::new(Asserter {
410 prop: SinkProp::default(),
411 }))
412 });
413
414 #[cfg_attr(feature = "sval", derive(sval_derive::Value))]
415 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
416 struct Data {
417 i: i32,
418 v: Vec<i32>,
419 }
420 let data = Data {
421 i: 1,
422 v: vec![1, 2],
423 };
424
425 info!(logger: asserter, "1", kv: { v = 1 });
426 info!(logger: asserter, "2", kv: { v = "string" });
427 info!(logger: asserter, "3", kv: { v: = 1 });
428 info!(logger: asserter, "4", kv: { v:? = 1 });
429 #[cfg(feature = "sval")]
430 info!(logger: asserter, "5", kv: { v:sval = vec![1, 2] });
431 #[cfg(feature = "sval")]
432 info!(logger: asserter, "6", kv: { v:sval = data });
433 #[cfg(feature = "serde")]
434 info!(logger: asserter, "7", kv: { v:serde = data });
435 }
436}