custom_appender/
custom_appender.rs1use std::sync::{Arc, Mutex};
6
7use log4rc::{Appender, Layout, LogEvent, LogLevel, Logger};
8
9struct KeyValueLayout;
11
12impl Layout for KeyValueLayout {
13 fn format(&self, event: &LogEvent) -> String {
14 format!("level={} message={}", event.level.as_str(), event.message)
15 }
16}
17
18#[derive(Clone)]
20struct VecAppender {
21 layout: Arc<dyn Layout>,
22 messages: Arc<Mutex<Vec<String>>>,
23}
24
25impl VecAppender {
26 fn new(layout: Arc<dyn Layout>) -> Self {
27 Self {
28 layout,
29 messages: Arc::new(Mutex::new(Vec::new())),
30 }
31 }
32
33 fn messages(&self) -> Vec<String> {
34 self.messages.lock().unwrap().clone()
35 }
36}
37
38impl Appender for VecAppender {
39 fn append(&self, event: &LogEvent) {
40 self.messages.lock().unwrap().push(self.layout.format(event));
41 }
42}
43
44fn main() {
45 let collector = VecAppender::new(Arc::new(KeyValueLayout));
46
47 Logger::builder(LogLevel::Info)
49 .appender(Box::new(collector.clone()))
50 .init();
51
52 log4rc::info!("Hello, appender!");
53 log4rc::debug!("This is filtered out at Info level");
54 log4rc::error!("Something went wrong");
55
56 for line in collector.messages() {
58 println!("captured: {line}");
59 }
60}