1 | //! WARNING: this is not part of the crate's public API and is subject to change at any time |
2 | |
3 | use self::sealed::KVs; |
4 | use crate::{logger, Level, Log, Metadata, Record}; |
5 | use std::fmt::Arguments; |
6 | use std::panic::Location; |
7 | pub use std::{format_args, module_path, stringify}; |
8 | |
9 | #[cfg (not(feature = "kv" ))] |
10 | pub type Value<'a> = &'a str; |
11 | |
12 | mod 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 | |
21 | impl<'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 | |
28 | impl<'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 | |
37 | /// The global logger proxy. |
38 | #[derive (Debug)] |
39 | pub struct GlobalLogger; |
40 | |
41 | impl Log for GlobalLogger { |
42 | fn enabled(&self, metadata: &Metadata) -> bool { |
43 | logger().enabled(metadata) |
44 | } |
45 | |
46 | fn log(&self, record: &Record) { |
47 | logger().log(record) |
48 | } |
49 | |
50 | fn flush(&self) { |
51 | logger().flush() |
52 | } |
53 | } |
54 | |
55 | // Split from `log` to reduce generics and code size |
56 | fn log_impl<L: Log>( |
57 | logger: L, |
58 | args: Arguments, |
59 | level: Level, |
60 | &(target: &str, module_path: &'static str, loc: &'static Location<'_>): &(&str, &'static str, &'static Location), |
61 | kvs: Option<&[(&str, Value)]>, |
62 | ) { |
63 | #[cfg (not(feature = "kv" ))] |
64 | if kvs.is_some() { |
65 | panic!("key-value support is experimental and must be enabled using the `kv` feature" ) |
66 | } |
67 | |
68 | let mut builder: RecordBuilder<'_> = Record::builder(); |
69 | |
70 | builder&mut RecordBuilder<'_> |
71 | .args(args) |
72 | .level(level) |
73 | .target(target) |
74 | .module_path_static(Some(module_path)) |
75 | .file_static(file:Some(loc.file())) |
76 | .line(Some(loc.line())); |
77 | |
78 | #[cfg (feature = "kv" )] |
79 | builder.key_values(&kvs); |
80 | |
81 | logger.log(&builder.build()); |
82 | } |
83 | |
84 | pub fn log<'a, K, L>( |
85 | logger: L, |
86 | args: Arguments, |
87 | level: Level, |
88 | target_module_path_and_loc: &(&str, &'static str, &'static Location), |
89 | kvs: K, |
90 | ) where |
91 | K: KVs<'a>, |
92 | L: Log, |
93 | { |
94 | log_impl( |
95 | logger, |
96 | args, |
97 | level, |
98 | target_module_path_and_loc, |
99 | kvs.into_kvs(), |
100 | ) |
101 | } |
102 | |
103 | pub fn enabled<L: Log>(logger: L, level: Level, target: &str) -> bool { |
104 | logger.enabled(&Metadata::builder().level(arg:level).target(target).build()) |
105 | } |
106 | |
107 | #[track_caller ] |
108 | pub fn loc() -> &'static Location<'static> { |
109 | Location::caller() |
110 | } |
111 | |
112 | #[cfg (feature = "kv" )] |
113 | mod kv_support { |
114 | use crate::kv; |
115 | |
116 | pub type Value<'a> = kv::Value<'a>; |
117 | |
118 | // NOTE: Many functions here accept a double reference &&V |
119 | // This is so V itself can be ?Sized, while still letting us |
120 | // erase it to some dyn Trait (because &T is sized) |
121 | |
122 | pub fn capture_to_value<'a, V: kv::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> { |
123 | v.to_value() |
124 | } |
125 | |
126 | pub fn capture_debug<'a, V: core::fmt::Debug + ?Sized>(v: &'a &'a V) -> Value<'a> { |
127 | Value::from_debug(v) |
128 | } |
129 | |
130 | pub fn capture_display<'a, V: core::fmt::Display + ?Sized>(v: &'a &'a V) -> Value<'a> { |
131 | Value::from_display(v) |
132 | } |
133 | |
134 | #[cfg (feature = "kv_std" )] |
135 | pub fn capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a> { |
136 | Value::from_dyn_error(v) |
137 | } |
138 | |
139 | #[cfg (feature = "kv_sval" )] |
140 | pub fn capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a> { |
141 | Value::from_sval(v) |
142 | } |
143 | |
144 | #[cfg (feature = "kv_serde" )] |
145 | pub fn capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> { |
146 | Value::from_serde(v) |
147 | } |
148 | } |
149 | |
150 | #[cfg (feature = "kv" )] |
151 | pub use self::kv_support::*; |
152 | |