diff --git a/examples/direct_logger.rs b/examples/direct_logger.rs new file mode 100644 index 00000000..410230bc --- /dev/null +++ b/examples/direct_logger.rs @@ -0,0 +1,40 @@ +/*! +Using `env_logger::Logger` and the `log::Log` trait directly. + +This example doesn't rely on environment variables, or having a static logger installed. +*/ + +extern crate log; +extern crate env_logger; + +fn record() -> log::Record<'static> { + let error_metadata = log::MetadataBuilder::new() + .target("myApp") + .level(log::Level::Error) + .build(); + + log::Record::builder() + .metadata(error_metadata) + .args(format_args!("Error!")) + .line(Some(433)) + .file(Some("app.rs")) + .module_path(Some("server")) + .build() +} + +fn main() { + use log::Log; + + let stylish_logger = env_logger::Builder::new() + .filter(None, log::LevelFilter::Error) + .write_style(env_logger::WriteStyle::Always) + .build(); + + let unstylish_logger = env_logger::Builder::new() + .filter(None, log::LevelFilter::Error) + .write_style(env_logger::WriteStyle::Never) + .build(); + + stylish_logger.log(&record()); + unstylish_logger.log(&record()); +} \ No newline at end of file diff --git a/src/fmt.rs b/src/fmt.rs index 24e096dc..64e55169 100644 --- a/src/fmt.rs +++ b/src/fmt.rs @@ -67,6 +67,7 @@ pub use termcolor::Color; /// [`style`]: #method.style pub struct Formatter { buf: Rc>, + write_style: WriteStyle, } /// A set of styles to apply to the terminal output. @@ -179,7 +180,16 @@ impl Default for WriteStyle { } /// A terminal target with color awareness. -pub(crate) struct Writer(BufferWriter); +pub(crate) struct Writer { + inner: BufferWriter, + write_style: WriteStyle, +} + +impl Writer { + pub(crate) fn write_style(&self) -> WriteStyle { + self.write_style + } +} /// A builder for a terminal writer. /// @@ -232,7 +242,10 @@ impl Builder { Target::Stdout => BufferWriter::stdout(color_choice), }; - Writer(writer) + Writer { + inner: writer, + write_style: self.write_style, + } } } @@ -355,10 +368,15 @@ impl Style { impl Formatter { pub(crate) fn new(writer: &Writer) -> Self { Formatter { - buf: Rc::new(RefCell::new(writer.0.buffer())), + buf: Rc::new(RefCell::new(writer.inner.buffer())), + write_style: writer.write_style(), } } + pub(crate) fn write_style(&self) -> WriteStyle { + self.write_style + } + /// Begin a new [`Style`]. /// /// # Examples @@ -414,7 +432,7 @@ impl Formatter { } pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> { - writer.0.print(&self.buf.borrow()) + writer.inner.print(&self.buf.borrow()) } pub(crate) fn clear(&mut self) { diff --git a/src/lib.rs b/src/lib.rs index 98f59585..d9df2a83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A simple logger configured via an environment variable which writes +//! A simple logger configured via environment variables which writes //! to stdout or stderr, for use with the logging facade exposed by the //! [`log` crate][log-crate-url]. //! @@ -426,7 +426,7 @@ impl Builder { /// This method is kept private because the only way we support building /// loggers is by installing them as the single global logger for the /// `log` crate. - fn build(&mut self) -> Logger { + pub fn build(&mut self) -> Logger { Logger { writer: self.writer.build(), filter: self.filter.build(), @@ -460,11 +460,9 @@ impl Log for Logger { // so will always at least have capacity for the largest log record formatted // on that thread. // - // Because these buffers are tied to a particular logger, we don't let callers - // create instances of `Logger` themselves, or they'll race to configure the - // thread local buffer with their own configuration. This is still potentially - // an issue if a caller attempts to set and use the global logger multiple times, - // but in that case it's clearer that there's shared state at play. + // If multiple `Logger`s are used by the same threads then the thread-local + // formatter might have different color support. If this is the case the + // formatter and its buffer are discarded and recreated. thread_local! { static FORMATTER: RefCell> = RefCell::new(None); @@ -473,8 +471,15 @@ impl Log for Logger { FORMATTER.with(|tl_buf| { let mut tl_buf = tl_buf.borrow_mut(); - if tl_buf.is_none() { - *tl_buf = Some(Formatter::new(&self.writer)); + // Check the buffer style. If it's different from the logger's + // style then drop the buffer and recreate it. + match *tl_buf { + Some(ref mut formatter) => { + if formatter.write_style() != self.writer.write_style() { + *formatter = Formatter::new(&self.writer) + } + }, + ref mut tl_buf => *tl_buf = Some(Formatter::new(&self.writer)) } // The format is guaranteed to be `Some` by this point