Skip to content

Commit f7abf9c

Browse files
authored
Allow building a Logger yourself (#53)
* make logger build public * ensure logger keeps printed records consistent
1 parent 1321306 commit f7abf9c

3 files changed

Lines changed: 76 additions & 13 deletions

File tree

examples/direct_logger.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*!
2+
Using `env_logger::Logger` and the `log::Log` trait directly.
3+
4+
This example doesn't rely on environment variables, or having a static logger installed.
5+
*/
6+
7+
extern crate log;
8+
extern crate env_logger;
9+
10+
fn record() -> log::Record<'static> {
11+
let error_metadata = log::MetadataBuilder::new()
12+
.target("myApp")
13+
.level(log::Level::Error)
14+
.build();
15+
16+
log::Record::builder()
17+
.metadata(error_metadata)
18+
.args(format_args!("Error!"))
19+
.line(Some(433))
20+
.file(Some("app.rs"))
21+
.module_path(Some("server"))
22+
.build()
23+
}
24+
25+
fn main() {
26+
use log::Log;
27+
28+
let stylish_logger = env_logger::Builder::new()
29+
.filter(None, log::LevelFilter::Error)
30+
.write_style(env_logger::WriteStyle::Always)
31+
.build();
32+
33+
let unstylish_logger = env_logger::Builder::new()
34+
.filter(None, log::LevelFilter::Error)
35+
.write_style(env_logger::WriteStyle::Never)
36+
.build();
37+
38+
stylish_logger.log(&record());
39+
unstylish_logger.log(&record());
40+
}

src/fmt.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub use termcolor::Color;
6767
/// [`style`]: #method.style
6868
pub struct Formatter {
6969
buf: Rc<RefCell<Buffer>>,
70+
write_style: WriteStyle,
7071
}
7172

7273
/// A set of styles to apply to the terminal output.
@@ -179,7 +180,16 @@ impl Default for WriteStyle {
179180
}
180181

181182
/// A terminal target with color awareness.
182-
pub(crate) struct Writer(BufferWriter);
183+
pub(crate) struct Writer {
184+
inner: BufferWriter,
185+
write_style: WriteStyle,
186+
}
187+
188+
impl Writer {
189+
pub(crate) fn write_style(&self) -> WriteStyle {
190+
self.write_style
191+
}
192+
}
183193

184194
/// A builder for a terminal writer.
185195
///
@@ -232,7 +242,10 @@ impl Builder {
232242
Target::Stdout => BufferWriter::stdout(color_choice),
233243
};
234244

235-
Writer(writer)
245+
Writer {
246+
inner: writer,
247+
write_style: self.write_style,
248+
}
236249
}
237250
}
238251

@@ -355,10 +368,15 @@ impl Style {
355368
impl Formatter {
356369
pub(crate) fn new(writer: &Writer) -> Self {
357370
Formatter {
358-
buf: Rc::new(RefCell::new(writer.0.buffer())),
371+
buf: Rc::new(RefCell::new(writer.inner.buffer())),
372+
write_style: writer.write_style(),
359373
}
360374
}
361375

376+
pub(crate) fn write_style(&self) -> WriteStyle {
377+
self.write_style
378+
}
379+
362380
/// Begin a new [`Style`].
363381
///
364382
/// # Examples
@@ -414,7 +432,7 @@ impl Formatter {
414432
}
415433

416434
pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> {
417-
writer.0.print(&self.buf.borrow())
435+
writer.inner.print(&self.buf.borrow())
418436
}
419437

420438
pub(crate) fn clear(&mut self) {

src/lib.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! A simple logger configured via an environment variable which writes
11+
//! A simple logger configured via environment variables which writes
1212
//! to stdout or stderr, for use with the logging facade exposed by the
1313
//! [`log` crate][log-crate-url].
1414
//!
@@ -426,7 +426,7 @@ impl Builder {
426426
/// This method is kept private because the only way we support building
427427
/// loggers is by installing them as the single global logger for the
428428
/// `log` crate.
429-
fn build(&mut self) -> Logger {
429+
pub fn build(&mut self) -> Logger {
430430
Logger {
431431
writer: self.writer.build(),
432432
filter: self.filter.build(),
@@ -460,11 +460,9 @@ impl Log for Logger {
460460
// so will always at least have capacity for the largest log record formatted
461461
// on that thread.
462462
//
463-
// Because these buffers are tied to a particular logger, we don't let callers
464-
// create instances of `Logger` themselves, or they'll race to configure the
465-
// thread local buffer with their own configuration. This is still potentially
466-
// an issue if a caller attempts to set and use the global logger multiple times,
467-
// but in that case it's clearer that there's shared state at play.
463+
// If multiple `Logger`s are used by the same threads then the thread-local
464+
// formatter might have different color support. If this is the case the
465+
// formatter and its buffer are discarded and recreated.
468466

469467
thread_local! {
470468
static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
@@ -473,8 +471,15 @@ impl Log for Logger {
473471
FORMATTER.with(|tl_buf| {
474472
let mut tl_buf = tl_buf.borrow_mut();
475473

476-
if tl_buf.is_none() {
477-
*tl_buf = Some(Formatter::new(&self.writer));
474+
// Check the buffer style. If it's different from the logger's
475+
// style then drop the buffer and recreate it.
476+
match *tl_buf {
477+
Some(ref mut formatter) => {
478+
if formatter.write_style() != self.writer.write_style() {
479+
*formatter = Formatter::new(&self.writer)
480+
}
481+
},
482+
ref mut tl_buf => *tl_buf = Some(Formatter::new(&self.writer))
478483
}
479484

480485
// The format is guaranteed to be `Some` by this point

0 commit comments

Comments
 (0)