1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
// Copyright 2016 Victor Brekenfeld // // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. //! Module providing the CombinedLogger Implementation use crate::{Config, SharedLogger}; use log::{set_boxed_logger, set_max_level, LevelFilter, Log, Metadata, Record, SetLoggerError}; /// The CombinedLogger struct. Provides a Logger implementation that proxies multiple Loggers as one. /// /// The purpose is to allow multiple Loggers to be set globally pub struct CombinedLogger { level: LevelFilter, logger: Vec<Box<dyn SharedLogger>>, } impl CombinedLogger { /// init function. Globally initializes the CombinedLogger as the one and only used log facility. /// /// Takes all used Loggers as a Vector argument. None of those Loggers should already be set globally. /// /// All loggers need to implement `log::Log` and `logger::SharedLogger` and need to provide a way to be /// initialized without calling `set_logger`. All loggers of this library provide a `new(..)`` method /// for that purpose. /// Fails if another logger is already set globally. /// /// # Examples /// ``` /// # extern crate simplelog; /// # use simplelog::*; /// # use std::fs::File; /// # fn main() { /// let _ = CombinedLogger::init( /// vec![ /// # #[cfg(feature = "termcolor")] /// TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed), /// WriteLogger::new(LevelFilter::Info, Config::default(), File::create("my_rust_bin.log").unwrap()) /// ] /// ); /// # } /// ``` pub fn init(logger: Vec<Box<dyn SharedLogger>>) -> Result<(), SetLoggerError> { let comblog = CombinedLogger::new(logger); set_max_level(comblog.level()); set_boxed_logger(comblog) } /// allows to create a new logger, that can be independently used, no matter whats globally set. /// /// no macros are provided for this case and you probably /// dont want to use this function, but `init()`, if you dont want to build a `CombinedLogger`. /// /// Takes all used loggers as a Vector argument. The log level is automatically determined by the /// lowest log level used by the given loggers. /// /// All loggers need to implement log::Log. /// /// # Examples /// ``` /// # extern crate simplelog; /// # use simplelog::*; /// # use std::fs::File; /// # fn main() { /// let combined_logger = CombinedLogger::new( /// vec![ /// # #[cfg(feature = "termcolor")] /// TermLogger::new(LevelFilter::Debug, Config::default(), TerminalMode::Mixed), /// WriteLogger::new(LevelFilter::Info, Config::default(), File::create("my_rust_bin.log").unwrap()) /// ] /// ); /// # } /// ``` pub fn new(logger: Vec<Box<dyn SharedLogger>>) -> Box<CombinedLogger> { let mut log_level = LevelFilter::Off; for log in &logger { if log_level < log.level() { log_level = log.level(); } } Box::new(CombinedLogger { level: log_level, logger: logger, }) } } impl Log for CombinedLogger { fn enabled(&self, metadata: &Metadata<'_>) -> bool { metadata.level() <= self.level } fn log(&self, record: &Record<'_>) { if self.enabled(record.metadata()) { for log in &self.logger { log.log(record); } } } fn flush(&self) { for log in &self.logger { log.flush(); } } } impl SharedLogger for CombinedLogger { fn level(&self) -> LevelFilter { self.level } fn config(&self) -> Option<&Config> { None } fn as_log(self: Box<Self>) -> Box<dyn Log> { Box::new(*self) } }