Skip to content

Commit

Permalink
Feature: Initialize simple logger with custom logging-backend.
Browse files Browse the repository at this point in the history
  • Loading branch information
fslongjin committed Nov 5, 2023
1 parent 5965c06 commit 1bb311f
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
24 changes: 24 additions & 0 deletions examples/custom_log_backend.rs
Original file line number Diff line number Diff line change
@@ -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.");
}
80 changes: 75 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -119,6 +122,7 @@ impl SimpleLogger {

#[cfg(feature = "colored")]
colors: true,
backend: Box::new(DefaultLogBackend::new()),
}
}

Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -564,6 +600,8 @@ pub fn init_by_env() {

#[cfg(test)]
mod test {
use std::sync::{Arc, Mutex};

use super::*;

#[test]
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 1bb311f

Please sign in to comment.