loggerithm/
level.rs

1//! Everything related to logging levels.
2//! 
3//! # Examples
4// 
5//! ```
6//! use loggerithm::level::{TRACE, DEBUG, INFO, NOTICE, SUCCESS, FAILURE, WARN, ERROR, FATAL};
7//! log!(TRACE, "Test message");
8//! log!(DEBUG, "Test message");
9//! log!(INFO, "Test message");
10//! log!(NOTICE, "Test message");
11//! log!(SUCCESS, "Test message");
12//! log!(FAILURE, "Test message");
13//! log!(WARN, "Test message");
14//! log!(ERROR, "Test message");
15//! log!(FATAL, "Test message");
16//! ```
17
18
19
20use colored::{ColoredString, Colorize};
21
22use crate::internal;
23use crate::level;
24
25
26
27/// An object containing information
28/// about how to print a log message.
29pub struct LogLevel {
30    name      : String,
31    severity  : u32,
32    formatter : Box<dyn Fn(String) -> ColoredString>,
33    init      : bool
34}
35/// Initialisation.
36impl LogLevel {
37    /// Create a new log level.
38    /// 
39    /// # Arguments
40    /// 
41    /// * `severity` - The severity of the log level. When
42    ///                logged, must be equal to or higher
43    ///                than the minimum severity level of
44    ///                the active logger in order to be
45    ///                seen.
46    /// 
47    /// # Returns
48    /// 
49    /// The log level that was created.
50    /// 
51    /// # Examples
52    /// 
53    /// ```
54    /// log_level!(ALERT, LogLevel::new(30));
55    /// ```
56    pub fn new(severity : u32) -> LogLevel {
57        let level = LogLevel {
58            name      : String::new(),
59            severity,
60            formatter : Box::new(|v| v.normal()),
61            init      : false
62        };
63        return level;
64    }
65    /// Register the log level and attach
66    /// a name.
67    /// 
68    /// This function will panic if called
69    /// more than once.
70    /// 
71    /// This function is called automatically
72    /// with the `log_level!` macro.
73    /// 
74    /// # Arguments
75    /// 
76    /// * `name` - The name of the log level.
77    /// 
78    /// # Returns
79    /// 
80    /// `self`
81    pub fn init(mut self, name : &str) -> LogLevel {
82        if (self.init) {
83            panic!("`init` already called.");
84        }
85        self.init = true;
86        self.name = String::from(name);
87        if (unsafe {internal::MAX_LEVEL_NAME_LEN} < self.name.len()) {
88            unsafe {
89                internal::MAX_LEVEL_NAME_LEN = self.name.len();
90            }
91        }
92        return self;
93    }
94    /// Set the formatting of the log level.
95    /// 
96    /// # Arguments
97    /// 
98    /// * `formatter` - The function that formats the level.
99    ///                 It takes a `String` as an argument
100    ///                 and should return a
101    ///                 `colored::ColoredString`.
102    /// 
103    /// # Generics
104    /// 
105    /// * `F` - The formatting function.
106    /// 
107    /// # Returns
108    /// 
109    /// `self`
110    pub fn formatted<F : 'static>(mut self, formatter : F) -> LogLevel
111        where F : Fn(String) -> ColoredString
112    {
113        self.formatter = Box::new(formatter);
114        return self;
115    }
116}
117/// Data access functions.
118impl LogLevel {
119    /// Get the name of the log level.
120    /// 
121    /// # Returns
122    /// 
123    /// The name of the log level.
124    pub fn get_name(&self) -> String {
125        return String::from(&self.name);
126    }
127    /// Get the severity of the log level.
128    /// 
129    /// # Returns
130    /// 
131    /// The severity of the log level.
132    pub fn get_severity(&self) -> u32 {
133        return self.severity;
134    }
135    /// Calls the formatter on a string.
136    /// 
137    /// # Arguments
138    /// 
139    /// * `text` - The text to format.
140    /// 
141    /// # Returns
142    /// 
143    /// The formatted text.
144    pub fn format(&self, text : String) -> String {
145        return (self.formatter)(text).to_string();
146    }
147}
148/// Thread safety.
149unsafe impl Sync for LogLevel {}
150
151
152
153/// Registers a new log level.
154/// 
155/// # Arguments
156/// 
157/// * `name`   - The identifier to store the level at.
158///              This will be the name of the level
159///              and the name used to access it.
160/// * `logger` - The level to register and store.
161/// 
162/// # Returns
163/// 
164/// A module containing everything
165/// needed for the level.
166/// 
167/// # Examples
168/// 
169/// ```
170/// log_level!(ALERT, LogLevel::new(30));
171/// fn main() {
172///     log!(ALERT, "This is an alert!");
173/// }
174/// ```
175#[macro_export]
176macro_rules! log_level {
177    ($name:ident, $level:expr) => {
178        /// A logging level.
179        #[allow(non_snake_case)]
180        pub mod $name {
181            use super::*;
182            extern crate static_init;
183            /// The log level object.
184            #[static_init::dynamic]
185            pub static LEVEL : $crate::level::LogLevel = $level.init(stringify!($name));
186            /// Get the severity value of the log
187            /// level.
188            /// 
189            /// # Returns
190            /// 
191            /// The severity of the level.
192            /// 
193            /// # Examples
194            /// 
195            /// ```
196            /// logger!(Logger::new()
197            ///     .set_min_severity(WARN::SEVERITY)
198            /// );
199            /// ```
200            pub fn SEVERITY() -> u32 {
201                return LEVEL.get_severity();
202            }
203        }
204    };
205}
206pub(crate) use log_level;
207
208
209
210log_level!(TRACE, level::LogLevel::new(5)
211    .formatted(|v| v.bright_black())
212);
213log_level!(DEBUG, level::LogLevel::new(10)
214    .formatted(|v| v.white().dimmed())
215);
216log_level!(INFO, level::LogLevel::new(20)
217    .formatted(|v| v.cyan().dimmed())
218);
219log_level!(NOTICE, level::LogLevel::new(25)
220    .formatted(|v| v.bright_cyan())
221);
222log_level!(SUCCESS, level::LogLevel::new(25)
223    .formatted(|v| v.green())
224);
225log_level!(WARN, level::LogLevel::new(30)
226    .formatted(|v| v.yellow())
227);
228log_level!(FAILURE, level::LogLevel::new(35)
229    .formatted(|v| v.red())
230);
231log_level!(ERROR, level::LogLevel::new(40)
232    .formatted(|v| v.bright_red().bold())
233);
234log_level!(FATAL, level::LogLevel::new(50)
235    .formatted(|v| v.bright_white().bold().on_red())
236);