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}