ezlog/
init.rs

1use std::ptr;
2
3use crate::{
4    EZLogCallback,
5    EZMsg,
6    EZRecord,
7    EventListener,
8    EventPrinter,
9    Formatter,
10    LogService,
11};
12
13/// InitBuilder is used to init ezlog
14pub struct InitBuilder {
15    listener: Option<&'static dyn EventListener>,
16    debug: bool,
17    layers: Vec<Box<dyn MsgHandler>>,
18    callback: Option<Box<dyn EZLogCallback>>,
19    formatter: Option<Box<dyn Formatter>>,
20}
21
22impl InitBuilder {
23    pub fn new() -> Self {
24        Self {
25            listener: None,
26            debug: false,
27            layers: vec![],
28            callback: None,
29            formatter: None,
30        }
31    }
32
33    /// set debug mode
34    ///
35    /// # Example
36    /// ```
37    /// ezlog::InitBuilder::new()
38    ///     .debug(true)
39    ///     .init();
40    /// ```
41    pub fn debug(mut self, debug: bool) -> Self {
42        self.debug = debug;
43        self
44    }
45
46    /// add a listener to handle all events
47    ///
48    /// # Example
49    /// ```
50    /// use ezlog::Event;
51    /// use ezlog::LogError;
52    ///
53    /// struct MyEventListener;
54    ///
55    /// impl ezlog::EventListener for MyEventListener {
56    ///     fn on_event(&self, event: Event, desc: &str) {
57    ///         println!("event: {:?}, desc: {}", event, desc);
58    ///     }
59    ///
60    ///     fn on_error_event(&self, event: Event, desc: &str, err: &LogError) {
61    ///         println!("event: {:?}, desc: {}, err: {}", event, desc, err);
62    ///     }
63    /// }
64    /// static LISTENER: MyEventListener = MyEventListener{};
65    /// ezlog::InitBuilder::new()
66    ///     .with_event_listener(&LISTENER)
67    ///     .init();
68    ///```
69    pub fn with_event_listener(mut self, listener: &'static dyn EventListener) -> Self {
70        self.listener = Some(listener);
71        self
72    }
73
74    /// add a layer to handle all operations
75    ///
76    /// # Example
77    /// ```
78    /// use ezlog::MsgHandler;
79    /// struct MyLayer;
80    ///
81    /// impl MyLayer {
82    ///     pub fn new() -> Self {
83    ///         Self {}
84    ///     }
85    /// }
86    ///
87    /// impl ezlog::MsgHandler for MyLayer {
88    ///     fn handle(&self, msg: &ezlog::EZMsg) {
89    ///         println!("{:?}", msg);
90    ///     }
91    /// }
92    ///
93    /// ezlog::InitBuilder::new()
94    ///     .with_layer(Box::new(MyLayer::new()))
95    ///     .init();
96    /// ```
97    pub fn with_layer(mut self, layer: Box<dyn MsgHandler>) -> Self {
98        self.layers.push(layer);
99        self
100    }
101
102    /// add a callback to receive log file path request result
103    ///
104    /// # Example
105    /// ```
106    /// let on_success : fn(&str, &str, &[&str]) = |name, date, logs| {
107    ///     println!("on_success: name: {}, desc: {}, tags: {:?}", name, date, logs);
108    /// };
109    ///
110    /// let on_fail : fn(&str, &str, &str) = |name, date, err| {
111    ///     println!("on_fail: name: {}, desc: {}, err: {}", name, date, err);
112    /// };
113    /// ezlog::InitBuilder::new()
114    ///     .with_request_callback_fn(on_success, on_fail)
115    ///     .init();
116    /// ```
117    ///
118    pub fn with_request_callback_fn(
119        mut self,
120        on_success: fn(&str, &str, &[&str]),
121        on_fail: fn(&str, &str, &str),
122    ) -> Self {
123        let callback = EZLogCallbackProxy::new(on_success, on_fail);
124        self.callback = Some(Box::new(callback));
125        self
126    }
127
128    /// add a callback to receive log file path request result
129    ///
130    /// # Example
131    /// ```
132    /// use ezlog::EZLogCallback;
133    ///
134    /// struct MyCallback {}
135    ///
136    /// impl EZLogCallback for MyCallback {
137    ///    fn on_fetch_success(&self, name: &str, date: &str, logs: &[&str]) {
138    ///        println!("on_success: name: {}, desc: {}, tags: {:?}", name, date, logs);
139    ///    }
140    ///
141    ///    fn on_fetch_fail(&self, name: &str, date: &str, err: &str) {
142    ///        println!("on_fail: name: {}, desc: {}, err: {}", name, date, err);
143    ///    }
144    /// }
145    ///
146    /// let callback: MyCallback = MyCallback {  };
147    /// ezlog::InitBuilder::new()
148    ///     .with_request_callback(callback)
149    ///     .init();
150    ///
151    pub fn with_request_callback(mut self, callback: impl EZLogCallback + 'static) -> Self {
152        let boxed_callback = Box::new(callback);
153        self.callback = Some(boxed_callback);
154        self
155    }
156
157    ///  add a layer to handle all operations
158    ///
159    /// # Example
160    /// ```
161    /// ezlog::InitBuilder::new()
162    ///     .with_layer_fn(|msg| println!("{:?}", msg))
163    ///     .init();
164    /// ```
165    pub fn with_layer_fn(mut self, layer: fn(&EZMsg)) -> Self {
166        self.layers.push(Box::new(MsgHandlerFn::new(layer)));
167        self
168    }
169
170    /// set a formatter to format log record
171    ///
172    /// # Example
173    /// ```
174    /// use ezlog::Formatter;
175    /// use ezlog::EZRecord;
176    /// struct MyFormatter;
177    /// impl Formatter for MyFormatter {
178    ///    fn format(&self, msg: &EZRecord) -> std::result::Result<Vec<u8>, ezlog::LogError> {
179    ///       Ok(format!("{:?}", msg).into_bytes())
180    ///   }
181    /// }
182    /// ezlog::InitBuilder::new()
183    ///    .with_formatter(Box::new(MyFormatter))
184    ///    .init();
185    /// ```
186    ///
187    pub fn with_formatter(mut self, formatter: Box<dyn Formatter>) -> Self {
188        self.formatter = Some(formatter);
189        self
190    }
191
192    /// set a formatter to format log record
193    ///
194    /// # Example
195    /// ```
196    /// ezlog::InitBuilder::new()
197    ///    .with_formatter_fn(|msg| format!("{:?}", msg).into_bytes())
198    ///    .init();
199    /// ```
200    pub fn with_formatter_fn(mut self, op: fn(&EZRecord) -> Vec<u8>) -> Self {
201        self.formatter = Some(Box::new(FormatterProxy::new(op)));
202        self
203    }
204
205    /// real init ezlog
206    pub fn init(self) -> EZLog {
207        crate::LOG_SERVICE_INIT.call_once(|| unsafe {
208            #[cfg(all(target_os = "android", feature = "android_logger"))]
209            if self.debug {
210                android_logger::init_once(
211                    android_logger::Config::default()
212                        .with_max_level(log::LevelFilter::Trace)
213                        .with_log_buffer(android_logger::LogId::Main),
214                );
215            }
216
217            // if debug, set a default event listener
218            if self.debug && self.listener.is_none() {
219                static EVENT: EventPrinter = EventPrinter {};
220                crate::set_event_listener(&EVENT);
221            }
222
223            if let Some(listener) = self.listener {
224                crate::set_event_listener(listener);
225            }
226
227            if let Some(callback) = self.callback {
228                crate::set_boxed_callback(callback);
229            }
230
231            if let Some(formatter) = self.formatter {
232                crate::set_boxed_formatter(formatter);
233            }
234            let mut service = LogService::new();
235            service.layers = self.layers;
236            ptr::write(crate::LOG_SERVICE.as_mut_ptr(), service);
237        });
238        EZLog {}
239    }
240}
241
242impl Default for InitBuilder {
243    fn default() -> Self {
244        Self::new()
245    }
246}
247
248pub trait MsgHandler {
249    fn handle(&self, msg: &EZMsg);
250}
251
252pub(crate) struct MsgHandlerFn {
253    handler: fn(&EZMsg),
254}
255
256impl MsgHandlerFn {
257    pub fn new(handler: fn(&EZMsg)) -> Self {
258        Self { handler }
259    }
260}
261
262impl MsgHandler for MsgHandlerFn {
263    fn handle(&self, msg: &EZMsg) {
264        (self.handler)(msg);
265    }
266}
267
268struct EZLogCallbackProxy {
269    success_fn: fn(&str, &str, &[&str]),
270    fail_fn: fn(&str, &str, &str),
271}
272
273impl EZLogCallbackProxy {
274    pub fn new(success_fn: fn(&str, &str, &[&str]), fail_fn: fn(&str, &str, &str)) -> Self {
275        Self {
276            success_fn,
277            fail_fn,
278        }
279    }
280}
281
282impl EZLogCallback for EZLogCallbackProxy {
283    fn on_fetch_success(&self, name: &str, date: &str, logs: &[&str]) {
284        (self.success_fn)(name, date, logs);
285    }
286
287    fn on_fetch_fail(&self, name: &str, date: &str, err: &str) {
288        (self.fail_fn)(name, date, err);
289    }
290}
291
292struct FormatterProxy {
293    op: fn(&EZRecord) -> Vec<u8>,
294}
295impl FormatterProxy {
296    fn new(op: fn(&EZRecord) -> Vec<u8>) -> FormatterProxy {
297        FormatterProxy { op }
298    }
299}
300
301impl Formatter for FormatterProxy {
302    fn format(&self, msg: &EZRecord) -> std::result::Result<Vec<u8>, crate::LogError> {
303        Ok((self.op)(msg))
304    }
305}
306
307#[derive(Clone, Copy)]
308pub struct EZLog {}
309
310#[cfg(feature = "log")]
311use log::{
312    Metadata,
313    Record,
314};
315
316#[cfg(feature = "log")]
317impl log::Log for EZLog {
318    fn enabled(&self, _metadata: &Metadata) -> bool {
319        true
320    }
321
322    fn log(&self, record: &Record) {
323        crate::log(record.into())
324    }
325
326    fn flush(&self) {}
327}