Skip to content

Commit

Permalink
Merge pull request #53 from mulark/master
Browse files Browse the repository at this point in the history
Add logging for named threads and thread field padding
  • Loading branch information
Drakulix committed Mar 28, 2020
2 parents a2fb655 + 82c9963 commit 39a5cb5
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 7 deletions.
40 changes: 39 additions & 1 deletion src/config.rs
Expand Up @@ -14,6 +14,28 @@ pub enum LevelPadding {
Off,
}

#[derive(Debug, Clone, Copy)]
/// Padding to be used for logging the thread id/name
pub enum ThreadPadding {
/// Add spaces on the left side, up to usize many
Left(usize),
/// Add spaces on the right side, up to usize many
Right(usize),
/// Do not pad the thread id/name
Off,
}

#[derive(Debug, Clone, Copy, PartialEq)]
/// Mode for logging the thread name or id or both.
pub enum ThreadLogMode {
/// Log thread ids only
IDs,
/// Log the thread names only
Names,
/// If this thread is named, log the name. Otherwise, log the thread id.
Both,
}

/// Configuration for the Loggers
///
/// All loggers print the message in the following form:
Expand All @@ -30,6 +52,8 @@ pub struct Config {
pub(crate) level: LevelFilter,
pub(crate) level_padding: LevelPadding,
pub(crate) thread: LevelFilter,
pub(crate) thread_log_mode: ThreadLogMode,
pub(crate) thread_padding: ThreadPadding,
pub(crate) target: LevelFilter,
pub(crate) location: LevelFilter,
pub(crate) time_format: Cow<'static, str>,
Expand Down Expand Up @@ -97,6 +121,18 @@ impl ConfigBuilder {
self
}

/// Set how the thread should be padded
pub fn set_thread_padding<'a>(&'a mut self, padding: ThreadPadding) -> &'a mut ConfigBuilder {
self.0.thread_padding = padding;
self
}

/// Set the mode for logging the thread
pub fn set_thread_mode<'a>(&'a mut self, mode: ThreadLogMode) -> &'a mut ConfigBuilder {
self.0.thread_log_mode = mode;
self
}

/// Set time chrono strftime format string. See: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers
pub fn set_time_format_str<'a>(
&'a mut self,
Expand Down Expand Up @@ -127,7 +163,7 @@ impl ConfigBuilder {
/// Add allowed module filters.
/// If any are specified, only records from modules starting with one of these entries will be printed
///
/// For example, `add_filter_allow_str("tokio::uds")` would allow only logging from the `tokio` crates `uds` module.
/// For example, `add_filter_allow_str("tokio::uds")` would allow only logging from the `tokio` crates `uds` module.
pub fn add_filter_allow_str<'a>(
&'a mut self,
time_format: &'static str,
Expand Down Expand Up @@ -201,6 +237,8 @@ impl Default for Config {
level: LevelFilter::Error,
level_padding: LevelPadding::Left,
thread: LevelFilter::Debug,
thread_log_mode: ThreadLogMode::IDs,
thread_padding: ThreadPadding::Off,
target: LevelFilter::Debug,
location: LevelFilter::Trace,
time_format: Cow::Borrowed("%H:%M:%S"),
Expand Down
19 changes: 18 additions & 1 deletion src/lib.rs
Expand Up @@ -24,7 +24,7 @@
mod config;
mod loggers;

pub use self::config::{Config, ConfigBuilder, LevelPadding};
pub use self::config::{Config, ConfigBuilder, LevelPadding, ThreadPadding, ThreadLogMode};
#[cfg(feature = "test")]
pub use self::loggers::TestLogger;
pub use self::loggers::{CombinedLogger, SimpleLogger, WriteLogger};
Expand Down Expand Up @@ -92,6 +92,16 @@ mod tests {
let mut vec = Vec::new();
let mut conf_builder = ConfigBuilder::new();

let conf_thread_name = ConfigBuilder::new()
.set_time_level(LevelFilter::Off)
.set_thread_level(LevelFilter::Error)
.set_thread_mode(ThreadLogMode::Names)
.build();

vec.push(
WriteLogger::new(LevelFilter::Error, conf_thread_name, File::create("thread_naming.log").unwrap()) as Box<dyn SharedLogger>
);

for elem in vec![
LevelFilter::Off,
LevelFilter::Trace,
Expand Down Expand Up @@ -204,6 +214,13 @@ mod tests {
debug!("Test Debug");
trace!("Test Trace");

let mut thread_naming = String::new();
File::open("thread_naming.log").unwrap().read_to_string(&mut thread_naming).unwrap();

if let Some(name) = std::thread::current().name() {
assert!(thread_naming.contains(&format!("({})", name)));
}

for j in 1..i {
let mut error = String::new();
File::open(&format!("error_{}.log", j))
Expand Down
48 changes: 44 additions & 4 deletions src/loggers/logging.rs
@@ -1,4 +1,4 @@
use crate::{Config, LevelPadding};
use crate::{Config, LevelPadding, ThreadPadding, ThreadLogMode};
use chrono;
use log::{LevelFilter, Record};
use std::io::{Error, Write};
Expand All @@ -22,7 +22,14 @@ where
}

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

if config.target <= record.level() && config.target != LevelFilter::Off {
Expand Down Expand Up @@ -87,14 +94,47 @@ where
Ok(())
}

pub fn write_thread_id<W>(write: &mut W) -> Result<(), Error>
pub fn write_thread_name<W>(write: &mut W, config: &Config) -> Result<(), Error>
where
W: Write + Sized,
{
if let Some(name) = thread::current().name() {
match config.thread_padding {
ThreadPadding::Left{0: qty} => {
write!(write, "({name:>0$}) ", qty, name=name)?;
}
ThreadPadding::Right{0: qty} => {
write!(write, "({name:<0$}) ", qty, name=name)?;
}
ThreadPadding::Off => {
write!(write, "({}) ", name)?;
}
}
} else if config.thread_log_mode == ThreadLogMode::Both {
write_thread_id(write, config)?;
}

Ok(())
}

pub fn write_thread_id<W>(write: &mut W, config: &Config) -> Result<(), Error>
where
W: Write + Sized,
{
let id = format!("{:?}", thread::current().id());
let id = id.replace("ThreadId(", "");
let id = id.replace(")", "");
write!(write, "({}) ", id)?;
match config.thread_padding {
ThreadPadding::Left{0: qty} => {
write!(write, "({id:>0$}) ", qty, id=id)?;
}
ThreadPadding::Right{0: qty} => {
write!(write, "({id:<0$}) ", qty, id=id)?;
}
ThreadPadding::Off => {
write!(write, "({}) ", id)?;
}
}
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion src/loggers/termlog.rs
Expand Up @@ -241,7 +241,7 @@ impl TermLogger {
}

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

if self.config.target <= record.level() && self.config.target != LevelFilter::Off {
Expand Down

0 comments on commit 39a5cb5

Please sign in to comment.