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