simplelog/loggers/
logging.rs

1use crate::{Config, LevelPadding, ThreadLogMode, ThreadPadding};
2use log::{LevelFilter, Record};
3use std::io::{Error, Write};
4use std::thread;
5
6#[inline(always)]
7pub fn try_log<W>(config: &Config, record: &Record<'_>, write: &mut W) -> Result<(), Error>
8where
9    W: Write + Sized,
10{
11    if should_skip(config, record) {
12        return Ok(());
13    }
14
15    if config.time <= record.level() && config.time != LevelFilter::Off {
16        write_time(write, config)?;
17    }
18
19    if config.level <= record.level() && config.level != LevelFilter::Off {
20        write_level(record, write, config)?;
21    }
22
23    if config.thread <= record.level() && config.thread != LevelFilter::Off {
24        match config.thread_log_mode {
25            ThreadLogMode::IDs => {
26                write_thread_id(write, config)?;
27            }
28            ThreadLogMode::Names | ThreadLogMode::Both => {
29                write_thread_name(write, config)?;
30            }
31        }
32    }
33
34    if config.target <= record.level() && config.target != LevelFilter::Off {
35        write_target(record, write)?;
36    }
37
38    if config.location <= record.level() && config.location != LevelFilter::Off {
39        write_location(record, write)?;
40    }
41
42    write_args(record, write)
43}
44
45#[inline(always)]
46pub fn write_time<W>(write: &mut W, config: &Config) -> Result<(), Error>
47where
48    W: Write + Sized,
49{
50    let cur_time = if config.time_local {
51        (chrono::Local::now() + config.time_offset).format(&*config.time_format)
52    } else {
53        (chrono::Utc::now() + config.time_offset).format(&*config.time_format)
54    };
55
56    write!(write, "{} ", cur_time)?;
57    Ok(())
58}
59
60#[inline(always)]
61pub fn write_level<W>(record: &Record<'_>, write: &mut W, config: &Config) -> Result<(), Error>
62where
63    W: Write + Sized,
64{
65    match config.level_padding {
66        LevelPadding::Left => write!(write, "[{: >5}] ", record.level())?,
67        LevelPadding::Right => write!(write, "[{: <5}] ", record.level())?,
68        LevelPadding::Off => write!(write, "[{}] ", record.level())?,
69    };
70    Ok(())
71}
72
73#[inline(always)]
74pub fn write_target<W>(record: &Record<'_>, write: &mut W) -> Result<(), Error>
75where
76    W: Write + Sized,
77{
78    write!(write, "{}: ", record.target())?;
79    Ok(())
80}
81
82#[inline(always)]
83pub fn write_location<W>(record: &Record<'_>, write: &mut W) -> Result<(), Error>
84where
85    W: Write + Sized,
86{
87    let file = record.file().unwrap_or("<unknown>");
88    if let Some(line) = record.line() {
89        write!(write, "[{}:{}] ", file, line)?;
90    } else {
91        write!(write, "[{}:<unknown>] ", file)?;
92    }
93    Ok(())
94}
95
96pub fn write_thread_name<W>(write: &mut W, config: &Config) -> Result<(), Error>
97where
98    W: Write + Sized,
99{
100    if let Some(name) = thread::current().name() {
101        match config.thread_padding {
102            ThreadPadding::Left { 0: qty } => {
103                write!(write, "({name:>0$}) ", qty, name = name)?;
104            }
105            ThreadPadding::Right { 0: qty } => {
106                write!(write, "({name:<0$}) ", qty, name = name)?;
107            }
108            ThreadPadding::Off => {
109                write!(write, "({}) ", name)?;
110            }
111        }
112    } else if config.thread_log_mode == ThreadLogMode::Both {
113        write_thread_id(write, config)?;
114    }
115
116    Ok(())
117}
118
119pub fn write_thread_id<W>(write: &mut W, config: &Config) -> Result<(), Error>
120where
121    W: Write + Sized,
122{
123    let id = format!("{:?}", thread::current().id());
124    let id = id.replace("ThreadId(", "");
125    let id = id.replace(")", "");
126    match config.thread_padding {
127        ThreadPadding::Left { 0: qty } => {
128            write!(write, "({id:>0$}) ", qty, id = id)?;
129        }
130        ThreadPadding::Right { 0: qty } => {
131            write!(write, "({id:<0$}) ", qty, id = id)?;
132        }
133        ThreadPadding::Off => {
134            write!(write, "({}) ", id)?;
135        }
136    }
137    Ok(())
138}
139
140#[inline(always)]
141pub fn write_args<W>(record: &Record<'_>, write: &mut W) -> Result<(), Error>
142where
143    W: Write + Sized,
144{
145    writeln!(write, "{}", record.args())?;
146    Ok(())
147}
148
149#[inline(always)]
150pub fn should_skip(config: &Config, record: &Record<'_>) -> bool {
151    // If a module path and allowed list are available
152    match (record.target(), &*config.filter_allow) {
153        (path, allowed) if !allowed.is_empty() => {
154            // Check that the module path matches at least one allow filter
155            if !allowed.iter().any(|v| path.starts_with(&**v)) {
156                // If not, skip any further writing
157                return true;
158            }
159        }
160        _ => {}
161    }
162
163    // If a module path and ignore list are available
164    match (record.target(), &*config.filter_ignore) {
165        (path, ignore) if !ignore.is_empty() => {
166            // Check that the module path does not match any ignore filters
167            if ignore.iter().any(|v| path.starts_with(&**v)) {
168                // If not, skip any further writing
169                return true;
170            }
171        }
172        _ => {}
173    }
174
175    false
176}