浏览代码

Feature: Initialize simple logger with custom logging-backend. (#1)

LoGin 1 年之前
父节点
当前提交
36ab404868
共有 3 个文件被更改,包括 102 次插入5 次删除
  1. 3 0
      Cargo.toml
  2. 24 0
      examples/custom_log_backend.rs
  3. 75 5
      src/lib.rs

+ 3 - 0
Cargo.toml

@@ -27,6 +27,9 @@ windows-sys = { version = "^0.42.0", features = ["Win32_System_Console", "Win32_
 name = "colors"
 required-features = ["colors"]
 
+[[example]]
+name = "custom_log_backend"
+
 [[example]]
 name = "threads"
 required-features = ["threads"]

+ 24 - 0
examples/custom_log_backend.rs

@@ -0,0 +1,24 @@
+use simple_logger::{LogBackend, SimpleLogger};
+
+struct CustomLogBackend;
+
+impl LogBackend for CustomLogBackend {
+    fn log(&self, message: String) {
+        println!("[Custom log backend] {}", message);
+    }
+}
+
+impl CustomLogBackend {
+    fn new() -> Box<Self> {
+        Box::new(Self)
+    }
+}
+
+fn main() {
+    SimpleLogger::new()
+        .with_backend(CustomLogBackend::new())
+        .init()
+        .unwrap();
+
+    log::warn!("This is an example message.");
+}

+ 75 - 5
src/lib.rs

@@ -89,6 +89,9 @@ pub struct SimpleLogger {
     /// This field is only available if the `color` feature is enabled.
     #[cfg(feature = "colored")]
     colors: bool,
+
+    /// The backend used to log messages.
+    backend: Box<dyn LogBackend>,
 }
 
 impl SimpleLogger {
@@ -119,6 +122,7 @@ impl SimpleLogger {
 
             #[cfg(feature = "colored")]
             colors: true,
+            backend: Box::new(DefaultLogBackend::new()),
         }
     }
 
@@ -342,6 +346,13 @@ impl SimpleLogger {
         self
     }
 
+    /// Set the backend used to log messages.
+    #[must_use = "You must call init() to begin logging"]
+    pub fn with_backend(mut self, backend: Box<dyn LogBackend>) -> SimpleLogger {
+        self.backend = backend;
+        self
+    }
+
     /// 'Init' the actual logger, instantiate it and configure it,
     /// this method MUST be called in order for the logger to be effective.
     pub fn init(mut self) -> Result<(), SetLoggerError> {
@@ -477,11 +488,7 @@ impl Log for SimpleLogger {
 
             let message = format!("{}{} [{}{}] {}", timestamp, level_string, target, thread, record.args());
 
-            #[cfg(not(feature = "stderr"))]
-            println!("{}", message);
-
-            #[cfg(feature = "stderr")]
-            eprintln!("{}", message);
+            self.backend.log(message);
         }
     }
 
@@ -517,6 +524,35 @@ fn set_up_color_terminal() {
     }
 }
 
+/// A trait for logging messages.
+///
+/// We use this trait to allow the user to choose the backend used to log messages.
+pub trait LogBackend: Send + Sync {
+    fn log(&self, message: String);
+}
+
+/// The default backend used by [`SimpleLogger`].
+///
+/// This backend logs messages to stdout or stderr.
+#[derive(PartialEq, Eq)]
+pub struct DefaultLogBackend;
+
+impl DefaultLogBackend {
+    pub fn new() -> Self {
+        DefaultLogBackend
+    }
+}
+
+impl LogBackend for DefaultLogBackend {
+    fn log(&self, message: String) {
+        #[cfg(not(feature = "stderr"))]
+        println!("{}", message);
+
+        #[cfg(feature = "stderr")]
+        eprintln!("{}", message);
+    }
+}
+
 /// Initialise the logger with its default configuration.
 ///
 /// Log messages will not be filtered.
@@ -564,6 +600,8 @@ pub fn init_by_env() {
 
 #[cfg(test)]
 mod test {
+    use std::sync::{Arc, Mutex};
+
     use super::*;
 
     #[test]
@@ -646,6 +684,38 @@ mod test {
         assert!(builder.colors == false);
     }
 
+    #[test]
+    fn test_with_custom_backend() {
+        let result_collection: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
+
+        struct CustomLogBackend {
+            results: Arc<Mutex<Vec<String>>>,
+        }
+
+        impl LogBackend for CustomLogBackend {
+            fn log(&self, message: String) {
+                self.results
+                    .lock()
+                    .unwrap()
+                    .push(format!("[Custom log backend] {}", message));
+            }
+        }
+
+        impl CustomLogBackend {
+            fn new(results: Arc<Mutex<Vec<String>>>) -> Box<Self> {
+                Box::new(Self { results })
+            }
+        }
+
+        let backend = CustomLogBackend::new(Arc::clone(&result_collection));
+
+        let logger = SimpleLogger::new().with_backend(backend);
+        logger.backend.log("Test message".to_string());
+
+        assert!(result_collection.lock().unwrap().len() == 1);
+        assert!(result_collection.lock().unwrap()[0] == "[Custom log backend] Test message");
+    }
+
     fn create_log(name: &str, level: Level) -> Metadata {
         let mut builder = Metadata::builder();
         builder.level(level);