1use crate::buf_file_impl::LogBufFile;
2use crate::console_impl::LogConsole;
3use crate::file_impl::LogRawFile;
4use crate::log_impl::setup_log;
5use crate::{
6 formatter::{FormatRecord, TimeFormatter},
7 log_impl::LogSink,
8 time::Timer,
9};
10use log::{Level, LevelFilter, Record};
11use std::hash::{DefaultHasher, Hash, Hasher};
12use std::path::Path;
13
14#[derive(Default)]
17pub struct Builder {
18 pub dynamic: bool,
25
26 pub rotation_signals: Vec<i32>,
29
30 pub panic: bool,
32
33 pub continue_when_panic: bool,
35
36 pub(crate) sinks: Vec<Box<dyn SinkConfigTrait>>,
38}
39
40impl Builder {
41 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn test(mut self) -> Self {
48 self.dynamic = true;
49 self.rotation_signals.clear();
50 self
51 }
52
53 pub fn signal(mut self, signal: i32) -> Self {
55 self.rotation_signals.push(signal);
56 self
57 }
58
59 pub fn raw_file(mut self, config: LogRawFile) -> Self {
61 self.sinks.push(Box::new(config));
62 self
63 }
64
65 pub fn buf_file(mut self, config: LogBufFile) -> Self {
67 self.sinks.push(Box::new(config));
68 self
69 }
70
71 pub fn console(mut self, config: LogConsole) -> Self {
73 self.sinks.push(Box::new(config));
74 self
75 }
76
77 pub fn get_max_level(&self) -> LevelFilter {
79 let mut max_level = Level::Error;
80 for sink in &self.sinks {
81 let level = sink.get_level();
82 if level > max_level {
83 max_level = level;
84 }
85 }
86 return max_level.to_level_filter();
87 }
88
89 pub(crate) fn cal_checksum(&self) -> u64 {
91 let mut hasher = Box::new(DefaultHasher::new()) as Box<dyn Hasher>;
92 self.dynamic.hash(&mut hasher);
93 self.rotation_signals.hash(&mut hasher);
94 self.panic.hash(&mut hasher);
95 self.continue_when_panic.hash(&mut hasher);
96 for sink in &self.sinks {
97 sink.write_hash(&mut hasher);
98 }
99 hasher.finish()
100 }
101
102 pub fn build(self) -> Result<(), ()> {
105 setup_log(self)
106 }
107}
108
109pub(crate) trait SinkConfigTrait {
110 fn get_level(&self) -> Level;
112 #[allow(dead_code)]
114 fn get_file_path(&self) -> Option<Box<Path>>;
115 fn write_hash(&self, hasher: &mut Box<dyn Hasher>);
117 fn build(&self) -> LogSink;
119}
120
121pub type FormatFunc = fn(FormatRecord) -> String;
122
123#[derive(Clone, Hash)]
125pub struct LogFormat {
126 time_fmt: &'static str,
127 format_fn: FormatFunc,
128}
129
130impl LogFormat {
131 pub const fn new(time_fmt: &'static str, format_fn: FormatFunc) -> Self {
154 Self { time_fmt, format_fn }
155 }
156
157 #[inline(always)]
158 pub(crate) fn process(&self, now: &Timer, record: &Record) -> String {
159 let time = TimeFormatter { now, fmt_str: self.time_fmt };
160 let r = FormatRecord { record, time };
161 return (self.format_fn)(r);
162 }
163}