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::{Level, 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 | fn log_impl( |
38 | args: Arguments, |
39 | level: Level, |
40 | &(target: &str, module_path: &'static str, loc: &'static Location<'_>): &(&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: RecordBuilder<'_> = Record::builder(); |
49 | |
50 | builder&mut RecordBuilder<'_> |
51 | .args(args) |
52 | .level(level) |
53 | .target(target) |
54 | .module_path_static(Some(module_path)) |
55 | .file_static(file: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 | |
64 | pub 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 | |
75 | pub fn enabled(level: Level, target: &str) -> bool { |
76 | crate::logger().enabled(&Metadata::builder().level(arg:level).target(target).build()) |
77 | } |
78 | |
79 | #[track_caller ] |
80 | pub fn loc() -> &'static Location<'static> { |
81 | Location::caller() |
82 | } |
83 | |
84 | #[cfg (feature = "kv" )] |
85 | mod 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" )] |
123 | pub use self::kv_support::*; |
124 | |