nonblock_logger/
consumer.rs1use crate::{Error, Receiver};
2use log::LevelFilter;
3use std::io::{stderr, stdout, BufWriter, Stderr, Stdout, Write};
4use std::{fmt, fs::File};
5
6pub trait Consumer: Send + Sync + 'static {
7 fn boxed(self) -> Result<Box<dyn Consumer>, Error>;
8 fn consume(&mut self, channel: Receiver);
9}
10
11impl Consumer for BaseConsumer {
12 fn boxed(self) -> Result<Box<dyn Consumer>, Error> {
13 Ok(Box::new(self) as _)
14 }
15
16 fn consume(&mut self, channel: Receiver) {
17 for message in channel {
18 if let Some(message) = message {
19 for (level, ref mut w) in self.outputers.iter_mut() {
20 if *level >= message.level {
21 if let Err(e) = w.write_all(message.content.as_bytes()) {
22 panic!("failed write log to {}: {}", (&*w).desc(), e);
23 }
24 }
25 }
26 } else {
27 break;
28 }
29 }
30 }
31}
32
33#[derive(Default)]
34pub struct BaseConsumer {
35 outputers: Vec<(LevelFilter, Box<dyn Outputer>)>,
36}
37
38impl fmt::Debug for BaseConsumer {
39 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
40 fmt.debug_struct("BaseConsumer")
41 .field(
42 "outputers",
43 &self.outputers.iter().map(|(l, o)| (l, o.desc())).collect::<Vec<_>>(),
44 )
45 .finish()
46 }
47}
48
49impl BaseConsumer {
50 pub fn new() -> Self {
51 Self::default()
52 }
53
54 pub fn chain<O: Outputer>(mut self, level: LevelFilter, outputer: O) -> Result<Self, Error> {
55 self.outputers.push((level, outputer.boxed()?));
56 Ok(self)
57 }
58
59 pub fn stdout(level: LevelFilter) -> Self {
60 Self::new().chain(level, stdout()).unwrap()
61 }
62
63 pub fn stderr(level: LevelFilter) -> Self {
64 Self::new().chain(level, stderr()).unwrap()
65 }
66
67 pub fn file(level: LevelFilter, file: File) -> Self {
68 Self::new().chain(level, file).unwrap()
69 }
70
71 pub fn bufwriter<W>(level: LevelFilter, bufwriter: BufWriter<W>) -> Self
72 where
73 W: Write + Send + Sync + 'static,
74 {
75 Self::new().chain(level, bufwriter).unwrap()
76 }
77}
78
79pub trait Outputer: Write + Send + Sync + 'static {
80 fn boxed(self) -> Result<Box<dyn Outputer>, Error>;
81 fn desc(&self) -> &str;
82}
83
84impl Outputer for Stdout {
85 fn boxed(self) -> Result<Box<dyn Outputer>, Error> {
86 Ok(Box::new(self) as _)
87 }
88
89 fn desc(&self) -> &str {
90 "stdout"
91 }
92}
93
94impl Outputer for Stderr {
95 fn boxed(self) -> Result<Box<dyn Outputer>, Error> {
96 Ok(Box::new(self) as _)
97 }
98
99 fn desc(&self) -> &str {
100 "stderr"
101 }
102}
103
104impl Outputer for File {
105 fn boxed(self) -> Result<Box<dyn Outputer>, Error> {
106 Ok(Box::new(self) as _)
107 }
108
109 fn desc(&self) -> &str {
110 "file"
111 }
112}
113
114impl<W> Outputer for BufWriter<W>
115where
116 W: Write + Send + Sync + 'static,
117{
118 fn boxed(self) -> Result<Box<dyn Outputer>, Error> {
119 Ok(Box::new(self) as _)
120 }
121
122 fn desc(&self) -> &str {
123 "bufwriter"
124 }
125}