rust_loguru/handler/
mod.rs1use parking_lot::RwLock;
2use std::fmt;
3use std::io;
4use std::sync::Arc;
5
6use crate::formatters::Formatter;
7use crate::level::LogLevel;
8use crate::record::Record;
9
10pub type HandlerFilter = Arc<dyn Fn(&Record) -> bool + Send + Sync>;
12
13#[derive(Debug)]
15pub enum HandlerError {
16 IoError(io::Error),
18 NotInitialized,
20 Custom(String),
22}
23
24impl std::fmt::Display for HandlerError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 HandlerError::IoError(e) => write!(f, "I/O error: {}", e),
28 HandlerError::NotInitialized => write!(f, "Handler not initialized"),
29 HandlerError::Custom(msg) => write!(f, "{}", msg),
30 }
31 }
32}
33
34impl std::error::Error for HandlerError {
35 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
36 match self {
37 HandlerError::IoError(e) => Some(e),
38 _ => None,
39 }
40 }
41}
42
43pub trait Handler: Send + Sync + fmt::Debug {
45 fn level(&self) -> LogLevel;
47
48 fn set_level(&mut self, level: LogLevel);
50
51 fn is_enabled(&self) -> bool;
53
54 fn set_enabled(&mut self, enabled: bool);
56
57 fn formatter(&self) -> &Formatter;
59
60 fn set_formatter(&mut self, formatter: Formatter);
62
63 fn set_filter(&mut self, filter: Option<HandlerFilter>);
65
66 fn filter(&self) -> Option<&HandlerFilter>;
68
69 fn handle(&self, record: &Record) -> Result<(), HandlerError>;
71
72 fn handle_batch(&self, records: &[Record]) -> Result<(), HandlerError> {
74 for record in records {
75 self.handle(record)?;
76 }
77 Ok(())
78 }
79
80 fn init(&mut self) -> Result<(), HandlerError> {
82 Ok(())
83 }
84
85 fn flush(&self) -> Result<(), HandlerError> {
87 Ok(())
88 }
89
90 fn shutdown(&mut self) -> Result<(), HandlerError> {
92 Ok(())
93 }
94}
95
96pub struct NullHandler {
98 level: LogLevel,
100 enabled: bool,
102 formatter: Formatter,
104 filter: Option<HandlerFilter>,
106}
107
108impl Default for NullHandler {
109 fn default() -> Self {
110 Self {
111 level: LogLevel::Info,
112 enabled: true,
113 formatter: Formatter::text(),
114 filter: None,
115 }
116 }
117}
118
119impl Handler for NullHandler {
120 fn level(&self) -> LogLevel {
121 self.level
122 }
123
124 fn set_level(&mut self, level: LogLevel) {
125 self.level = level;
126 }
127
128 fn is_enabled(&self) -> bool {
129 self.enabled
130 }
131
132 fn set_enabled(&mut self, enabled: bool) {
133 self.enabled = enabled;
134 }
135
136 fn formatter(&self) -> &Formatter {
137 &self.formatter
138 }
139
140 fn set_formatter(&mut self, formatter: Formatter) {
141 self.formatter = formatter;
142 }
143
144 fn set_filter(&mut self, filter: Option<HandlerFilter>) {
145 self.filter = filter;
146 }
147
148 fn filter(&self) -> Option<&HandlerFilter> {
149 self.filter.as_ref()
150 }
151
152 fn handle(&self, _record: &Record) -> Result<(), HandlerError> {
153 Ok(())
154 }
155}
156
157impl NullHandler {
158 pub fn new(level: LogLevel) -> Self {
159 Self {
160 level,
161 enabled: true,
162 formatter: Formatter::text(),
163 filter: None,
164 }
165 }
166}
167
168impl fmt::Debug for NullHandler {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 f.debug_struct("NullHandler")
171 .field("level", &self.level)
172 .field("enabled", &self.enabled)
173 .field("formatter", &self.formatter)
174 .finish()
175 }
176}
177
178pub mod console;
179pub mod file;
180pub mod network;
181
182pub type HandlerRef = Arc<RwLock<dyn Handler>>;
184
185pub fn new_handler_ref<H: Handler + 'static>(handler: H) -> HandlerRef {
187 Arc::new(RwLock::new(handler))
188}
189
190pub struct BaseHandler {
192 level: LogLevel,
194 enabled: bool,
196 formatter: Formatter,
198 filter: Option<HandlerFilter>,
200}
201
202impl BaseHandler {
203 pub fn new(level: LogLevel) -> Self {
205 Self {
206 level,
207 enabled: true,
208 formatter: Formatter::text(),
209 filter: None,
210 }
211 }
212}
213
214impl Handler for BaseHandler {
215 fn level(&self) -> LogLevel {
216 self.level
217 }
218
219 fn set_level(&mut self, level: LogLevel) {
220 self.level = level;
221 }
222
223 fn is_enabled(&self) -> bool {
224 self.enabled
225 }
226
227 fn set_enabled(&mut self, enabled: bool) {
228 self.enabled = enabled;
229 }
230
231 fn formatter(&self) -> &Formatter {
232 &self.formatter
233 }
234
235 fn set_formatter(&mut self, formatter: Formatter) {
236 self.formatter = formatter;
237 }
238
239 fn set_filter(&mut self, filter: Option<HandlerFilter>) {
240 self.filter = filter;
241 }
242
243 fn filter(&self) -> Option<&HandlerFilter> {
244 self.filter.as_ref()
245 }
246
247 fn handle(&self, record: &Record) -> Result<(), HandlerError> {
248 if !self.is_enabled() {
249 return Ok(());
250 }
251
252 if let Some(filter) = &self.filter {
253 if !filter(record) {
254 return Ok(());
255 }
256 }
257
258 Ok(())
259 }
260}
261
262impl fmt::Debug for BaseHandler {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 f.debug_struct("BaseHandler")
265 .field("level", &self.level)
266 .field("enabled", &self.enabled)
267 .field("formatter", &self.formatter)
268 .finish()
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275
276 #[test]
277 fn test_base_handler() {
278 let mut handler = BaseHandler::new(LogLevel::Info);
279 assert_eq!(handler.level(), LogLevel::Info);
280 assert!(handler.is_enabled());
281
282 handler.set_enabled(false);
284 assert!(!handler.is_enabled());
285 let record = Record::new(LogLevel::Info, "test", None::<String>, None::<String>, None);
286 assert!(handler.handle(&record).is_ok());
287
288 handler.set_enabled(true);
290 let debug_record = Record::new(
291 LogLevel::Debug,
292 "test",
293 None::<String>,
294 None::<String>,
295 None,
296 );
297 assert!(handler.handle(&debug_record).is_ok()); let info_record = Record::new(LogLevel::Info, "test", None::<String>, None::<String>, None);
300 assert!(handler.handle(&info_record).is_ok()); let formatter = Formatter::text();
304 handler.set_formatter(formatter);
305 assert!(handler.formatter().format(&info_record).contains("test"));
306 }
307}