diff --git a/Cargo.lock b/Cargo.lock index 2bb97a6a..d35a745a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.10.1" @@ -117,6 +127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", + "value-bag", ] [[package]] @@ -125,6 +136,24 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + [[package]] name = "regex" version = "1.7.0" @@ -156,6 +185,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -165,6 +205,28 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 7a1ae457..3d565de5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ color = ["dep:termcolor"] auto-color = ["dep:is-terminal", "color"] humantime = ["dep:humantime"] regex = ["dep:regex"] +kv_unstable = ["log/kv_unstable"] [dependencies] log = { version = "0.4.8", features = ["std"] } diff --git a/src/fmt/mod.rs b/src/fmt/mod.rs index ded40278..3808c7ce 100644 --- a/src/fmt/mod.rs +++ b/src/fmt/mod.rs @@ -51,6 +51,9 @@ pub(crate) mod glob { pub use super::{Target, TimestampPrecision, WriteStyle}; } +#[cfg(feature = "kv_unstable")] +use log::kv; + /// Formatting precision of timestamps. /// /// Seconds give precision of full seconds, milliseconds give thousands of a @@ -149,6 +152,9 @@ pub(crate) struct Builder { pub custom_format: Option, pub format_suffix: &'static str, built: bool, + + #[cfg(feature = "kv_unstable")] + pub format_key_values: bool, } impl Builder { @@ -181,6 +187,9 @@ impl Builder { indent: built.format_indent, suffix: built.format_suffix, buf, + + #[cfg(feature = "kv_unstable")] + key_values: built.format_key_values, }; fmt.write(record) @@ -200,6 +209,9 @@ impl Default for Builder { custom_format: None, format_suffix: "\n", built: false, + + #[cfg(feature = "kv_unstable")] + format_key_values: true, } } } @@ -221,6 +233,9 @@ struct DefaultFormat<'a> { indent: Option, buf: &'a mut Formatter, suffix: &'a str, + + #[cfg(feature = "kv_unstable")] + key_values: bool, } impl<'a> DefaultFormat<'a> { @@ -231,6 +246,9 @@ impl<'a> DefaultFormat<'a> { self.write_target(record)?; self.finish_header()?; + #[cfg(feature = "kv_unstable")] + self.write_key_values(record)?; + self.write_args(record) } @@ -338,6 +356,45 @@ impl<'a> DefaultFormat<'a> { } } + #[cfg(feature = "kv_unstable")] + fn write_key_values(&mut self, record: &Record) -> io::Result<()> { + if !self.key_values { + return Ok(()); + } + + struct KVVisitor<'a, 'b> { + fmt: &'a mut DefaultFormat<'b>, + visited: bool, + } + + impl<'kvs> kv::Visitor<'kvs> for KVVisitor { + fn visit_pair( + &mut self, + key: kv::Key<'kvs>, + value: kv::Value<'kvs>, + ) -> Result<(), kv::Error> { + if self.visited { + write!(self.fmt.buf, ", ")?; + } else { + self.visited = true; + } + write!(self.fmt.buf, "{}={}", key, value)?; + Ok(()) + } + } + + let mut visitor = KVVisitor { + fmt: self, + visited: false, + }; + record.key_values().visit(&mut visitor)?; + if visitor.visited { + write!(self.buf, ": ")?; + } + Ok(()) + } + + fn write_args(&mut self, record: &Record) -> io::Result<()> { match self.indent { // Fast path for no indentation diff --git a/src/logger.rs b/src/logger.rs index 6c8a00d4..99cb7942 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -312,6 +312,13 @@ impl Builder { self } + /// Configures if keys and values should be included. + #[cfg(feature = "kv_unstable")] + pub fn format_key_values(&mut self, value: bool) -> &mut Self { + self.format.format_key_values = value; + self + } + /// Adds a directive to the filter for a specific module. /// /// # Examples