Skip to content

Commit

Permalink
TermLogger: Use termcolor::BufferedStandardStream
Browse files Browse the repository at this point in the history
Without it, termcolor issues _many, many_ small writes. This
increases performance by several orders of magnitude, at least on Linux.
Users should call log::Logger::flush() to flush the log as-desired.
  • Loading branch information
mrkline committed Sep 21, 2021
1 parent ea98623 commit 1b1bb5b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "simplelog"
version = "0.10.0"
version = "0.10.1"
edition = "2018"
authors = ["Drakulix <github@drakulix.de>"]
description = "A simple and easy-to-use logging facility for Rust's log crate"
Expand Down
58 changes: 19 additions & 39 deletions src/loggers/termlog.rs
Expand Up @@ -5,29 +5,15 @@ use log::{
};
use std::io::{Error, Write};
use std::sync::Mutex;
use termcolor::{ColorChoice, ColorSpec, StandardStream, WriteColor};
use termcolor::{BufferedStandardStream, ColorChoice, ColorSpec, WriteColor};

use super::logging::*;

use crate::{Config, SharedLogger, ThreadLogMode};

enum StdTerminal {
Stderr(Box<dyn WriteColor + Send>),
Stdout(Box<dyn WriteColor + Send>),
}

impl StdTerminal {
fn flush(&mut self) -> Result<(), Error> {
match self {
StdTerminal::Stderr(term) => term.flush(),
StdTerminal::Stdout(term) => term.flush(),
}
}
}

struct OutputStreams {
err: StdTerminal,
out: StdTerminal,
err: BufferedStandardStream,
out: BufferedStandardStream,
}

/// Specifies which streams should be used when logging
Expand Down Expand Up @@ -117,16 +103,16 @@ impl TermLogger {
) -> Box<TermLogger> {
let streams = match mode {
TerminalMode::Stdout => OutputStreams {
err: StdTerminal::Stdout(Box::new(StandardStream::stdout(color_choice))),
out: StdTerminal::Stdout(Box::new(StandardStream::stdout(color_choice))),
err: BufferedStandardStream::stdout(color_choice),
out: BufferedStandardStream::stdout(color_choice),
},
TerminalMode::Stderr => OutputStreams {
err: StdTerminal::Stderr(Box::new(StandardStream::stderr(color_choice))),
out: StdTerminal::Stderr(Box::new(StandardStream::stderr(color_choice))),
err: BufferedStandardStream::stderr(color_choice),
out: BufferedStandardStream::stderr(color_choice),
},
TerminalMode::Mixed => OutputStreams {
err: StdTerminal::Stderr(Box::new(StandardStream::stderr(color_choice))),
out: StdTerminal::Stdout(Box::new(StandardStream::stdout(color_choice))),
err: BufferedStandardStream::stderr(color_choice),
out: BufferedStandardStream::stdout(color_choice),
},
};

Expand All @@ -140,40 +126,40 @@ impl TermLogger {
fn try_log_term(
&self,
record: &Record<'_>,
term_lock: &mut Box<dyn WriteColor + Send>,
term_lock: &mut BufferedStandardStream,
) -> Result<(), Error> {
let color = self.config.level_color[record.level() as usize];

if self.config.time <= record.level() && self.config.time != LevelFilter::Off {
write_time(&mut *term_lock, &self.config)?;
write_time(term_lock, &self.config)?;
}

if self.config.level <= record.level() && self.config.level != LevelFilter::Off {
term_lock.set_color(ColorSpec::new().set_fg(color))?;
write_level(record, &mut *term_lock, &self.config)?;
write_level(record, term_lock, &self.config)?;
term_lock.reset()?;
}

if self.config.thread <= record.level() && self.config.thread != LevelFilter::Off {
match self.config.thread_log_mode {
ThreadLogMode::IDs => {
write_thread_id(&mut *term_lock, &self.config)?;
write_thread_id(term_lock, &self.config)?;
}
ThreadLogMode::Names | ThreadLogMode::Both => {
write_thread_name(&mut *term_lock, &self.config)?;
write_thread_name(term_lock, &self.config)?;
}
}
}

if self.config.target <= record.level() && self.config.target != LevelFilter::Off {
write_target(record, &mut *term_lock)?;
write_target(record, term_lock)?;
}

if self.config.location <= record.level() && self.config.location != LevelFilter::Off {
write_location(record, &mut *term_lock)?;
write_location(record, term_lock)?;
}

write_args(record, &mut *term_lock)
write_args(record, term_lock)
}

fn try_log(&self, record: &Record<'_>) -> Result<(), Error> {
Expand All @@ -185,15 +171,9 @@ impl TermLogger {
let mut streams = self.streams.lock().unwrap();

if record.level() == Level::Error {
match streams.err {
StdTerminal::Stderr(ref mut term) => self.try_log_term(record, term),
StdTerminal::Stdout(ref mut term) => self.try_log_term(record, term),
}
self.try_log_term(record, &mut streams.err)
} else {
match streams.out {
StdTerminal::Stderr(ref mut term) => self.try_log_term(record, term),
StdTerminal::Stdout(ref mut term) => self.try_log_term(record, term),
}
self.try_log_term(record, &mut streams.out)
}
} else {
Ok(())
Expand Down

0 comments on commit 1b1bb5b

Please sign in to comment.