1 #![cfg_attr(test, deny(warnings))]
2 #![deny(missing_docs)]
3 #![doc(html_root_url = "https://docs.rs/pretty_env_logger/0.3.1")]
4 
5 //! A logger configured via an environment variable which writes to standard
6 //! error with nice colored output for log levels.
7 //!
8 //! ## Example
9 //!
10 //! ```
11 //! extern crate pretty_env_logger;
12 //! #[macro_use] extern crate log;
13 //!
14 //! fn main() {
15 //!     pretty_env_logger::init();
16 //!
17 //!     trace!("a trace example");
18 //!     debug!("deboogging");
19 //!     info!("such information");
20 //!     warn!("o_O");
21 //!     error!("boom");
22 //! }
23 //! ```
24 
25 extern crate env_logger;
26 extern crate log;
27 extern crate chrono;
28 
29 use std::sync::atomic::{AtomicUsize, Ordering};
30 
31 use chrono::Local;
32 use env_logger::{fmt::{Color, Style, StyledValue}, Builder};
33 use log::Level;
34 
colored_level<'a>(style: &'a mut Style, level: Level) -> StyledValue<'a, &'static str>35 fn colored_level<'a>(style: &'a mut Style, level: Level) -> StyledValue<'a, &'static str> {
36     match level {
37         Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
38         Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
39         Level::Info => style.set_color(Color::Green).value("INFO "),
40         Level::Warn => style.set_color(Color::Yellow).value("WARN "),
41         Level::Error => style.set_color(Color::Red).value("ERROR"),
42     }
43 }
44 
45 static MAX_MODULE_WIDTH: AtomicUsize = AtomicUsize::new(0);
46 
47 /// Initializes the global logger with a pretty env logger.
48 ///
49 /// This should be called early in the execution of a Rust program, and the
50 /// global logger may only be initialized once. Future initialization attempts
51 /// will return an error.
52 ///
53 /// # Panics
54 ///
55 /// This function fails to set the global logger if one has already been set.
56 #[inline]
init()57 pub fn init() {
58     try_init().unwrap();
59 }
60 
61 /// Initializes the global logger with a timed pretty env logger.
62 ///
63 /// This should be called early in the execution of a Rust program, and the
64 /// global logger may only be initialized once. Future initialization attempts
65 /// will return an error.
66 ///
67 /// # Panics
68 ///
69 /// This function fails to set the global logger if one has already been set.
70 #[inline]
init_timed()71 pub fn init_timed() {
72     try_init_timed().unwrap();
73 }
74 
75 /// Initializes the global logger with a pretty env logger.
76 ///
77 /// This should be called early in the execution of a Rust program, and the
78 /// global logger may only be initialized once. Future initialization attempts
79 /// will return an error.
80 ///
81 /// # Errors
82 ///
83 /// This function fails to set the global logger if one has already been set.
try_init() -> Result<(), log::SetLoggerError>84 pub fn try_init() -> Result<(), log::SetLoggerError> {
85     try_init_custom_env("RUST_LOG")
86 }
87 
88 /// Initializes the global logger with a timed pretty env logger.
89 ///
90 /// This should be called early in the execution of a Rust program, and the
91 /// global logger may only be initialized once. Future initialization attempts
92 /// will return an error.
93 ///
94 /// # Errors
95 ///
96 /// This function fails to set the global logger if one has already been set.
try_init_timed() -> Result<(), log::SetLoggerError>97 pub fn try_init_timed() -> Result<(), log::SetLoggerError> {
98     try_init_timed_custom_env("RUST_LOG")
99 }
100 
101 /// Initialized the global logger with a pretty env logger, with a custom variable name.
102 ///
103 /// This should be called early in the execution of a Rust program, and the
104 /// global logger may only be initialized once. Future initialization attempts
105 /// will return an error.
106 ///
107 /// # Panics
108 ///
109 /// This function fails to set the global logger if one has already been set.
init_custom_env(environment_variable_name: &str)110 pub fn init_custom_env(environment_variable_name: &str) {
111     try_init_custom_env(environment_variable_name).unwrap();
112 }
113 
114 /// Initialized the global logger with a pretty env logger, with a custom variable name.
115 ///
116 /// This should be called early in the execution of a Rust program, and the
117 /// global logger may only be initialized once. Future initialization attempts
118 /// will return an error.
119 ///
120 /// # Errors
121 ///
122 /// This function fails to set the global logger if one has already been set.
try_init_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError>123 pub fn try_init_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
124     let mut builder = formatted_builder();
125 
126     if let Ok(s) = ::std::env::var(environment_variable_name) {
127         builder.parse_filters(&s);
128     }
129 
130     builder.try_init()
131 }
132 
133 /// Initialized the global logger with a timed pretty env logger, with a custom variable name.
134 ///
135 /// This should be called early in the execution of a Rust program, and the
136 /// global logger may only be initialized once. Future initialization attempts
137 /// will return an error.
138 ///
139 /// # Errors
140 ///
141 /// This function fails to set the global logger if one has already been set.
try_init_timed_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError>142 pub fn try_init_timed_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
143     let mut builder = formatted_timed_builder();
144 
145     if let Ok(s) = ::std::env::var(environment_variable_name) {
146         builder.parse_filters(&s);
147     }
148 
149     builder.try_init()
150 }
151 
152 /// Returns a `env_logger::Builder` for further customization.
153 ///
154 /// This method will return a colored and formatted `env_logger::Builder`
155 /// for further customization. Refer to env_logger::Build crate documentation
156 /// for further details and usage.
formatted_builder() -> Builder157 pub fn formatted_builder() -> Builder {
158     let mut builder = Builder::new();
159 
160     builder.format(|f, record| {
161         use std::io::Write;
162         let target = record.target();
163         let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
164         if max_width < target.len() {
165             MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
166             max_width = target.len();
167         }
168 
169 
170         let mut style = f.style();
171         let level = colored_level(&mut style, record.level());
172         let mut style = f.style();
173         let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
174         writeln!(
175             f,
176             " {} {} > {}",
177             level,
178             target,
179             record.args(),
180         )
181     });
182 
183     builder
184 }
185 
186 /// Returns a `env_logger::Builder` for further customization.
187 ///
188 /// This method will return a colored and time formatted `env_logger::Builder`
189 /// for further customization. Refer to env_logger::Build crate documentation
190 /// for further details and usage.
formatted_timed_builder() -> Builder191 pub fn formatted_timed_builder() -> Builder {
192     let mut builder = Builder::new();
193 
194     builder.format(|f, record| {
195         use std::io::Write;
196         let target = record.target();
197         let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
198         if max_width < target.len() {
199             MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
200             max_width = target.len();
201         }
202 
203         let mut style = f.style();
204         let level = colored_level(&mut style, record.level());
205         let mut style = f.style();
206         let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
207         writeln!(
208             f,
209             " {} {} {} > {}",
210             Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"),
211             level,
212             target,
213             record.args(),
214         )
215     });
216 
217     builder
218 }
219