src/logger/mod.rs

Lines

100.00 %

Functions

100.00 %

Regions

100.00 %

LineCountSource (jump to first uncovered line)
1
//
2
// File Name:    mod.rs
3
// Directory:    src/logger
4
// Project Name: flogging
5
//
6
// Copyright (C) 2025 Bradley Willcott
7
//
8
// SPDX-License-Identifier: GPL-3.0-or-later
9
//
10
// This library (crate) is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
14
//
15
// This library (crate) is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
// GNU General Public License for more details.
19
//
20
// You should have received a copy of the GNU General Public License
21
// along with this library (crate).  If not, see <https://www.gnu.org/licenses/>.
22
//
23
24
//!
25
//! # Logger
26
//!
27
//! `Logger` is the work-horse of the crate.
28
//!
29
//! It contains the primary methods to both create a logger instance, and has
30
//! the methods to add log messages at various log levels.
31
//!
32
33
#![allow(clippy::needless_doctest_main)]
34
35
mod builder;
36
mod level;
37
mod log_entry;
38
39
use anyhow::{Context, Error, Result};
40
use std::cell::{LazyCell, RefCell};
41
use std::collections::hash_map::IterMut;
42
use std::collections::{HashMap, HashSet};
43
use std::f32::consts;
44
use std::fs::{File, exists};
45
use std::io::Write;
46
use std::marker::PhantomData;
47
use std::module_path;
48
use std::ops::DerefMut;
49
use std::path::Path;
50
use std::sync::mpsc::Sender;
51
use std::sync::{Arc, MutexGuard, PoisonError, mpsc};
52
use std::thread;
53
use std::{fmt, fs};
54
55
pub use builder::*;
56
pub use level::Level;
57
pub use log_entry::LogEntry;
58
59
use crate::*;
60
61
///
62
/// This is the work-horse, providing the primary methods of the crate.
63
///
64
pub struct Logger {
65
    ///
66
    /// Identify the source of log messages passed to this logger.
67
    ///
68
    /// This would ideally be the **mod** path.
69
    ///
70
    mod_path: String,
71
72
    ///
73
    /// The name of the function/method inside which the log message
74
    /// is generated.
75
    ///
76
    fn_name: String,
77
78
    ///
79
    /// Default level used by `log(msg)`.
80
    ///
81
    level: Level,
82
83
    ///
84
    /// Holds the handlers associated with this logger.
85
    ///
86
    handlers: RefCell<HashMap<Handler, Box<dyn HandlerTrait>>>,
87
}
88
89
impl Logger {
90
    ///
91
    /// Create a new Logger instance.
92
    ///
93
    /// Logging level is set to it's default setting (INFO).
94
    ///
95
    /// No `handlers` are set. Use the various methods of
96
    /// [`LoggerBuilder`] to configure the new `Logger`.
97
    ///
98
    /// ## Parameters
99
    /// - `mod_path` - The module path. Can be set with: [`module_path!()`]
100
    ///
101
    /// Returns a `LoggerBuilder` for further configuring.
102
    ///
103
    /// ## Examples
104
    /// ```
105
    /// use flogging::*;
106
    ///
107
    /// let mut log = Logger::builder(module_path!())
108
    ///     .add_console_handler()
109
    ///     .build();
110
    /// ```
111
    ///
11246
    pub fn builder(mod_path: &str) -> LoggerBuilder {
11346
        LoggerBuilder::create(mod_path.to_string())
11446
    }
115
116
    ///
117
    /// Log a CONFIG message.
118
    ///
119
    /// If the logger is currently enabled for the CONFIG message level
120
    /// then the given message is forwarded to all the registered output
121
    /// Handler objects.
122
    ///
123
    /// ## Parameters
124
    /// - `msg` - The string message.
125
    ///
126
    /// ## Examples
127
    /// ```
128
    /// use flogging::*;
129
    ///
130
    /// let mut log = Logger::console_logger(module_path!());
131
    /// log.set_level(Level::CONFIG);
132
    /// log.config("Some text to store.");
133
    /// ```
134
    ///
1359
    pub fn config(&mut self, msg: &str) {
1369
        self.log(Level::CONFIG, &self.fn_name(), msg);
1379
    }
138
139
    ///
140
    /// Create new Logger instance, with a `ConsoleHandler`, output
141
    /// set to: [`std::io::stdout`].
142
    ///
143
    /// Logging level is set to it's default setting (INFO).
144
    ///
145
    /// ## Parameters
146
    /// - `mod_path`- The module path. Suggest using [`module_path!()`].
147
    ///
148
    /// Returns a configured `Logger`.
149
    ///
150
    /// ## Examples
151
    /// ```
152
    /// use flogging::*;
153
    ///
154
    /// let mut log = Logger::console_logger(module_path!());
155
    /// log.set_fn_name("main");
156
    ///
157
    /// log.warning("Don't over do it.");
158
    /// ```
159
    /// Output to stdout:
160
    /// ```text
161
    /// flogging->main [WARNING] Don't over do it.
162
    /// ```
163
    ///
1643
    pub fn console_logger(mod_path: &str) -> Logger {
1653
        Logger::builder(mod_path).add_console_handler().build()
1663
    }
167
168
    ///
169
    /// Create new Logger instance, with a custom handler.
170
    ///
171
    /// ## Parameters
172
    /// - `mod_path`- The module path. Suggest using [`module_path!()`].
173
    /// - `label` - Unique label for this custom handler.
174
    /// - `custom` - The boxed custom handler.
175
    ///
176
    /// Returns a configured `Logger`.
177
    ///
178
    /// ## Examples
179
    /// ```
180
    /// use flogging::*;
181
    ///
182
    /// let mut log = Logger::custom_logger(
183
    ///     module_path!(),
184
    ///     "MockHandler",
185
    ///     Box::new(MockHandler::create("Some text").unwrap()),
186
    /// );
187
    /// log.set_fn_name("main");
188
    ///
189
    /// log.warning("Don't over do it.");
190
    /// ```
191
    /// [`MockHandler`] doesn't publish anything, as [`publish()`][MockHandler::publish()] is a **NoOp** method.
192
    /// It is used here to make the example work.
193
    ///
194
    /// However, it is expected that _your_ custom handler will do a little more.
195
    ///
1962
    pub fn custom_logger(mod_path: &str, label: &str, custom: Box<dyn HandlerTrait>) -> Logger {
1972
        Logger::builder(mod_path)
1982
            .add_custom_handler(label, custom)
1992
            .build()
2002
    }
201
202
    ///
203
    /// Create new Logger instance, with a `ConsoleHandler`, output
204
    /// set to: [`std::io::stderr`].
205
    ///
206
    /// Logging level is set to it's default setting (INFO).
207
    ///
208
    /// ## Parameters
209
    /// - `mod_path`- The module path. Suggest using [`module_path!()`].
210
    ///
211
    /// Returns a configured `Logger`.
212
    ///
213
    /// ## Examples
214
    /// ```
215
    /// use flogging::*;
216
    ///
217
    /// let mut log = Logger::econsole_logger(module_path!());
218
    /// log.set_fn_name("main");
219
    ///
220
    /// log.warning("Don't over do it.");
221
    /// ```
222
    /// Output to stderr:
223
    /// ```text
224
    /// flogging->main [WARNING] Don't over do it.
225
    /// ```
226
    ///
2272
    pub fn econsole_logger(mod_path: &str) -> Logger {
2282
        Logger::builder(mod_path).add_econsole_handler().build()
2292
    }
230
231
    ///
232
    /// Log a method entry.
233
    ///
234
    /// This is a convenience method that can be used to log entry to a method.
235
    /// A `LogEntry` with message "Entry" and log level FINER, is logged.
236
    ///
237
    /// ## Examples
238
    /// ```
239
    /// mod my_mod {
240
    ///     extern crate flogging;
241
    ///     use flogging::*;
242
    ///     use std::cell::{LazyCell, RefCell};
243
    ///
244
    ///     // Setting up the module level logger.
245
    ///     const LOGGER: LazyCell<RefCell<Logger>> = LazyCell::new(|| {
246
    ///         RefCell::new({
247
    ///             Logger::builder(module_path!())
248
    ///                 .add_console_handler()
249
    ///                 .set_level(Level::FINEST)
250
    ///                 .build()
251
    ///         })
252
    ///     });
253
    ///
254
    ///     pub fn my_func(data: &str) {
255
    ///         let binding = LOGGER;
256
    ///         let mut log = binding.borrow_mut();
257
    ///         log.set_fn_name("my_func");
258
    ///
259
    ///         log.entering();
260
    ///     }
261
    /// }
262
    ///
263
    /// fn main() {
264
    ///     let data = "Some data";
265
    ///     my_mod::my_func(data);
266
    /// }
267
    /// ```
268
    /// Output:
269
    /// ```text
270
    /// flogging::my_mod->my_func [FINER  ] Entry
271
    /// ```
272
    ///
2736
    pub fn entering(&mut self) {
2746
        self.log(Level::FINER, &self.fn_name(), "Entry");
2756
    }
276
277
    ///
278
    /// Log a method entry.
279
    ///
280
    /// This is a convenience method that can be used to log entry to a method.
281
    /// A `LogEntry` with message "Entry" and log level FINER, is logged.
282
    ///
283
    /// ## Parameters
284
    /// - `msg` - The string message.
285
    ///
286
    /// ## Examples
287
    /// ```
288
    /// mod my_mod {
289
    ///     extern crate flogging;
290
    ///     use flogging::*;
291
    ///     use std::cell::{LazyCell, RefCell};
292
    ///
293
    ///     // Setting up the module level logger.
294
    ///     const LOGGER: LazyCell<RefCell<Logger>> = LazyCell::new(|| {
295
    ///         RefCell::new({
296
    ///             Logger::builder(module_path!())
297
    ///                 .add_console_handler()
298
    ///                 .set_level(Level::FINEST)
299
    ///                 .build()
300
    ///         })
301
    ///     });
302
    ///
303
    ///     pub fn my_func(data: &str) {
304
    ///         let binding = LOGGER;
305
    ///         let mut log = binding.borrow_mut();
306
    ///         log.set_fn_name("my_func");
307
    ///
308
    ///         log.entering_with(&format!("data: \"{data}\""));
309
    ///     }
310
    /// }
311
    ///
312
    /// fn main() {
313
    ///     let data = "Some data";
314
    ///     my_mod::my_func(data);
315
    /// }
316
    /// ```
317
    /// Output:
318
    /// ```text
319
    /// flogging::my_mod->my_func [FINER  ] Entry: (data: "Some data")
320
    /// ```
321
    ///
3223
    pub fn entering_with(&mut self, msg: &str) {
3233
        self.log(
3243
            Level::FINER,
3253
            &self.fn_name(),
3263
            &("Entry: (".to_string() + msg + ")"),
327
        );
3283
    }
329
330
    ///
331
    /// Log a method return.
332
    ///
333
    /// This is a convenience method that can be used to log returning from a method.
334
    /// A `LogEntry` with message "Return" and log level FINER, is logged.
335
    ///
336
    /// ## Examples
337
    /// ```
338
    /// mod my_mod {
339
    ///     extern crate flogging;
340
    ///     use flogging::*;
341
    ///     use std::cell::{LazyCell, RefCell};
342
    ///
343
    ///     // Setting up the module level logger.
344
    ///     const LOGGER: LazyCell<RefCell<Logger>> = LazyCell::new(|| {
345
    ///         RefCell::new({
346
    ///             Logger::builder(module_path!())
347
    ///                 .add_console_handler()
348
    ///                 .set_level(Level::FINEST)
349
    ///                 .build()
350
    ///         })
351
    ///     });
352
    ///
353
    ///     pub fn my_func(data: &str) {
354
    ///         let binding = LOGGER;
355
    ///         let mut log = binding.borrow_mut();
356
    ///         log.set_fn_name("my_func");
357
    ///
358
    ///         log.exiting();
359
    ///     }
360
    /// }
361
    ///
362
    /// fn main() {
363
    ///     let data = "Some data";
364
    ///     my_mod::my_func(data);
365
    /// }
366
    /// ```
367
    /// Output:
368
    /// ```text
369
    /// flogging::my_mod->my_func [FINER  ] Return
370
    /// ```
371
    ///
3726
    pub fn exiting(&mut self) {
3736
        self.log(Level::FINER, &self.fn_name(), "Return");
3746
    }
375
376
    ///
377
    /// Log a method return.
378
    ///
379
    /// This is a convenience method that can be used to log returning from a method.
380
    /// A `LogEntry` with message "Return" and log level FINER, is logged.
381
    ///
382
    /// ## Parameters
383
    /// - `msg` - The string message.
384
    ///
385
    /// ## Examples
386
    /// ```
387
    /// mod my_mod {
388
    ///     extern crate flogging;
389
    ///     use flogging::*;
390
    ///     use std::cell::{LazyCell, RefCell};
391
    ///
392
    ///     // Setting up the module level logger.
393
    ///     const LOGGER: LazyCell<RefCell<Logger>> = LazyCell::new(|| {
394
    ///         RefCell::new({
395
    ///             Logger::builder(module_path!())
396
    ///                 .add_console_handler()
397
    ///                 .set_level(Level::FINEST)
398
    ///                 .build()
399
    ///         })
400
    ///     });
401
    ///
402
    ///     pub fn my_func(data: &str) -> bool {
403
    ///         let binding = LOGGER;
404
    ///         let mut log = binding.borrow_mut();
405
    ///         log.set_fn_name("my_func");
406
    ///
407
    ///         let rtn = true;
408
    ///         log.exiting_with(&format!("rtn: {rtn}"));
409
    ///         rtn
410
    ///     }
411
    /// }
412
    ///
413
    /// fn main() {
414
    ///     let data = "Some data";
415
    ///     my_mod::my_func(data);
416
    /// }
417
    /// ```
418
    /// Output:
419
    /// ```text
420
    /// flogging::my_mod->my_func [FINER  ] Return: (rtn: true)
421
    /// ```
422
    ///
4233
    pub fn exiting_with(&mut self, msg: &str) {
4243
        self.log(
4253
            Level::FINER,
4263
            &self.fn_name(),
4273
            &("Return: (".to_string() + msg + ")"),
428
        );
4293
    }
430
431
    ///
432
    /// Create new Logger instance, with a `FileHandler`.
433
    ///
434
    /// Logging level is set to it's default setting (INFO).
435
    ///
436
    /// ## Parameters
437
    /// - `mod_path`- The module path. Suggest using [`std::module_path`][mp].
438
    /// - `filename` - The name of the log file to use. Will be created
439
    ///   if it doesn't exist.
440
    ///
441
    /// Returns a configured `Logger`.
442
    ///
443
    /// ## Examples
444
    /// ```
445
    /// use flogging::Logger;
446
    ///
447
    /// let mut log = Logger::file_logger(module_path!(), "test_logs/logger.log");
448
    /// log.set_fn_name("main");
449
    ///
450
    /// log.info("Some text to store.");
451
    /// ```
452
    /// Output:
453
    /// ```text
454
    /// 2025-07-18T12:14:47.322720683+08:00 flogging->main [INFO   ] Some text to store.
455
    /// ```
456
    ///
457
    /// [mp]: https://doc.rust-lang.org/std/macro.module_path.html
4582
    pub fn file_logger(mod_path: &str, filename: &str) -> Logger {
4592
        Logger::builder(mod_path).add_file_handler(filename).build()
4602
    }
461
462
    ///
463
    /// Log a FINE message.
464
    ///
465
    /// If the logger is currently enabled for the FINE message level
466
    /// then the given message is forwarded to all the registered output
467
    /// Handler objects.
468
    ///
469
    /// ## Parameters
470
    /// - `msg` - The string message.
471
    ///
472
    /// ## Examples
473
    /// ```
474
    /// use flogging::*;
475
    ///
476
    /// let mut log = Logger::console_logger(module_path!());
477
    /// log.set_level(Level::FINEST);
478
    /// log.set_fn_name("main");
479
    ///
480
    /// log.fine("Some text to store.");
481
    /// ```
482
    /// Output:
483
    /// ```text
484
    /// flogging->main [FINE   ] Some text to store.
485
    /// ```
486
    ///
4876
    pub fn fine(&mut self, msg: &str) {
4886
        self.log(Level::FINE, &self.fn_name(), msg);
4896
    }
490
491
    ///
492
    /// Log a FINER message.
493
    ///
494
    /// If the logger is currently enabled for the FINER message level
495
    /// then the given message is forwarded to all the registered output
496
    /// Handler objects.
497
    ///
498
    /// ## Parameters
499
    /// - `msg` - The string message.
500
    ///
501
    /// ## Examples
502
    /// ```
503
    /// use flogging::*;
504
    ///
505
    /// let mut log = Logger::console_logger(module_path!());
506
    /// log.set_level(Level::FINEST);
507
    /// log.set_fn_name("main");
508
    ///
509
    /// log.finer("Some text to store.");
510
    /// ```
511
    /// Output:
512
    /// ```text
513
    /// flogging->main [FINER  ] Some text to store.
514
    /// ```
515
    ///
5162
    pub fn finer(&mut self, msg: &str) {
5172
        self.log(Level::FINER, &self.fn_name(), msg);
5182
    }
519
520
    ///
521
    /// Log a FINEST message.
522
    ///
523
    /// If the logger is currently enabled for the FINEST message level
524
    /// then the given message is forwarded to all the registered output
525
    /// Handler objects.
526
    ///
527
    /// ## Parameters
528
    /// - `msg` - The string message.
529
    ///
530
    /// ## Examples
531
    /// ```
532
    /// use flogging::*;
533
    ///
534
    /// let mut log = Logger::console_logger(module_path!());
535
    /// log.set_level(Level::FINEST);
536
    /// log.set_fn_name("main");
537
    ///
538
    /// log.finest("Some text to store.");
539
    /// ```
540
    /// Output:
541
    /// ```text
542
    /// flogging->main [FINEST ] Some text to store.
543
    /// ```
544
    ///
5453
    pub fn finest(&mut self, msg: &str) {
5463
        self.log(Level::FINEST, &self.fn_name(), msg);
5473
    }
548
549
    ///
550
    /// Get the current function/method name.
551
    ///
552106
    pub fn fn_name(&self) -> String {
553106
        self.fn_name.clone()
554106
    }
555
556
    ///
557
    /// Get required `Handler`.
558
    ///
559
    /// ## Parameters
560
    /// - `handler` - The enum of the required handler.
561
    ///
562
    /// Returns Some boxed handler, or None.
563
    ///
564
    /// ## Examples
565
    /// ```
566
    /// use flogging::*;
567
    ///
568
    /// let mut log = Logger::string_logger(module_path!());
569
    /// log.set_fn_name("get_handler");
570
    ///
571
    /// log.info("Some text to store.");
572
    ///
573
    /// let h = log.get_handler(Handler::String).unwrap();
574
    /// println!("{h}");
575
    /// ```
57625
    pub fn get_handler(&mut self, handler: Handler) -> Option<Box<&mut dyn HandlerTrait>> {
57725
        match self.handlers.get_mut().get_mut(&handler) {
57824
            Some(val) => Some(Box::new(&mut **val)),
5791
            None => None,
580
        }
58125
    }
582
583
    ///
584
    /// Check if the required `Handler` has been added to this `Logger`.
585
    ///
586
    /// ## Parameters
587
    /// - `handler` - The enum of the required handler.
588
    ///
589
    /// Returns `true` if it exists, `false` otherwise.
590
    ///
591
    /// ## Examples
592
    /// ```
593
    /// use flogging::*;
594
    ///
595
    /// let mut log = Logger::string_logger(module_path!());
596
    /// log.info("Some text to store.");
597
    ///
598
    /// println!("This logger has a 'StringHandler': {}", log.has_handler(Handler::String));
599
    /// ```
6001
    pub fn has_handler(&self, handler: Handler) -> bool {
6011
        self.handlers.borrow().contains_key(&handler)
6021
    }
603
    ///
604
    /// Log a INFO message.
605
    ///
606
    /// If the logger is currently enabled for the INFO message level
607
    /// then the given message is forwarded to all the registered output
608
    /// Handler objects.
609
    ///
610
    /// ## Parameters
611
    /// - `msg` - The string message.
612
    ///
613
    /// ## Examples
614
    /// ```
615
    /// use flogging::*;
616
    ///
617
    /// let mut log = Logger::console_logger(module_path!());
618
    /// log.set_level(Level::FINEST);
619
    /// log.set_fn_name("main");
620
    ///
621
    /// log.info("Some text to store.");
622
    /// ```
623
    /// Output:
624
    /// ```text
625
    /// flogging->main [INFO   ] Some text to store.
626
    /// ```
627
    ///
62834
    pub fn info(&mut self, msg: &str) {
62934
        self.log(Level::INFO, &self.fn_name(), msg);
63034
    }
631
632
    ///
633
    /// Check if a message of the given level would actually be logged by this logger.
634
    ///
635
    /// ## Parameters
636
    /// - `level` - The level to compare with.
637
    ///
638
    /// Returns `true` if it is loggable, `false` if not.
639
    ///
640108
    fn is_loggable(&self, level: &Level) -> bool {
641108
        *level >= self.level
642108
    }
643
644
    ///
645
    /// Checks whether or not this logger is processing log requests.
646
    ///
647
    /// Returns `true` if it is, `false` if not.
648
    ///
649
    /// ## Examples
650
    /// ```
651
    /// use flogging::*;
652
    ///
653
    /// let mut log = Logger::console_logger(module_path!());
654
    /// log.set_level(Level::OFF);
655
    /// log.set_fn_name("main");
656
    ///
657
    /// let msg = "The program might become unstable.";
658
    /// log.warning(msg);
659
    ///
660
    /// if !log.is_logging() {
661
    ///     eprintln!{"{msg}"};
662
    /// }
663
    /// ```
664
    /// Output to [`std::io::stderr`]:
665
    /// ```text
666
    /// The program might become unstable.
667
    /// ```
668
    ///
6694
    pub fn is_logging(&self) -> bool {
6704
        self.level() != &Level::OFF
6714
    }
672
673
    ///
674
    /// Obtain the current logging level for this Log instance.
675
    ///
6764
    pub fn level(&self) -> &Level {
6774
        &self.level
6784
    }
679
680
    ///
681
    /// Log a `LogEntry`.
682
    ///
683
    /// All the other logging methods in this class call through this method to actually
684
    /// perform any logging.
685
    ///
686
    /// ## Parameters
687
    /// - `entry` - The `LogEntry` to be published.
688
    ///
689104
    fn _log(&mut self, entry: &mut LogEntry) {
690104
        entry.set_mod_path(self.mod_path.clone());
691
692157
        for handler in self.handlers.get_mut() {
693157
            handler.1.publish(entry);
694157
        }
695104
    }
696
697
    ///
698
    /// Log a message, with no arguments.
699
    ///
700
    /// If the logger is currently enabled for the given message level then the given
701
    /// message is forwarded to all the registered output `Handler` objects.
702
    ///
703
    /// ## Parameters
704
    /// - `level` - One of the message level identifiers, e.g., SEVERE.
705
    /// - `fn_name` - The name of the function/method from-which this method
706
    ///   was called.
707
    /// - `msg` - The string message.
708
    ///
709106
    fn log(&mut self, level: Level, fn_name: &str, msg: &str) {
710106
        if !self.is_loggable(&level) {
7112
            return;
712104
        }
713
714
        // build LogEntry
715104
        let mut log_entry = LogEntry::create(level, fn_name.to_string(), msg.to_string());
716
        // Send LogEntry
717104
        self._log(&mut log_entry);
718106
    }
719
720
    ///
721
    /// Create new Logger instance, with a `ConsoleHandler`, output
722
    /// set to: [`std::io::stdout`].
723
    ///
724
    /// Logging level is set to it's default setting (INFO).
725
    ///
726
    /// All `INFO` level log entries are output without any formatting.
727
    /// All other levels are processed through the formatter, first.
728
    ///
729
    /// ## Parameters
730
    /// - `mod_path`- The module path. Suggest using [`module_path!()`].
731
    ///
732
    /// Returns a configured `Logger`.
733
    ///
734
    /// ## Examples
735
    /// ```
736
    /// use flogging::*;
737
    ///
738
    /// let mut log = Logger::pconsole_logger(module_path!());
739
    /// log.set_fn_name("main");
740
    ///
741
    /// log.warning("Don't over do it.");
742
    /// ```
743
    /// Output to stderr:
744
    /// ```text
745
    /// flogging->main [WARNING] Don't over do it.
746
    /// ```
747
    ///
7482
    pub fn pconsole_logger(mod_path: &str) -> Logger {
7492
        Logger::builder(mod_path).add_pconsole_handler().build()
7502
    }
751
752
    ///
753
    /// Remove an existing log file.
754
    ///
755
    /// The purpose of this, is to allow resetting of the log file, each time
756
    /// a test run is done.
757
    ///
758
    /// ## Note
759
    ///
760
    /// This **must** be called _before_ adding the corresponding file handler
761
    /// that is going to open this file.
762
    ///
763
    /// ## Parameters
764
    ///
765
    /// - `filename` - The name of the output log file. Must include any relevant
766
    ///   path (relative or absolute).
767
    ///
768
    /// ## Examples
769
    /// ```
770
    /// use flogging::*;
771
    ///
772
    /// Logger::remove_file("test_logs/logger.log");
773
    /// let mut log = Logger::file_logger(module_path!(), "test_logs/logger.log");
774
    /// log.set_fn_name("main");
775
    /// log.info("Something to log.");
776
    /// ```
777
    ///
7781
    pub fn remove_file(filename: &str) {
7791
        let _ = fs::remove_file(filename).is_err();
7801
    }
781
782
    ///
783
    /// Set the current function/method name.
784
    ///
785
    /// ## Parameters
786
    /// - `fn_name` - The name of the function/method in which you are
787
    ///   logging.
788
    ///
789
    /// Returns itself for chaining purposes.
790
    ///
79117
    pub fn set_fn_name(&mut self, fn_name: &str) -> &mut Self {
79217
        self.fn_name = fn_name.to_string();
79317
        self
79417
    }
795
796
    ///
797
    /// Set logging level for this Log instance.
798
    ///
799
    /// ## Parameters
800
    /// - `level` - The new logging level to set.
801
    ///
802
    /// Returns itself for chaining purposes.
803
    ///
8044
    pub fn set_level(&mut self, level: Level) -> &mut Self {
8054
        self.level = level;
8064
        self
8074
    }
808
809
    ///
810
    /// Log a SEVERE message.
811
    ///
812
    /// If the logger is currently enabled for the SEVERE message level
813
    /// then the given message is forwarded to all the registered output
814
    /// Handler objects.
815
    ///
816
    /// ## Parameters
817
    /// - `msg` - The string message.
818
    ///
819
    /// ## Examples
820
    /// ```
821
    /// use flogging::*;
822
    ///
823
    /// let mut log = Logger::console_logger(module_path!());
824
    /// log.set_level(Level::FINEST);
825
    /// log.set_fn_name("main");
826
    ///
827
    /// log.severe("Some text to store.");
828
    /// ```
829
    /// Output:
830
    /// ```text
831
    /// flogging->main [SEVERE ] Some text to store.
832
    /// ```
833
    ///
8345
    pub fn severe(&mut self, msg: &str) {
8355
        self.log(Level::SEVERE, &self.fn_name(), msg);
8365
    }
837
838
    ///
839
    /// Create new Logger instance, with a `ConsoleHandler`.
840
    ///
841
    /// Logging level is set to it's default setting (INFO).
842
    ///
843
    /// I expect this will be primarily used during unit testing of
844
    /// the logging output. Though, any requirement to pass-on the log entry,
845
    /// perhaps for further processing, would also be a valid use case.
846
    ///
847
    /// ## Parameters
848
    /// - `mod_path`- The module path. Suggest using [`module_path!()`].
849
    ///
850
    /// Returns a configured `Logger`.
851
    ///
852
    /// ## Examples
853
    /// ```
854
    /// use flogging::*;
855
    ///
856
    /// let mut log = Logger::string_logger(module_path!());
857
    /// log.set_fn_name("main");
858
    ///
859
    /// log.warning("Don't over do it.");
860
    ///
861
    /// let log_str = log.get_handler(Handler::String).unwrap().get_log();
862
    ///
863
    /// println!("{log_str}");
864
    /// ```
865
    /// Output:
866
    /// ```text
867
    /// flogging->main [WARNING] Don't over do it.
868
    /// ```
869
    ///
8704
    pub fn string_logger(mod_path: &str) -> Logger {
8714
        Logger::builder(mod_path).add_string_handler().build()
8724
    }
873
874
    ///
875
    /// Log a WARNING message.
876
    ///
877
    /// If the logger is currently enabled for the WARNING message level
878
    /// then the given message is forwarded to all the registered output
879
    /// Handler objects.
880
    ///
881
    /// ## Parameters
882
    /// - `msg` - The string message.
883
    ///
884
    /// ## Examples
885
    /// ```
886
    /// use flogging::*;
887
    ///
888
    /// let mut log = Logger::console_logger(module_path!());
889
    /// log.set_level(Level::FINEST);
890
    /// log.set_fn_name("main");
891
    ///
892
    /// log.warning("Some text to store.");
893
    /// ```
894
    /// Output:
895
    /// ```text
896
    /// flogging->main [WARNING] Some text to store.
897
    /// ```
898
    ///
89929
    pub fn warning(&mut self, msg: &str) {
90029
        self.log(Level::WARNING, &self.fn_name(), msg);
90129
    }
902
}
903
904
impl fmt::Display for Logger {
9053
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9063
        let mut buf = String::new();
907
9084
        for elem in self.handlers.borrow().iter() {
9094
            let s = format!("{}: {}\n", elem.0, elem.1);
9104
            buf.push_str(&s);
9114
        }
912
9133
        writeln!(
9143
            f,
9153
            "{}::{} - [{}]\n\n{}",
916
            self.mod_path, self.fn_name, self.level, buf
917
        )
9183
    }
919
}
920
921
#[cfg(test)]
922
mod tests;