1use self::sealed::KVs;
4use crate::{logger, Level, Log, 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 Key<'a> = &'a str;
11#[cfg(not(feature = "kv"))]
12pub type Value<'a> = &'a str;
13
14mod sealed {
15 pub trait KVs<'a> {
17 fn into_kvs(self) -> Option<&'a [(super::Key<'a>, super::Value<'a>)]>;
18 }
19}
20
21impl<'a> KVs<'a> for &'a [(Key<'a>, Value<'a>)] {
24 #[inline]
25 fn into_kvs(self) -> Option<&'a [(Key<'a>, Value<'a>)]> {
26 Some(self)
27 }
28}
29
30impl<'a> KVs<'a> for () {
31 #[inline]
32 fn into_kvs(self) -> Option<&'a [(Key<'a>, Value<'a>)]> {
33 None
34 }
35}
36
37#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GlobalLogger {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "GlobalLogger")
}
}Debug)]
41pub struct GlobalLogger;
42
43impl Log for GlobalLogger {
44 fn enabled(&self, metadata: &Metadata) -> bool {
45 logger().enabled(metadata)
46 }
47
48 fn log(&self, record: &Record) {
49 logger().log(record)
50 }
51
52 fn flush(&self) {
53 logger().flush()
54 }
55}
56
57fn log_impl<L: Log>(
59 logger: L,
60 args: Arguments,
61 level: Level,
62 &(target, module_path, loc): &(&str, &'static str, &'static Location),
63 kvs: Option<&[(Key, Value)]>,
64) {
65 #[cfg(not(feature = "kv"))]
66 if kvs.is_some() {
67 {
::core::panicking::panic_fmt(format_args!("key-value support is experimental and must be enabled using the `kv` feature"));
}panic!("key-value support is experimental and must be enabled using the `kv` feature")
68 }
69
70 let mut builder = Record::builder();
71
72 builder
73 .args(args)
74 .level(level)
75 .target(target)
76 .module_path_static(Some(module_path))
77 .file_static(Some(loc.file()))
78 .line(Some(loc.line()));
79
80 #[cfg(feature = "kv")]
81 builder.key_values(&kvs);
82
83 logger.log(&builder.build());
84}
85
86pub fn log<'a, K, L>(
87 logger: L,
88 args: Arguments,
89 level: Level,
90 target_module_path_and_loc: &(&str, &'static str, &'static Location),
91 kvs: K,
92) where
93 K: KVs<'a>,
94 L: Log,
95{
96 log_impl(
97 logger,
98 args,
99 level,
100 target_module_path_and_loc,
101 kvs.into_kvs(),
102 )
103}
104
105pub fn enabled<L: Log>(logger: L, level: Level, target: &str) -> bool {
106 logger.enabled(&Metadata::builder().level(level).target(target).build())
107}
108
109#[track_caller]
110pub fn loc() -> &'static Location<'static> {
111 Location::caller()
112}
113
114#[cfg(feature = "kv")]
115mod kv_support {
116 use crate::kv;
117
118 pub type Key<'a> = kv::Key<'a>;
119 pub type Value<'a> = kv::Value<'a>;
120
121 pub fn capture_to_value<'a, V: kv::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> {
126 v.to_value()
127 }
128
129 pub fn capture_debug<'a, V: core::fmt::Debug + ?Sized>(v: &'a &'a V) -> Value<'a> {
130 Value::from_debug(v)
131 }
132
133 pub fn capture_display<'a, V: core::fmt::Display + ?Sized>(v: &'a &'a V) -> Value<'a> {
134 Value::from_display(v)
135 }
136
137 #[cfg(feature = "kv_std")]
138 pub fn capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a> {
139 Value::from_dyn_error(v)
140 }
141
142 #[cfg(feature = "kv_sval")]
143 pub fn capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a> {
144 Value::from_sval(v)
145 }
146
147 #[cfg(feature = "kv_serde")]
148 pub fn capture_serde<'a, V: serde_core::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> {
149 Value::from_serde(v)
150 }
151}
152
153#[cfg(feature = "kv")]
154pub use self::kv_support::*;