Skip to content

Commit

Permalink
feat: Add support for Key-Value data in log records.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmccombs committed Jan 24, 2024
1 parent 8f4361b commit 356702d
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 52 deletions.
62 changes: 62 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ color = ["dep:anstream", "dep:anstyle"]
auto-color = ["color", "anstream/auto"]
humantime = ["dep:humantime"]
regex = ["env_filter/regex"]
unstable-kv = ["log/kv_unstable"]

[dependencies]
log = { version = "0.4.8", features = ["std"] }
Expand Down
45 changes: 45 additions & 0 deletions src/fmt/kv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use std::io::{self, Write};

use super::Formatter;
use log::kv::{source::Source, Error, Key, Value, Visitor};

/// Format function for serializing key/value pairs
///
/// This trait determines how key/value pairs for structured logs are serialized within the default
/// format.
pub(crate) type KvFormatFn = dyn Fn(&mut Formatter, &dyn Source) -> io::Result<()> + Sync + Send;

/// Null Key Value Format
///
/// This function is intended to be passed to [`env_logger::Builder::format_key_values`].
///
/// This key value format simply ignores any key/value fields and doesn't include them in the
/// output.
pub fn hidden_kv_format(_formatter: &mut Formatter, _fields: &dyn Source) -> io::Result<()> {
Ok(())
}

/// Defualt Key Value Format
///
/// This function is intended to be passed to [`env_logger::Builder::format_key_values`].
///
/// This is the default key/value format. Which uses an "=" as the separator between the key and
/// value and a " " between each pair.
///
/// For example: `ip=127.0.0.1 port=123456 path=/example`
pub fn default_kv_format(formatter: &mut Formatter, fields: &dyn Source) -> io::Result<()> {
fields
.visit(&mut DefaultVisitor(formatter))
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
}

struct DefaultVisitor<'a>(&'a mut Formatter);

impl<'a, 'kvs> Visitor<'kvs> for DefaultVisitor<'a> {
fn visit_pair(&mut self, key: Key, value: Value<'kvs>) -> Result<(), Error> {
// TODO: add styling
// tracing-subscriber uses italic for the key and dimmed for the =
write!(self.0, " {}={}", key, value)?;
Ok(())
}
}
Loading

0 comments on commit 356702d

Please sign in to comment.