| 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 | |