Skip to content

Commit

Permalink
Add log::kv support
Browse files Browse the repository at this point in the history
  • Loading branch information
ellttBen committed May 7, 2024
1 parent f688e38 commit 230f2ea
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 18 deletions.
45 changes: 37 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
[package]
name = "log4rs"
version = "1.3.0"
authors = ["Steven Fackler <sfackler@gmail.com>", "Evan Simmons <esims89@gmail.com>"]
authors = [
"Steven Fackler <sfackler@gmail.com>",
"Evan Simmons <esims89@gmail.com>",
]
description = "A highly configurable multi-output logging implementation for the `log` facade"
license = "MIT OR Apache-2.0"
repository = "https://github.com/estk/log4rs"
Expand All @@ -13,7 +16,13 @@ rust-version = "1.69"
[features]
default = ["all_components", "config_parsing", "yaml_format"]

config_parsing = ["humantime", "serde", "serde-value", "typemap-ors", "log/serde"]
config_parsing = [
"humantime",
"serde",
"serde-value",
"typemap-ors",
"log/serde",
]
yaml_format = ["serde_yaml"]
json_format = ["serde_json"]
toml_format = ["toml"]
Expand All @@ -27,13 +36,21 @@ fixed_window_roller = []
size_trigger = []
time_trigger = ["rand"]
onstartup_trigger = []
json_encoder = ["serde", "serde_json", "chrono", "log-mdc", "log/serde", "thread-id"]
json_encoder = [
"serde",
"serde_json",
"chrono",
"log-mdc",
"log/serde",
"thread-id",
]
pattern_encoder = ["chrono", "log-mdc", "thread-id"]
ansi_writer = []
console_writer = ["ansi_writer", "libc", "winapi"]
simple_writer = []
threshold_filter = []
background_rotation = []
log_kv = ["log/kv"]

all_components = [
"console_appender",
Expand All @@ -47,7 +64,7 @@ all_components = [
"onstartup_trigger",
"json_encoder",
"pattern_encoder",
"threshold_filter"
"threshold_filter",
]

gzip = ["flate2"]
Expand All @@ -58,7 +75,9 @@ harness = false

[dependencies]
arc-swap = "1.6"
chrono = { version = "0.4.23", optional = true, features = ["clock"], default-features = false }
chrono = { version = "0.4.23", optional = true, features = [
"clock",
], default-features = false }
flate2 = { version = "1.0", optional = true }
fnv = "1.0"
humantime = { version = "2.1", optional = true }
Expand All @@ -72,14 +91,20 @@ serde_json = { version = "1.0", optional = true }
serde_yaml = { version = "0.9", optional = true }
toml = { version = "<0.8.10", optional = true }
parking_lot = { version = "0.12.0", optional = true }
rand = { version = "0.8", optional = true}
rand = { version = "0.8", optional = true }
thiserror = "1.0.15"
anyhow = "1.0.28"
derivative = "2.2"
once_cell = "1.17.1"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", optional = true, features = ["handleapi", "minwindef", "processenv", "winbase", "wincon"] }
winapi = { version = "0.3", optional = true, features = [
"handleapi",
"minwindef",
"processenv",
"winbase",
"wincon",
] }

[target.'cfg(not(windows))'.dependencies]
libc = { version = "0.2", optional = true }
Expand All @@ -98,7 +123,11 @@ required-features = ["json_encoder", "console_appender"]

[[example]]
name = "log_to_file"
required-features = ["console_appender", "file_appender", "rolling_file_appender"]
required-features = [
"console_appender",
"file_appender",
"rolling_file_appender",
]

[[example]]
name = "compile_time_config"
Expand Down
65 changes: 56 additions & 9 deletions src/encode/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
//! }
//! }
//! ```
//! If the `log_kv` feature is enabled, an additional `attributes` field will
//! contain a map of the record's [log::kv][log_kv] structured logging
//! attributes.
//!
//! [log_kv]: https://docs.rs/log/latest/log/kv/index.html

use chrono::{
format::{DelayedFormat, Fixed, Item},
Expand Down Expand Up @@ -76,6 +81,8 @@ impl JsonEncoder {
thread: thread.name(),
thread_id: thread_id::get(),
mdc: Mdc,
#[cfg(feature = "log_kv")]
attributes: kv::get_attributes(record.key_values())?,
};
message.serialize(&mut serde_json::Serializer::new(&mut *w))?;
w.write_all(NEWLINE.as_bytes())?;
Expand Down Expand Up @@ -106,6 +113,8 @@ struct Message<'a> {
thread: Option<&'a str>,
thread_id: usize,
mdc: Mdc,
#[cfg(feature = "log_kv")]
attributes: kv::Map,
}

fn ser_display<T, S>(v: &T, s: S) -> Result<S::Ok, S::Error>
Expand Down Expand Up @@ -162,6 +171,34 @@ impl Deserialize for JsonEncoderDeserializer {
Ok(Box::<JsonEncoder>::default())
}
}
#[cfg(feature = "log_kv")]
mod kv {
use log::kv::VisitSource;
use std::collections::BTreeMap;

pub(crate) type Map = BTreeMap<String, String>;

pub(crate) fn get_attributes(source: &dyn log::kv::Source) -> anyhow::Result<Map> {
struct Visitor {
inner: Map,
}
impl<'kvs> VisitSource<'kvs> for Visitor {
fn visit_pair(
&mut self,
key: log::kv::Key<'kvs>,
value: log::kv::Value<'kvs>,
) -> Result<(), log::kv::Error> {
self.inner.insert(format!("{key}"), format!("{value}"));
Ok(())
}
}
let mut visitor = Visitor {
inner: BTreeMap::new(),
};
source.visit(&mut visitor)?;
Ok(visitor.inner)
}
}

#[cfg(test)]
#[cfg(feature = "simple_writer")]
Expand Down Expand Up @@ -189,26 +226,35 @@ mod test {

let encoder = JsonEncoder::new();

let mut record_builder = Record::builder();
record_builder
.level(level)
.target(target)
.module_path(Some(module_path))
.file(Some(file))
.line(Some(line));

#[cfg(feature = "log_kv")]
record_builder.key_values(&[("log_foo", "log_bar")]);

let mut buf = vec![];
encoder
.encode_inner(
&mut SimpleWriter(&mut buf),
time,
&Record::builder()
.level(level)
.target(target)
.module_path(Some(module_path))
.file(Some(file))
.line(Some(line))
.args(format_args!("{}", message))
.build(),
&record_builder.args(format_args!("{}", message)).build(),
)
.unwrap();

#[cfg(feature = "log_kv")]
let expected_attributes = ",\"attributes\":{\"log_foo\":\"log_bar\"}";
#[cfg(not(feature = "log_kv"))]
let expected_attributes = "";

let expected = format!(
"{{\"time\":\"{}\",\"level\":\"{}\",\"message\":\"{}\",\"module_path\":\"{}\",\
\"file\":\"{}\",\"line\":{},\"target\":\"{}\",\
\"thread\":\"{}\",\"thread_id\":{},\"mdc\":{{\"foo\":\"bar\"}}}}",
\"thread\":\"{}\",\"thread_id\":{},\"mdc\":{{\"foo\":\"bar\"}}{}}}",
time.to_rfc3339(),
level,
message,
Expand All @@ -218,6 +264,7 @@ mod test {
target,
thread,
thread_id::get(),
expected_attributes
);
assert_eq!(expected, String::from_utf8(buf).unwrap().trim());
}
Expand Down
Loading

0 comments on commit 230f2ea

Please sign in to comment.