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);