]> git.proxmox.com Git - rustc.git/blob - src/vendor/log/src/lib.rs
New upstream version 1.15.0+dfsg1
[rustc.git] / src / vendor / log / src / lib.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A lightweight logging facade.
12 //!
13 //! A logging facade provides a single logging API that abstracts over the
14 //! actual logging implementation. Libraries can use the logging API provided
15 //! by this crate, and the consumer of those libraries can choose the logging
16 //! framework that is most suitable for its use case.
17 //!
18 //! If no logging implementation is selected, the facade falls back to a "noop"
19 //! implementation that ignores all log messages. The overhead in this case
20 //! is very small - just an integer load, comparison and jump.
21 //!
22 //! A log request consists of a target, a level, and a body. A target is a
23 //! string which defaults to the module path of the location of the log
24 //! request, though that default may be overridden. Logger implementations
25 //! typically use the target to filter requests based on some user
26 //! configuration.
27 //!
28 //! # Use
29 //!
30 //! ## In libraries
31 //!
32 //! Libraries should link only to the `log` crate, and use the provided
33 //! macros to log whatever information will be useful to downstream consumers.
34 //!
35 //! ### Examples
36 //!
37 //! ```rust
38 //! # #![allow(unstable)]
39 //! #[macro_use]
40 //! extern crate log;
41 //!
42 //! # #[derive(Debug)] pub struct Yak(String);
43 //! # impl Yak { fn shave(&self, _: u32) {} }
44 //! # fn find_a_razor() -> Result<u32, u32> { Ok(1) }
45 //! pub fn shave_the_yak(yak: &Yak) {
46 //! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak);
47 //!
48 //! loop {
49 //! match find_a_razor() {
50 //! Ok(razor) => {
51 //! info!("Razor located: {}", razor);
52 //! yak.shave(razor);
53 //! break;
54 //! }
55 //! Err(err) => {
56 //! warn!("Unable to locate a razor: {}, retrying", err);
57 //! }
58 //! }
59 //! }
60 //! }
61 //! # fn main() {}
62 //! ```
63 //!
64 //! ## In executables
65 //!
66 //! Executables should choose a logging framework and initialize it early in the
67 //! runtime of the program. Logging frameworks will typically include a
68 //! function to do this. Any log messages generated before the framework is
69 //! initialized will be ignored.
70 //!
71 //! The executable itself may use the `log` crate to log as well.
72 //!
73 //! ### Warning
74 //!
75 //! The logging system may only be initialized once.
76 //!
77 //! ### Examples
78 //!
79 //! ```rust,ignore
80 //! #[macro_use]
81 //! extern crate log;
82 //! extern crate my_logger;
83 //!
84 //! fn main() {
85 //! my_logger::init();
86 //!
87 //! info!("starting up");
88 //!
89 //! // ...
90 //! }
91 //! ```
92 //!
93 //! # Logger implementations
94 //!
95 //! Loggers implement the `Log` trait. Here's a very basic example that simply
96 //! logs all messages at the `Error`, `Warn` or `Info` levels to stdout:
97 //!
98 //! ```rust
99 //! extern crate log;
100 //!
101 //! use log::{LogRecord, LogLevel, LogMetadata};
102 //!
103 //! struct SimpleLogger;
104 //!
105 //! impl log::Log for SimpleLogger {
106 //! fn enabled(&self, metadata: &LogMetadata) -> bool {
107 //! metadata.level() <= LogLevel::Info
108 //! }
109 //!
110 //! fn log(&self, record: &LogRecord) {
111 //! if self.enabled(record.metadata()) {
112 //! println!("{} - {}", record.level(), record.args());
113 //! }
114 //! }
115 //! }
116 //!
117 //! # fn main() {}
118 //! ```
119 //!
120 //! Loggers are installed by calling the `set_logger` function. It takes a
121 //! closure which is provided a `MaxLogLevel` token and returns a `Log` trait
122 //! object. The `MaxLogLevel` token controls the global maximum log level. The
123 //! logging facade uses this as an optimization to improve performance of log
124 //! messages at levels that are disabled. In the case of our example logger,
125 //! we'll want to set the maximum log level to `Info`, since we ignore any
126 //! `Debug` or `Trace` level log messages. A logging framework should provide a
127 //! function that wraps a call to `set_logger`, handling initialization of the
128 //! logger:
129 //!
130 //! ```rust
131 //! # extern crate log;
132 //! # use log::{LogLevel, LogLevelFilter, SetLoggerError, LogMetadata};
133 //! # struct SimpleLogger;
134 //! # impl log::Log for SimpleLogger {
135 //! # fn enabled(&self, _: &LogMetadata) -> bool { false }
136 //! # fn log(&self, _: &log::LogRecord) {}
137 //! # }
138 //! # fn main() {}
139 //! # #[cfg(feature = "use_std")]
140 //! pub fn init() -> Result<(), SetLoggerError> {
141 //! log::set_logger(|max_log_level| {
142 //! max_log_level.set(LogLevelFilter::Info);
143 //! Box::new(SimpleLogger)
144 //! })
145 //! }
146 //! ```
147 //!
148 //! # Use with `no_std`
149 //!
150 //! To use the `log` crate without depending on `libstd`, you need to specify
151 //! `default-features = false` when specifying the dependency in `Cargo.toml`.
152 //! This makes no difference to libraries using `log` since the logging API
153 //! remains the same. However executables will need to use the `set_logger_raw`
154 //! function to initialize a logger and the `shutdown_logger_raw` function to
155 //! shut down the global logger before exiting:
156 //!
157 //! ```rust
158 //! # extern crate log;
159 //! # use log::{LogLevel, LogLevelFilter, SetLoggerError, ShutdownLoggerError,
160 //! # LogMetadata};
161 //! # struct SimpleLogger;
162 //! # impl log::Log for SimpleLogger {
163 //! # fn enabled(&self, _: &LogMetadata) -> bool { false }
164 //! # fn log(&self, _: &log::LogRecord) {}
165 //! # }
166 //! # impl SimpleLogger {
167 //! # fn flush(&self) {}
168 //! # }
169 //! # fn main() {}
170 //! pub fn init() -> Result<(), SetLoggerError> {
171 //! unsafe {
172 //! log::set_logger_raw(|max_log_level| {
173 //! static LOGGER: SimpleLogger = SimpleLogger;
174 //! max_log_level.set(LogLevelFilter::Info);
175 //! &SimpleLogger
176 //! })
177 //! }
178 //! }
179 //! pub fn shutdown() -> Result<(), ShutdownLoggerError> {
180 //! log::shutdown_logger_raw().map(|logger| {
181 //! let logger = unsafe { &*(logger as *const SimpleLogger) };
182 //! logger.flush();
183 //! })
184 //! }
185 //! ```
186
187 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
188 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
189 html_root_url = "https://doc.rust-lang.org/log/")]
190 #![warn(missing_docs)]
191 #![cfg_attr(feature = "nightly", feature(panic_handler))]
192
193 #![cfg_attr(not(feature = "use_std"), no_std)]
194
195 #[cfg(not(feature = "use_std"))]
196 extern crate core as std;
197
198 use std::cmp;
199 #[cfg(feature = "use_std")]
200 use std::error;
201 use std::fmt;
202 use std::mem;
203 use std::ops::Deref;
204 use std::str::FromStr;
205 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
206 #[macro_use]
207 mod macros;
208
209 // The setup here is a bit weird to make shutdown_logger_raw work.
210 //
211 // There are four different states that we care about: the logger's
212 // uninitialized, the logger's initializing (set_logger's been called but
213 // LOGGER hasn't actually been set yet), the logger's active, or the logger is
214 // shut down after calling shutdown_logger_raw.
215 //
216 // The LOGGER static holds a pointer to the global logger. It is protected by
217 // the STATE static which determines whether LOGGER has been initialized yet.
218 //
219 // The shutdown_logger_raw routine needs to make sure that no threads are
220 // actively logging before it returns. The number of actively logging threads is
221 // tracked in the REFCOUNT static. The routine first sets STATE back to
222 // INITIALIZING. All logging calls past that point will immediately return
223 // without accessing the logger. At that point, the at_exit routine just waits
224 // for the refcount to reach 0 before deallocating the logger. Note that the
225 // refcount does not necessarily monotonically decrease at this point, as new
226 // log calls still increment and decrement it, but the interval in between is
227 // small enough that the wait is really just for the active log calls to finish.
228
229 static mut LOGGER: *const Log = &NopLogger;
230 static STATE: AtomicUsize = ATOMIC_USIZE_INIT;
231 static REFCOUNT: AtomicUsize = ATOMIC_USIZE_INIT;
232
233 const UNINITIALIZED: usize = 0;
234 const INITIALIZING: usize = 1;
235 const INITIALIZED: usize = 2;
236
237 static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT;
238
239 static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO",
240 "DEBUG", "TRACE"];
241
242 /// An enum representing the available verbosity levels of the logging framework
243 ///
244 /// A `LogLevel` may be compared directly to a `LogLevelFilter`.
245 #[repr(usize)]
246 #[derive(Copy, Eq, Debug)]
247 pub enum LogLevel {
248 /// The "error" level.
249 ///
250 /// Designates very serious errors.
251 Error = 1, // This way these line up with the discriminants for LogLevelFilter below
252 /// The "warn" level.
253 ///
254 /// Designates hazardous situations.
255 Warn,
256 /// The "info" level.
257 ///
258 /// Designates useful information.
259 Info,
260 /// The "debug" level.
261 ///
262 /// Designates lower priority information.
263 Debug,
264 /// The "trace" level.
265 ///
266 /// Designates very low priority, often extremely verbose, information.
267 Trace,
268 }
269
270 impl Clone for LogLevel {
271 #[inline]
272 fn clone(&self) -> LogLevel {
273 *self
274 }
275 }
276
277 impl PartialEq for LogLevel {
278 #[inline]
279 fn eq(&self, other: &LogLevel) -> bool {
280 *self as usize == *other as usize
281 }
282 }
283
284 impl PartialEq<LogLevelFilter> for LogLevel {
285 #[inline]
286 fn eq(&self, other: &LogLevelFilter) -> bool {
287 *self as usize == *other as usize
288 }
289 }
290
291 impl PartialOrd for LogLevel {
292 #[inline]
293 fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
294 Some(self.cmp(other))
295 }
296 }
297
298 impl PartialOrd<LogLevelFilter> for LogLevel {
299 #[inline]
300 fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
301 Some((*self as usize).cmp(&(*other as usize)))
302 }
303 }
304
305 impl Ord for LogLevel {
306 #[inline]
307 fn cmp(&self, other: &LogLevel) -> cmp::Ordering {
308 (*self as usize).cmp(&(*other as usize))
309 }
310 }
311
312 fn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> {
313 match t {
314 Some(t) => Ok(t),
315 None => Err(e),
316 }
317 }
318
319 // Reimplemented here because std::ascii is not available in libcore
320 fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {
321 fn to_ascii_uppercase(c: u8) -> u8 {
322 if c >= b'a' && c <= b'z' {
323 c - b'a' + b'A'
324 } else {
325 c
326 }
327 }
328
329 if a.len() == b.len() {
330 a.bytes()
331 .zip(b.bytes())
332 .all(|(a, b)| to_ascii_uppercase(a) == to_ascii_uppercase(b))
333 } else {
334 false
335 }
336 }
337
338 impl FromStr for LogLevel {
339 type Err = ();
340 fn from_str(level: &str) -> Result<LogLevel, ()> {
341 ok_or(LOG_LEVEL_NAMES.iter()
342 .position(|&name| eq_ignore_ascii_case(name, level))
343 .into_iter()
344 .filter(|&idx| idx != 0)
345 .map(|idx| LogLevel::from_usize(idx).unwrap())
346 .next(), ())
347 }
348 }
349
350 impl fmt::Display for LogLevel {
351 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
352 fmt.pad(LOG_LEVEL_NAMES[*self as usize])
353 }
354 }
355
356 impl LogLevel {
357 fn from_usize(u: usize) -> Option<LogLevel> {
358 match u {
359 1 => Some(LogLevel::Error),
360 2 => Some(LogLevel::Warn),
361 3 => Some(LogLevel::Info),
362 4 => Some(LogLevel::Debug),
363 5 => Some(LogLevel::Trace),
364 _ => None
365 }
366 }
367
368 /// Returns the most verbose logging level.
369 #[inline]
370 pub fn max() -> LogLevel {
371 LogLevel::Trace
372 }
373
374 /// Converts the `LogLevel` to the equivalent `LogLevelFilter`.
375 #[inline]
376 pub fn to_log_level_filter(&self) -> LogLevelFilter {
377 LogLevelFilter::from_usize(*self as usize).unwrap()
378 }
379 }
380
381 /// An enum representing the available verbosity level filters of the logging
382 /// framework.
383 ///
384 /// A `LogLevelFilter` may be compared directly to a `LogLevel`.
385 #[repr(usize)]
386 #[derive(Copy, Eq, Debug)]
387 pub enum LogLevelFilter {
388 /// A level lower than all log levels.
389 Off,
390 /// Corresponds to the `Error` log level.
391 Error,
392 /// Corresponds to the `Warn` log level.
393 Warn,
394 /// Corresponds to the `Info` log level.
395 Info,
396 /// Corresponds to the `Debug` log level.
397 Debug,
398 /// Corresponds to the `Trace` log level.
399 Trace,
400 }
401
402 // Deriving generates terrible impls of these traits
403
404 impl Clone for LogLevelFilter {
405 #[inline]
406 fn clone(&self) -> LogLevelFilter {
407 *self
408 }
409 }
410
411 impl PartialEq for LogLevelFilter {
412 #[inline]
413 fn eq(&self, other: &LogLevelFilter) -> bool {
414 *self as usize == *other as usize
415 }
416 }
417
418 impl PartialEq<LogLevel> for LogLevelFilter {
419 #[inline]
420 fn eq(&self, other: &LogLevel) -> bool {
421 other.eq(self)
422 }
423 }
424
425 impl PartialOrd for LogLevelFilter {
426 #[inline]
427 fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
428 Some(self.cmp(other))
429 }
430 }
431
432 impl PartialOrd<LogLevel> for LogLevelFilter {
433 #[inline]
434 fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
435 other.partial_cmp(self).map(|x| x.reverse())
436 }
437 }
438
439 impl Ord for LogLevelFilter {
440 #[inline]
441 fn cmp(&self, other: &LogLevelFilter) -> cmp::Ordering {
442 (*self as usize).cmp(&(*other as usize))
443 }
444 }
445
446 impl FromStr for LogLevelFilter {
447 type Err = ();
448 fn from_str(level: &str) -> Result<LogLevelFilter, ()> {
449 ok_or(LOG_LEVEL_NAMES.iter()
450 .position(|&name| eq_ignore_ascii_case(name, level))
451 .map(|p| LogLevelFilter::from_usize(p).unwrap()), ())
452 }
453 }
454
455 impl fmt::Display for LogLevelFilter {
456 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
457 write!(fmt, "{}", LOG_LEVEL_NAMES[*self as usize])
458 }
459 }
460
461 impl LogLevelFilter {
462 fn from_usize(u: usize) -> Option<LogLevelFilter> {
463 match u {
464 0 => Some(LogLevelFilter::Off),
465 1 => Some(LogLevelFilter::Error),
466 2 => Some(LogLevelFilter::Warn),
467 3 => Some(LogLevelFilter::Info),
468 4 => Some(LogLevelFilter::Debug),
469 5 => Some(LogLevelFilter::Trace),
470 _ => None
471 }
472 }
473 /// Returns the most verbose logging level filter.
474 #[inline]
475 pub fn max() -> LogLevelFilter {
476 LogLevelFilter::Trace
477 }
478
479 /// Converts `self` to the equivalent `LogLevel`.
480 ///
481 /// Returns `None` if `self` is `LogLevelFilter::Off`.
482 #[inline]
483 pub fn to_log_level(&self) -> Option<LogLevel> {
484 LogLevel::from_usize(*self as usize)
485 }
486 }
487
488 /// The "payload" of a log message.
489 pub struct LogRecord<'a> {
490 metadata: LogMetadata<'a>,
491 location: &'a LogLocation,
492 args: fmt::Arguments<'a>,
493 }
494
495 impl<'a> LogRecord<'a> {
496 /// The message body.
497 pub fn args(&self) -> &fmt::Arguments<'a> {
498 &self.args
499 }
500
501 /// Metadata about the log directive.
502 pub fn metadata(&self) -> &LogMetadata {
503 &self.metadata
504 }
505
506 /// The location of the log directive.
507 pub fn location(&self) -> &LogLocation {
508 self.location
509 }
510
511 /// The verbosity level of the message.
512 pub fn level(&self) -> LogLevel {
513 self.metadata.level()
514 }
515
516 /// The name of the target of the directive.
517 pub fn target(&self) -> &str {
518 self.metadata.target()
519 }
520 }
521
522 /// Metadata about a log message.
523 pub struct LogMetadata<'a> {
524 level: LogLevel,
525 target: &'a str,
526 }
527
528 impl<'a> LogMetadata<'a> {
529 /// The verbosity level of the message.
530 pub fn level(&self) -> LogLevel {
531 self.level
532 }
533
534 /// The name of the target of the directive.
535 pub fn target(&self) -> &str {
536 self.target
537 }
538 }
539
540 /// A trait encapsulating the operations required of a logger
541 pub trait Log: Sync+Send {
542 /// Determines if a log message with the specified metadata would be
543 /// logged.
544 ///
545 /// This is used by the `log_enabled!` macro to allow callers to avoid
546 /// expensive computation of log message arguments if the message would be
547 /// discarded anyway.
548 fn enabled(&self, metadata: &LogMetadata) -> bool;
549
550 /// Logs the `LogRecord`.
551 ///
552 /// Note that `enabled` is *not* necessarily called before this method.
553 /// Implementations of `log` should perform all necessary filtering
554 /// internally.
555 fn log(&self, record: &LogRecord);
556 }
557
558 // Just used as a dummy initial value for LOGGER
559 struct NopLogger;
560
561 impl Log for NopLogger {
562 fn enabled(&self, _: &LogMetadata) -> bool { false }
563
564 fn log(&self, _: &LogRecord) {}
565 }
566
567 /// The location of a log message.
568 ///
569 /// # Warning
570 ///
571 /// The fields of this struct are public so that they may be initialized by the
572 /// `log!` macro. They are subject to change at any time and should never be
573 /// accessed directly.
574 #[derive(Copy, Clone, Debug)]
575 pub struct LogLocation {
576 #[doc(hidden)]
577 pub __module_path: &'static str,
578 #[doc(hidden)]
579 pub __file: &'static str,
580 #[doc(hidden)]
581 pub __line: u32,
582 }
583
584 impl LogLocation {
585 /// The module path of the message.
586 pub fn module_path(&self) -> &str {
587 self.__module_path
588 }
589
590 /// The source file containing the message.
591 pub fn file(&self) -> &str {
592 self.__file
593 }
594
595 /// The line containing the message.
596 pub fn line(&self) -> u32 {
597 self.__line
598 }
599 }
600
601 /// A token providing read and write access to the global maximum log level
602 /// filter.
603 ///
604 /// The maximum log level is used as an optimization to avoid evaluating log
605 /// messages that will be ignored by the logger. Any message with a level
606 /// higher than the maximum log level filter will be ignored. A logger should
607 /// make sure to keep the maximum log level filter in sync with its current
608 /// configuration.
609 #[allow(missing_copy_implementations)]
610 pub struct MaxLogLevelFilter(());
611
612 impl fmt::Debug for MaxLogLevelFilter {
613 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
614 write!(fmt, "MaxLogLevelFilter")
615 }
616 }
617
618 impl MaxLogLevelFilter {
619 /// Gets the current maximum log level filter.
620 pub fn get(&self) -> LogLevelFilter {
621 max_log_level()
622 }
623
624 /// Sets the maximum log level.
625 pub fn set(&self, level: LogLevelFilter) {
626 MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
627 }
628 }
629
630 /// Returns the current maximum log level.
631 ///
632 /// The `log!`, `error!`, `warn!`, `info!`, `debug!`, and `trace!` macros check
633 /// this value and discard any message logged at a higher level. The maximum
634 /// log level is set by the `MaxLogLevel` token passed to loggers.
635 #[inline(always)]
636 pub fn max_log_level() -> LogLevelFilter {
637 unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
638 }
639
640 /// Sets the global logger.
641 ///
642 /// The `make_logger` closure is passed a `MaxLogLevel` object, which the
643 /// logger should use to keep the global maximum log level in sync with the
644 /// highest log level that the logger will not ignore.
645 ///
646 /// This function may only be called once in the lifetime of a program. Any log
647 /// events that occur before the call to `set_logger` completes will be
648 /// ignored.
649 ///
650 /// This function does not typically need to be called manually. Logger
651 /// implementations should provide an initialization method that calls
652 /// `set_logger` internally.
653 ///
654 /// Requires the `use_std` feature (enabled by default).
655 #[cfg(feature = "use_std")]
656 pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
657 where M: FnOnce(MaxLogLevelFilter) -> Box<Log> {
658 unsafe { set_logger_raw(|max_level| mem::transmute(make_logger(max_level))) }
659 }
660
661 /// Sets the global logger from a raw pointer.
662 ///
663 /// This function is similar to `set_logger` except that it is usable in
664 /// `no_std` code.
665 ///
666 /// The `make_logger` closure is passed a `MaxLogLevel` object, which the
667 /// logger should use to keep the global maximum log level in sync with the
668 /// highest log level that the logger will not ignore.
669 ///
670 /// This function may only be called once in the lifetime of a program. Any log
671 /// events that occur before the call to `set_logger_raw` completes will be
672 /// ignored.
673 ///
674 /// This function does not typically need to be called manually. Logger
675 /// implementations should provide an initialization method that calls
676 /// `set_logger_raw` internally.
677 ///
678 /// # Safety
679 ///
680 /// The pointer returned by `make_logger` must remain valid for the entire
681 /// duration of the program or until `shutdown_logger_raw` is called. In
682 /// addition, `shutdown_logger` *must not* be called after this function.
683 pub unsafe fn set_logger_raw<M>(make_logger: M) -> Result<(), SetLoggerError>
684 where M: FnOnce(MaxLogLevelFilter) -> *const Log {
685 if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING,
686 Ordering::SeqCst) != UNINITIALIZED {
687 return Err(SetLoggerError(()));
688 }
689
690 LOGGER = make_logger(MaxLogLevelFilter(()));
691 STATE.store(INITIALIZED, Ordering::SeqCst);
692 Ok(())
693 }
694
695 /// Shuts down the global logger.
696 ///
697 /// This function may only be called once in the lifetime of a program, and may
698 /// not be called before `set_logger`. Once the global logger has been shut
699 /// down, it can no longer be re-initialized by `set_logger`. Any log events
700 /// that occur after the call to `shutdown_logger` completes will be ignored.
701 ///
702 /// The logger that was originally created by the call to to `set_logger` is
703 /// returned on success. At that point it is guaranteed that no other threads
704 /// are concurrently accessing the logger object.
705 #[cfg(feature = "use_std")]
706 pub fn shutdown_logger() -> Result<Box<Log>, ShutdownLoggerError> {
707 shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) })
708 }
709
710 /// Shuts down the global logger.
711 ///
712 /// This function is similar to `shutdown_logger` except that it is usable in
713 /// `no_std` code.
714 ///
715 /// This function may only be called once in the lifetime of a program, and may
716 /// not be called before `set_logger_raw`. Once the global logger has been shut
717 /// down, it can no longer be re-initialized by `set_logger_raw`. Any log
718 /// events that occur after the call to `shutdown_logger_raw` completes will be
719 /// ignored.
720 ///
721 /// The pointer that was originally passed to `set_logger_raw` is returned on
722 /// success. At that point it is guaranteed that no other threads are
723 /// concurrently accessing the logger object.
724 pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> {
725 // Set the global log level to stop other thread from logging
726 MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst);
727
728 // Set to INITIALIZING to prevent re-initialization after
729 if STATE.compare_and_swap(INITIALIZED, INITIALIZING,
730 Ordering::SeqCst) != INITIALIZED {
731 return Err(ShutdownLoggerError(()));
732 }
733
734 while REFCOUNT.load(Ordering::SeqCst) != 0 {
735 // FIXME add a sleep here when it doesn't involve timers
736 }
737
738 unsafe {
739 let logger = LOGGER;
740 LOGGER = &NopLogger;
741 Ok(logger)
742 }
743 }
744
745 /// The type returned by `set_logger` if `set_logger` has already been called.
746 #[allow(missing_copy_implementations)]
747 #[derive(Debug)]
748 pub struct SetLoggerError(());
749
750 impl fmt::Display for SetLoggerError {
751 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
752 write!(fmt, "attempted to set a logger after the logging system \
753 was already initialized")
754 }
755 }
756
757 // The Error trait is not available in libcore
758 #[cfg(feature = "use_std")]
759 impl error::Error for SetLoggerError {
760 fn description(&self) -> &str { "set_logger() called multiple times" }
761 }
762
763 /// The type returned by `shutdown_logger_raw` if `shutdown_logger_raw` has
764 /// already been called or if `set_logger_raw` has not been called yet.
765 #[allow(missing_copy_implementations)]
766 #[derive(Debug)]
767 pub struct ShutdownLoggerError(());
768
769 impl fmt::Display for ShutdownLoggerError {
770 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
771 write!(fmt, "attempted to shut down the logger without an active logger")
772 }
773 }
774
775 // The Error trait is not available in libcore
776 #[cfg(feature = "use_std")]
777 impl error::Error for ShutdownLoggerError {
778 fn description(&self) -> &str { "shutdown_logger() called without an active logger" }
779 }
780
781 /// Registers a panic hook which logs at the error level.
782 ///
783 /// The format is the same as the default panic hook . The reporting module is
784 /// `log::panic`.
785 ///
786 /// Requires the `use_std` (enabled by default) and `nightly` features.
787 #[cfg(all(feature = "nightly", feature = "use_std"))]
788 pub fn log_panics() {
789 std::panic::set_hook(Box::new(panic::log));
790 }
791
792 // inner module so that the reporting module is log::panic instead of log
793 #[cfg(all(feature = "nightly", feature = "use_std"))]
794 mod panic {
795 use std::panic::PanicInfo;
796 use std::thread;
797
798 pub fn log(info: &PanicInfo) {
799 let thread = thread::current();
800 let thread = thread.name().unwrap_or("<unnamed>");
801
802 let msg = match info.payload().downcast_ref::<&'static str>() {
803 Some(s) => *s,
804 None => match info.payload().downcast_ref::<String>() {
805 Some(s) => &s[..],
806 None => "Box<Any>",
807 }
808 };
809
810 match info.location() {
811 Some(location) => {
812 error!("thread '{}' panicked at '{}': {}:{}",
813 thread,
814 msg,
815 location.file(),
816 location.line())
817 }
818 None => error!("thread '{}' panicked at '{}'", thread, msg),
819 }
820 }
821 }
822
823 struct LoggerGuard(&'static Log);
824
825 impl Drop for LoggerGuard {
826 fn drop(&mut self) {
827 REFCOUNT.fetch_sub(1, Ordering::SeqCst);
828 }
829 }
830
831 impl Deref for LoggerGuard {
832 type Target = Log;
833
834 fn deref(&self) -> &(Log + 'static) {
835 self.0
836 }
837 }
838
839 fn logger() -> Option<LoggerGuard> {
840 REFCOUNT.fetch_add(1, Ordering::SeqCst);
841 if STATE.load(Ordering::SeqCst) != INITIALIZED {
842 REFCOUNT.fetch_sub(1, Ordering::SeqCst);
843 None
844 } else {
845 Some(LoggerGuard(unsafe { &*LOGGER }))
846 }
847 }
848
849 // WARNING
850 // This is not considered part of the crate's public API. It is subject to
851 // change at any time.
852 #[doc(hidden)]
853 pub fn __enabled(level: LogLevel, target: &str) -> bool {
854 if let Some(logger) = logger() {
855 logger.enabled(&LogMetadata { level: level, target: target })
856 } else {
857 false
858 }
859 }
860
861 // WARNING
862 // This is not considered part of the crate's public API. It is subject to
863 // change at any time.
864 #[doc(hidden)]
865 pub fn __log(level: LogLevel, target: &str, loc: &LogLocation,
866 args: fmt::Arguments) {
867 if let Some(logger) = logger() {
868 let record = LogRecord {
869 metadata: LogMetadata {
870 level: level,
871 target: target,
872 },
873 location: loc,
874 args: args
875 };
876 logger.log(&record)
877 }
878 }
879
880 // WARNING
881 // This is not considered part of the crate's public API. It is subject to
882 // change at any time.
883 #[inline(always)]
884 #[doc(hidden)]
885 pub fn __static_max_level() -> LogLevelFilter {
886 if !cfg!(debug_assertions) {
887 // This is a release build. Check `release_max_level_*` first.
888 if cfg!(feature = "release_max_level_off") {
889 return LogLevelFilter::Off
890 } else if cfg!(feature = "release_max_level_error") {
891 return LogLevelFilter::Error
892 } else if cfg!(feature = "release_max_level_warn") {
893 return LogLevelFilter::Warn
894 } else if cfg!(feature = "release_max_level_info") {
895 return LogLevelFilter::Info
896 } else if cfg!(feature = "release_max_level_debug") {
897 return LogLevelFilter::Debug
898 } else if cfg!(feature = "release_max_level_trace") {
899 return LogLevelFilter::Trace
900 }
901 }
902 if cfg!(feature = "max_level_off") {
903 LogLevelFilter::Off
904 } else if cfg!(feature = "max_level_error") {
905 LogLevelFilter::Error
906 } else if cfg!(feature = "max_level_warn") {
907 LogLevelFilter::Warn
908 } else if cfg!(feature = "max_level_info") {
909 LogLevelFilter::Info
910 } else if cfg!(feature = "max_level_debug") {
911 LogLevelFilter::Debug
912 } else {
913 LogLevelFilter::Trace
914 }
915 }
916
917 #[cfg(test)]
918 mod tests {
919 extern crate std;
920 use tests::std::string::ToString;
921 use super::{LogLevel, LogLevelFilter};
922
923 #[test]
924 fn test_loglevelfilter_from_str() {
925 let tests = [
926 ("off", Ok(LogLevelFilter::Off)),
927 ("error", Ok(LogLevelFilter::Error)),
928 ("warn", Ok(LogLevelFilter::Warn)),
929 ("info", Ok(LogLevelFilter::Info)),
930 ("debug", Ok(LogLevelFilter::Debug)),
931 ("trace", Ok(LogLevelFilter::Trace)),
932 ("OFF", Ok(LogLevelFilter::Off)),
933 ("ERROR", Ok(LogLevelFilter::Error)),
934 ("WARN", Ok(LogLevelFilter::Warn)),
935 ("INFO", Ok(LogLevelFilter::Info)),
936 ("DEBUG", Ok(LogLevelFilter::Debug)),
937 ("TRACE", Ok(LogLevelFilter::Trace)),
938 ("asdf", Err(())),
939 ];
940 for &(s, ref expected) in &tests {
941 assert_eq!(expected, &s.parse());
942 }
943 }
944
945 #[test]
946 fn test_loglevel_from_str() {
947 let tests = [
948 ("OFF", Err(())),
949 ("error", Ok(LogLevel::Error)),
950 ("warn", Ok(LogLevel::Warn)),
951 ("info", Ok(LogLevel::Info)),
952 ("debug", Ok(LogLevel::Debug)),
953 ("trace", Ok(LogLevel::Trace)),
954 ("ERROR", Ok(LogLevel::Error)),
955 ("WARN", Ok(LogLevel::Warn)),
956 ("INFO", Ok(LogLevel::Info)),
957 ("DEBUG", Ok(LogLevel::Debug)),
958 ("TRACE", Ok(LogLevel::Trace)),
959 ("asdf", Err(())),
960 ];
961 for &(s, ref expected) in &tests {
962 assert_eq!(expected, &s.parse());
963 }
964 }
965
966 #[test]
967 fn test_loglevel_show() {
968 assert_eq!("INFO", LogLevel::Info.to_string());
969 assert_eq!("ERROR", LogLevel::Error.to_string());
970 }
971
972 #[test]
973 fn test_loglevelfilter_show() {
974 assert_eq!("OFF", LogLevelFilter::Off.to_string());
975 assert_eq!("ERROR", LogLevelFilter::Error.to_string());
976 }
977
978 #[test]
979 fn test_cross_cmp() {
980 assert!(LogLevel::Debug > LogLevelFilter::Error);
981 assert!(LogLevelFilter::Warn < LogLevel::Trace);
982 assert!(LogLevelFilter::Off < LogLevel::Error);
983 }
984
985 #[test]
986 fn test_cross_eq() {
987 assert!(LogLevel::Error == LogLevelFilter::Error);
988 assert!(LogLevelFilter::Off != LogLevel::Error);
989 assert!(LogLevel::Trace == LogLevelFilter::Trace);
990 }
991
992 #[test]
993 fn test_to_log_level() {
994 assert_eq!(Some(LogLevel::Error), LogLevelFilter::Error.to_log_level());
995 assert_eq!(None, LogLevelFilter::Off.to_log_level());
996 assert_eq!(Some(LogLevel::Debug), LogLevelFilter::Debug.to_log_level());
997 }
998
999 #[test]
1000 fn test_to_log_level_filter() {
1001 assert_eq!(LogLevelFilter::Error, LogLevel::Error.to_log_level_filter());
1002 assert_eq!(LogLevelFilter::Trace, LogLevel::Trace.to_log_level_filter());
1003 }
1004
1005 #[test]
1006 #[cfg(feature = "use_std")]
1007 fn test_error_trait() {
1008 use std::error::Error;
1009 use super::SetLoggerError;
1010 let e = SetLoggerError(());
1011 assert_eq!(e.description(), "set_logger() called multiple times");
1012 }
1013 }