Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ include = [
test = []
default = ["termcolor", "local-offset"]
local-offset = ["time/local-offset"]
# requires log >= 0.4.21
kv = ["log/kv"]

[dependencies]
log = { version = "0.4.*", features = ["std"] }
Expand Down
30 changes: 30 additions & 0 deletions examples/kv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#[cfg(feature = "kv")]
fn main() {
use log::*;
use simplelog::*;

#[cfg(feature = "ansi_term")]
let config = ConfigBuilder::new()
.set_write_log_enable_colors(true)
.build();
#[cfg(not(feature = "ansi_term"))]
let config = Config::default();

TermLogger::init(
LevelFilter::Trace,
config,
TerminalMode::Stdout,
ColorChoice::Auto,
)
.unwrap();
error!(test = 1; "error with keys");
warn!(test = 2; "warning with keys");
info!(string = "value"; "info with keys");
debug!(dur = "5s"; "debug with keys");
trace!(test = 9000; "trace with keys");
}

#[cfg(not(feature = "kv"))]
fn main() {
println!("this example requires the kv feature.");
}
4 changes: 4 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ pub struct Config {
pub(crate) filter_ignore: Cow<'static, [Cow<'static, str>]>,
#[cfg(feature = "termcolor")]
pub(crate) level_color: [Option<Color>; 6],
#[cfg(all(feature = "termcolor", feature = "kv"))]
pub(crate) kv_key_color: Option<Color>,
pub(crate) write_log_enable_colors: bool,
#[cfg(feature = "paris")]
pub(crate) enable_paris_formatting: bool,
Expand Down Expand Up @@ -401,6 +403,8 @@ impl Default for Config {
Some(Color::Cyan), // Debug
Some(Color::White), // Trace
],
#[cfg(all(feature = "termcolor", feature = "kv"))]
kv_key_color: Some(Color::Yellow),

#[cfg(feature = "paris")]
enable_paris_formatting: true,
Expand Down
56 changes: 38 additions & 18 deletions src/loggers/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@ where
}

#[cfg(feature = "paris")]
return write_args(
record,
write,
config.enable_paris_formatting,
&config.line_ending,
);
write_args(record, write, config.enable_paris_formatting)?;
#[cfg(not(feature = "paris"))]
return write_args(record, write, &config.line_ending);
write_args(record, write)?;

#[cfg(feature = "kv")]
let _ = record.key_values().visit(&mut KvPrinter { write });

write!(write, "{}", config.line_ending)?;

Ok(())
}

#[inline(always)]
Expand Down Expand Up @@ -232,34 +234,28 @@ where

#[inline(always)]
#[cfg(feature = "paris")]
pub fn write_args<W>(
record: &Record<'_>,
write: &mut W,
with_colors: bool,
line_ending: &str,
) -> Result<(), Error>
pub fn write_args<W>(record: &Record<'_>, write: &mut W, with_colors: bool) -> Result<(), Error>
where
W: Write + Sized,
{
write!(
write,
"{}{}",
"{}",
crate::__private::paris::formatter::format_string(
format!("{}", record.args()),
with_colors
),
line_ending
)
)?;
Ok(())
}

