log/
__private_api.rs

1//! WARNING: this is not part of the crate's public API and is subject to change at any time
2
3use self::sealed::KVs;
4use crate::{Level, Metadata, Record};
5use std::fmt::Arguments;
6use std::panic::Location;
7pub use std::{format_args, module_path, stringify};
8
9#[cfg(not(feature = "kv"))]
10pub type Value<'a> = &'a str;
11
12mod sealed {
13    /// Types for the `kv` argument.
14    pub trait KVs<'a> {
15        fn into_kvs(self) -> Option<&'a [(&'a str, super::Value<'a>)]>;
16    }
17}
18
19// Types for the `kv` argument.
20
21impl<'a> KVs<'a> for &'a [(&'a str, Value<'a>)] {
22    #[inline]
23    fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> {
24        Some(self)
25    }
26}
27
28impl<'a> KVs<'a> for () {
29    #[inline]
30    fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> {
31        None
32    }
33}
34
35// Log implementation.
36
37fn log_impl(
38    args: Arguments,
39    level: Level,
40    &(target, module_path, loc): &(&str, &'static str, &'static Location),
41    kvs: Option<&[(&str, Value)]>,
42) {
43    #[cfg(not(feature = "kv"))]
44    if kvs.is_some() {
45        panic!("key-value support is experimental and must be enabled using the `kv` feature")
46    }
47
48    let mut builder = Record::builder();
49
50    builder
51        .args(args)
52        .level(level)
53        .target(target)
54        .module_path_static(Some(module_path))
55        .file_static(Some(loc.file()))
56        .line(Some(loc.line()));
57
58    #[cfg(feature = "kv")]
59    builder.key_values(&kvs);
60
61    crate::logger().log(&builder.build());
62}
63
64pub fn log<'a, K>(
65    args: Arguments,
66    level: Level,
67    target_module_path_and_loc: &(&str, &'static str, &'static Location),
68    kvs: K,
69) where
70    K: KVs<'a>,
71{
72    log_impl(args, level, target_module_path_and_loc, kvs.into_kvs())
73}
74
75pub fn enabled(level: Level, target: &str) -> bool {
76    crate::logger().enabled(&Metadata::builder().level(level).target(target).build())
77}
78
79#[track_caller]
80pub fn loc() -> &'static Location<'static> {
81    Location::caller()
82}
83
84#[cfg(feature = "kv")]
85mod kv_support {
86    use crate::kv;
87
88    pub type Value<'a> = kv::Value<'a>;
89
90    // NOTE: Many functions here accept a double reference &&V
91    // This is so V itself can be ?Sized, while still letting us
92    // erase it to some dyn Trait (because &T is sized)
93
94    pub fn capture_to_value<'a, V: kv::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> {
95        v.to_value()
96    }
97
98    pub fn capture_debug<'a, V: core::fmt::Debug + ?Sized>(v: &'a &'a V) -> Value<'a> {
99        Value::from_debug(v)
100    }
101
102    pub fn capture_display<'a, V: core::fmt::Display + ?Sized>(v: &'a &'a V) -> Value<'a> {
103        Value::from_display(v)
104    }
105
106    #[cfg(feature = "kv_std")]
107    pub fn capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a> {
108        Value::from_dyn_error(v)
109    }
110
111    #[cfg(feature = "kv_sval")]
112    pub fn capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a> {
113        Value::from_sval(v)
114    }
115
116    #[cfg(feature = "kv_serde")]
117    pub fn capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> {
118        Value::from_serde(v)
119    }
120}
121
122#[cfg(feature = "kv")]
123pub use self::kv_support::*;