Add module and all-pub-things docs and deny missing docs
[rust-lightning] / src / util / logger.rs
1 // Pruned copy of crate rust log, without global logger
2 // https://github.com/rust-lang-nursery/log #7a60286
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 //! Log traits live here, which are called throughout the library to provide useful information for
11 //! debugging purposes.
12 //!
13 //! There is currently 2 ways to filter log messages. First one, by using compilation features, e.g "max_level_off".
14 //! The second one, client-side by implementing check against Record Level field.
15 //! Each module may have its own Logger or share one.
16
17 use std::cmp;
18 use std::fmt;
19
20 static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
21
22 /// An enum representing the available verbosity levels of the logger.
23 #[derive(Copy, Clone, Eq, Debug, Hash)]
24 pub enum Level {
25         ///Designates logger being silent
26         Off,
27         /// Designates very serious errors
28         Error,
29         /// Designates hazardous situations
30         Warn,
31         /// Designates useful information
32         Info,
33         /// Designates lower priority information
34         Debug,
35         /// Designates very low priority, often extremely verbose, information
36         Trace,
37 }
38
39 impl PartialEq for Level {
40         #[inline]
41         fn eq(&self, other: &Level) -> bool {
42                 *self as usize == *other as usize
43         }
44 }
45
46 impl PartialOrd for Level {
47         #[inline]
48         fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
49                 Some(self.cmp(other))
50         }
51
52         #[inline]
53         fn lt(&self, other: &Level) -> bool {
54                 (*self as usize) < *other as usize
55         }
56
57         #[inline]
58         fn le(&self, other: &Level) -> bool {
59                 *self as usize <= *other as usize
60         }
61
62         #[inline]
63         fn gt(&self, other: &Level) -> bool {
64                 *self as usize > *other as usize
65         }
66
67         #[inline]
68         fn ge(&self, other: &Level) -> bool {
69                 *self as usize >= *other as usize
70         }
71 }
72
73 impl Ord for Level {
74         #[inline]
75         fn cmp(&self, other: &Level) -> cmp::Ordering {
76                 (*self as usize).cmp(&(*other as usize))
77         }
78 }
79
80 impl fmt::Display for Level {
81         fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
82                 fmt.pad(LOG_LEVEL_NAMES[*self as usize])
83         }
84 }
85
86 impl Level {
87         /// Returns the most verbose logging level.
88         #[inline]
89         pub fn max() -> Level {
90                 Level::Trace
91         }
92 }
93
94 /// A Record, unit of logging output with Metadata to enable filtering
95 /// Module_path, file, line to inform on log's source
96 #[derive(Clone,Debug)]
97 pub struct Record<'a> {
98         /// The verbosity level of the message.
99         pub level: Level,
100         /// The message body.
101         pub args: fmt::Arguments<'a>,
102         /// The module path of the message.
103         pub module_path: &'a str,
104         /// The source file containing the message.
105         pub file: &'a str,
106         /// The line containing the message.
107         pub line: u32,
108 }
109
110 impl<'a> Record<'a> {
111         /// Returns a new Record.
112         #[inline]
113         pub fn new(level: Level, args: fmt::Arguments<'a>, module_path: &'a str, file: &'a str, line: u32) -> Record<'a> {
114                 Record {
115                         level,
116                         args,
117                         module_path,
118                         file,
119                         line
120                 }
121         }
122 }
123
124 /// A trait encapsulating the operations required of a logger
125 pub trait Logger: Sync + Send {
126         /// Logs the `Record`
127         fn log(&self, record: &Record);
128 }
129
130 #[cfg(test)]
131 mod tests {
132         use util::logger::{Logger, Level};
133         use util::test_utils::TestLogger;
134         use std::sync::{Arc};
135
136         #[test]
137         fn test_level_show() {
138                 assert_eq!("INFO", Level::Info.to_string());
139                 assert_eq!("ERROR", Level::Error.to_string());
140                 assert_ne!("WARN", Level::Error.to_string());
141         }
142
143         struct WrapperLog {
144                 logger: Arc<Logger>
145         }
146
147         impl WrapperLog {
148                 fn new(logger: Arc<Logger>) -> WrapperLog {
149                         WrapperLog {
150                                 logger,
151                         }
152                 }
153
154                 fn call_macros(&self) {
155                         log_error!(self, "This is an error");
156                         log_warn!(self, "This is a warning");
157                         log_info!(self, "This is an info");
158                         log_debug!(self, "This is a debug");
159                         log_trace!(self, "This is a trace");
160                 }
161         }
162
163         #[test]
164         fn test_logging_macros() {
165                 let mut logger = TestLogger::new();
166                 logger.enable(Level::Trace);
167                 let logger : Arc<Logger> = Arc::new(logger);
168                 let wrapper = WrapperLog::new(Arc::clone(&logger));
169                 wrapper.call_macros();
170         }
171 }