#[inline(always)]
#[cfg(not(feature = "paris"))]
pub fn write_args<W>(record: &Record<'_>, write: &mut W, line_ending: &str) -> Result<(), Error>
pub fn write_args<W>(record: &Record<'_>, write: &mut W) -> Result<(), Error>
where
W: Write + Sized,
{
write!(write, "{}{}", record.args(), line_ending)?;
write!(write, "{}", record.args())?;
Ok(())
}

Expand Down Expand Up @@ -291,3 +287,27 @@ pub fn should_skip(config: &Config, record: &Record<'_>) -> bool {

false
}

#[cfg(feature = "kv")]
pub struct KvPrinter<'a, W>
where
W: Write + Sized,
{
pub write: &'a mut W,
}

#[cfg(feature = "kv")]
impl<'kv, W> log::kv::VisitSource<'kv> for KvPrinter<'kv, W>
where
W: Write + Sized,
{
fn visit_pair(
&mut self,
key: log::kv::Key<'kv>,
value: log::kv::Value<'kv>,
) -> Result<(), log::kv::Error> {
write!(self.write, " {key}={value:?}")?;

Ok(())
}
}
76 changes: 69 additions & 7 deletions src/loggers/termlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,19 @@ impl TermLogger {
}

#[cfg(feature = "paris")]
write_args(
record,
term_lock,
self.config.enable_paris_formatting,
&self.config.line_ending,
)?;
write_args(record, term_lock, self.config.enable_paris_formatting)?;
#[cfg(not(feature = "paris"))]
write_args(record, term_lock, &self.config.line_ending)?;
write_args(record, term_lock)?;

#[cfg(feature = "kv")]
// it's not possible to convert log::kv::Error into std::io::Error, though it's just inside
// can be ignored because error ignored in Log::log() anyway
let _ = record.key_values().visit(&mut KvTermPrinter {
config: &self.config,
write: term_lock,
});

write!(term_lock, "{}", self.config.line_ending)?;

// The log crate holds the logger as a `static mut`, which isn't dropped
// at program exit: https://doc.rust-lang.org/reference/items/static-items.html
Expand Down Expand Up @@ -241,3 +246,60 @@ impl SharedLogger for TermLogger {
Box::new(*self)
}
}

#[cfg(feature = "kv")]
struct KvTermPrinter<'a> {
config: &'a Config,
write: &'a mut BufferedStandardStream,
}

#[cfg(feature = "kv")]
impl<'kvs, 'c> log::kv::VisitSource<'kvs> for KvTermPrinter<'c> {
fn visit_pair(
&mut self,
key: log::kv::Key<'kvs>,
value: log::kv::Value<'kvs>,
) -> Result<(), log::kv::Error> {
write_term_kv_pair(key, value, self.write, self.config)?;

Ok(())
}
}

#[inline(always)]
#[cfg(feature = "kv")]
fn write_term_kv_pair<'kvs>(
key: log::kv::Key<'kvs>,
value: log::kv::Value<'kvs>,
write: &mut BufferedStandardStream,
#[cfg_attr(not(all(feature = "termcolor", feature = "ansi_term")), allow(unused))]
config: &Config,
) -> Result<(), Error> {
#[cfg(feature = "ansi_term")]
let color = match &config.kv_key_color {
Some(termcolor) if config.write_log_enable_colors => termcolor_to_ansiterm(termcolor),
_ => None,
};

#[cfg(feature = "ansi_term")]
match color {
Some(c) => write!(write, " {}={value:?}", c.paint(key.as_str()))?,
None => write!(write, " {key}={value:?}")?,
};

#[cfg(not(feature = "ansi_term"))]
{
use termcolor::{ColorSpec, WriteColor};

if !config.write_log_enable_colors {
write.set_color(ColorSpec::new().set_fg(config.kv_key_color))?;
}
write!(write, " {key}")?;
if !config.write_log_enable_colors {
write.reset()?;
}
write!(write, "={value:?}")?;
}

Ok(())
}
26 changes: 25 additions & 1 deletion src/loggers/testlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ pub fn log(config: &Config, record: &Record<'_>) {
}

write_args(record);

#[cfg(feature = "kv")]
let _ = record.key_values().visit(&mut KvTestPrinter);

println!();
}

#[inline(always)]
Expand Down Expand Up @@ -187,5 +192,24 @@ pub fn write_module(record: &Record<'_>) {

#[inline(always)]
pub fn write_args(record: &Record<'_>) {
println!("{}", record.args());
print!("{}", record.args());
}

#[cfg(feature = "kv")]
struct KvTestPrinter;

#[cfg(feature = "kv")]
impl<'kv> log::kv::VisitSource<'kv> for KvTestPrinter<'kv>
where
W: Write + Sized,
{
fn visit_pair(
&mut self,
key: log::kv::Key<'kv>,
value: log::kv::Value<'kv>,
) -> Result<(), log::kv::Error> {
print!(" {key}={value:?}");

Ok(())
}
}