1use std::collections::HashSet;
2use std::path::{Path, PathBuf};
3use std::thread;
4#[cfg(feature = "_log")]
5use flexi_logger::{Cleanup, Criterion, DeferredNow, Duplicate, FileSpec, FlexiLoggerError, Naming, Record};
6use flexi_logger::filter::{LogLineFilter, LogLineWriter};
7#[cfg(all(feature = "_log", not(feature = "nolog")))]
8pub use tracing::{info, warn, trace, debug, error};
9use tracing::log;
10use tracing::log::Metadata;
11
12#[cfg(feature = "nolog")]
13#[macro_export]
14macro_rules! error {
15 (name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
17 );
18 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
19 );
20 (name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
21 );
22 (name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
23 );
24 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
25 );
26
27 (name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
29 );
30 (name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
31 );
32 (name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
33 );
34 (name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
35 );
36 (name: $name:expr, target: $target:expr, $($arg:tt)+ ) => (
37 );
38
39 (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
41 );
42 (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
43 );
44 (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
45 );
46 (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
47 );
48 (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
49 );
50
51 (name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
53 );
54 (name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
55 );
56 (name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
57 );
58 (name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
59 );
60 (name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => (
61 );
62
63 (name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => (
65 );
66 (name: $name:expr, $($k:ident).+ $($field:tt)* ) => (
67 );
68 (name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => (
69 );
70 (name: $name:expr, %$($k:ident).+ $($field:tt)* ) => (
71 );
72 (name: $name:expr, $($arg:tt)+ ) => (
73 );
74
75 (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
77 );
78 (target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
79 );
80 (target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
81 );
82 (target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
83 );
84 (target: $target:expr, $($arg:tt)+ ) => (
85 );
86
87 (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => (
89 );
90 (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => (
91 );
92 (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => (
93 );
94 (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => (
95 );
96 (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => (
97 );
98 (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => (
99 );
100 (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => (
101 );
102 (parent: $parent:expr, $($arg:tt)+) => (
103 );
104
105 ({ $($field:tt)+ }, $($arg:tt)+ ) => (
107 );
108 ($($k:ident).+ = $($field:tt)*) => (
109 );
110 (?$($k:ident).+ = $($field:tt)*) => (
111 );
112 (%$($k:ident).+ = $($field:tt)*) => (
113 );
114 ($($k:ident).+, $($field:tt)*) => (
115 );
116 (?$($k:ident).+, $($field:tt)*) => (
117 );
118 (%$($k:ident).+, $($field:tt)*) => (
119 );
120 (?$($k:ident).+) => (
121 );
122 (%$($k:ident).+) => (
123 );
124 ($($k:ident).+) => (
125 );
126 ($($arg:tt)+) => (
127 );
128}
129
130#[cfg(feature = "nolog")]
131#[macro_export]
132macro_rules! debug {
133 (name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
135 );
136 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
137 );
138 (name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
139 );
140 (name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
141 );
142 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
143 );
144
145 (name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
147 );
148 (name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
149 );
150 (name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
151 );
152 (name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
153 );
154 (name: $name:expr, target: $target:expr, $($arg:tt)+ ) => (
155 );
156
157 (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
159 );
160 (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
161 );
162 (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
163 );
164 (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
165 );
166 (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
167 );
168
169 (name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
171 );
172 (name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
173 );
174 (name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
175 );
176 (name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
177 );
178 (name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => (
179 );
180
181 (name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => (
183 );
184 (name: $name:expr, $($k:ident).+ $($field:tt)* ) => (
185 );
186 (name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => (
187 );
188 (name: $name:expr, %$($k:ident).+ $($field:tt)* ) => (
189 );
190 (name: $name:expr, $($arg:tt)+ ) => (
191 );
192
193 (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
195 );
196 (target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
197 );
198 (target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
199 );
200 (target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
201 );
202 (target: $target:expr, $($arg:tt)+ ) => (
203 );
204
205 (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => (
207 );
208 (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => (
209 );
210 (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => (
211 );
212 (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => (
213 );
214 (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => (
215 );
216 (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => (
217 );
218 (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => (
219 );
220 (parent: $parent:expr, $($arg:tt)+) => (
221 );
222
223 ({ $($field:tt)+ }, $($arg:tt)+ ) => (
225 );
226 ($($k:ident).+ = $($field:tt)*) => (
227 );
228 (?$($k:ident).+ = $($field:tt)*) => (
229 );
230 (%$($k:ident).+ = $($field:tt)*) => (
231 );
232 ($($k:ident).+, $($field:tt)*) => (
233 );
234 (?$($k:ident).+, $($field:tt)*) => (
235 );
236 (%$($k:ident).+, $($field:tt)*) => (
237 );
238 (?$($k:ident).+) => (
239 );
240 (%$($k:ident).+) => (
241 );
242 ($($k:ident).+) => (
243 );
244 ($($arg:tt)+) => (
245 );
246}
247
248#[cfg(feature = "nolog")]
249#[macro_export]
250macro_rules! trace {
251 (name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
253 );
254 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
255 );
256 (name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
257 );
258 (name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
259 );
260 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
261 );
262
263 (name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
265 );
266 (name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
267 );
268 (name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
269 );
270 (name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
271 );
272 (name: $name:expr, target: $target:expr, $($arg:tt)+ ) => (
273 );
274
275 (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
277 );
278 (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
279 );
280 (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
281 );
282 (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
283 );
284 (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
285 );
286
287 (name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
289 );
290 (name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
291 );
292 (name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
293 );
294 (name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
295 );
296 (name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => (
297 );
298
299 (name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => (
301 );
302 (name: $name:expr, $($k:ident).+ $($field:tt)* ) => (
303 );
304 (name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => (
305 );
306 (name: $name:expr, %$($k:ident).+ $($field:tt)* ) => (
307 );
308 (name: $name:expr, $($arg:tt)+ ) => (
309 );
310
311 (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
313 );
314 (target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
315 );
316 (target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
317 );
318 (target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
319 );
320 (target: $target:expr, $($arg:tt)+ ) => (
321 );
322
323 (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => (
325 );
326 (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => (
327 );
328 (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => (
329 );
330 (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => (
331 );
332 (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => (
333 );
334 (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => (
335 );
336 (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => (
337 );
338 (parent: $parent:expr, $($arg:tt)+) => (
339 );
340
341 ({ $($field:tt)+ }, $($arg:tt)+ ) => (
343 );
344 ($($k:ident).+ = $($field:tt)*) => (
345 );
346 (?$($k:ident).+ = $($field:tt)*) => (
347 );
348 (%$($k:ident).+ = $($field:tt)*) => (
349 );
350 ($($k:ident).+, $($field:tt)*) => (
351 );
352 (?$($k:ident).+, $($field:tt)*) => (
353 );
354 (%$($k:ident).+, $($field:tt)*) => (
355 );
356 (?$($k:ident).+) => (
357 );
358 (%$($k:ident).+) => (
359 );
360 ($($k:ident).+) => (
361 );
362 ($($arg:tt)+) => (
363 );
364}
365
366#[cfg(feature = "nolog")]
367#[macro_export]
368macro_rules! info {
369 (name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
371 );
372 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
373 );
374 (name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
375 );
376 (name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
377 );
378 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
379 );
380
381 (name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
383 );
384 (name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
385 );
386 (name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
387 );
388 (name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
389 );
390 (name: $name:expr, target: $target:expr, $($arg:tt)+ ) => (
391 );
392
393 (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
395 );
396 (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
397 );
398 (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
399 );
400 (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
401 );
402 (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
403 );
404
405 (name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
407 );
408 (name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
409 );
410 (name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
411 );
412 (name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
413 );
414 (name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => (
415 );
416
417 (name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => (
419 );
420 (name: $name:expr, $($k:ident).+ $($field:tt)* ) => (
421 );
422 (name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => (
423 );
424 (name: $name:expr, %$($k:ident).+ $($field:tt)* ) => (
425 );
426 (name: $name:expr, $($arg:tt)+ ) => (
427 );
428
429 (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
431 );
432 (target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
433 );
434 (target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
435 );
436 (target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
437 );
438 (target: $target:expr, $($arg:tt)+ ) => (
439 );
440
441 (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => (
443 );
444 (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => (
445 );
446 (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => (
447 );
448 (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => (
449 );
450 (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => (
451 );
452 (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => (
453 );
454 (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => (
455 );
456 (parent: $parent:expr, $($arg:tt)+) => (
457 );
458
459 ({ $($field:tt)+ }, $($arg:tt)+ ) => (
461 );
462 ($($k:ident).+ = $($field:tt)*) => (
463 );
464 (?$($k:ident).+ = $($field:tt)*) => (
465 );
466 (%$($k:ident).+ = $($field:tt)*) => (
467 );
468 ($($k:ident).+, $($field:tt)*) => (
469 );
470 (?$($k:ident).+, $($field:tt)*) => (
471 );
472 (%$($k:ident).+, $($field:tt)*) => (
473 );
474 (?$($k:ident).+) => (
475 );
476 (%$($k:ident).+) => (
477 );
478 ($($k:ident).+) => (
479 );
480 ($($arg:tt)+) => (
481 );
482}
483
484
485#[cfg(feature = "nolog")]
486#[macro_export]
487macro_rules! warn {
488 (name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
490 );
491 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
492 );
493 (name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
494 );
495 (name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
496 );
497 (name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
498 );
499
500 (name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
502 );
503 (name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
504 );
505 (name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
506 );
507 (name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
508 );
509 (name: $name:expr, target: $target:expr, $($arg:tt)+ ) => (
510 );
511
512 (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
514 );
515 (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
516 );
517 (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
518 );
519 (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
520 );
521 (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => (
522 );
523
524 (name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => (
526 );
527 (name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => (
528 );
529 (name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => (
530 );
531 (name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => (
532 );
533 (name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => (
534 );
535
536 (name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => (
538 );
539 (name: $name:expr, $($k:ident).+ $($field:tt)* ) => (
540 );
541 (name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => (
542 );
543 (name: $name:expr, %$($k:ident).+ $($field:tt)* ) => (
544 );
545 (name: $name:expr, $($arg:tt)+ ) => (
546 );
547
548 (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => (
550 );
551 (target: $target:expr, $($k:ident).+ $($field:tt)* ) => (
552 );
553 (target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => (
554 );
555 (target: $target:expr, %$($k:ident).+ $($field:tt)* ) => (
556 );
557 (target: $target:expr, $($arg:tt)+ ) => (
558 );
559
560 (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => (
562 );
563 (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => (
564 );
565 (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => (
566 );
567 (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => (
568 );
569 (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => (
570 );
571 (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => (
572 );
573 (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => (
574 );
575 (parent: $parent:expr, $($arg:tt)+) => (
576 );
577
578 ({ $($field:tt)+ }, $($arg:tt)+ ) => (
580 );
581 ($($k:ident).+ = $($field:tt)*) => (
582 );
583 (?$($k:ident).+ = $($field:tt)*) => (
584 );
585 (%$($k:ident).+ = $($field:tt)*) => (
586 );
587 ($($k:ident).+, $($field:tt)*) => (
588 );
589 (?$($k:ident).+, $($field:tt)*) => (
590 );
591 (%$($k:ident).+, $($field:tt)*) => (
592 );
593 (?$($k:ident).+) => (
594 );
595 (%$($k:ident).+) => (
596 );
597 ($($k:ident).+) => (
598 );
599 ($($arg:tt)+) => (
600 );
601}
602
603
604#[cfg(feature = "_log")]
605fn custom_format(writer: &mut dyn std::io::Write, now: &mut DeferredNow, record: &Record) -> std::io::Result<()> {
606 let file = match record.file() {
607 None => {
608 "<unknown>".to_string()
609 }
610 Some(path) => {
611 Path::new(path).file_name().map(|v| v.to_string_lossy().to_string()).unwrap_or("<unknown>".to_string())
612 }
613 };
614 let module = if let Some((first, _)) = record.metadata().target().split_once("::") {
615 first
616 } else {
617 record.metadata().target()
618 };
619 write!(
620 writer,
621 "{} [{}] [{}:{}:{}] [{}] - {}",
622 now.format("%Y-%m-%d %H:%M:%S"),
623 record.level(),
624 module,
625 file,
626 record.line().unwrap_or(0),
627 thread::current().name().unwrap_or(format!("{:?}", thread::current().id()).as_str()),
628 &record.args()
629 )
630}
631pub struct Logger {
632 app_name: String,
633 log_level: String,
634 log_to_file: bool,
635 log_path: PathBuf,
636 log_file_size: u64,
637 log_file_count: usize,
638 instance_id: String,
639 output_console: bool,
640 filter: Vec<String>,
641 module_logs: Vec<(String, String)>,
642}
643
644impl Logger {
645 pub fn new(app_name: &str) -> Self {
646 Self {
647 app_name: app_name.to_string(),
648 log_level: "info".to_string(),
649 log_to_file: false,
650 log_path: std::env::current_dir().unwrap().join("logs"),
651 log_file_size: 10 * 1024 * 1024,
652 log_file_count: 10,
653 instance_id: "".to_string(),
654 output_console: true,
655 filter: vec![],
656 module_logs: vec![],
657 }
658 }
659
660 pub fn set_instance_id(mut self, instance_id: &str) -> Self {
661 self.instance_id = instance_id.to_string();
662 self
663 }
664
665 pub fn set_process_id_to_instance_id(mut self) -> Self {
666 self.instance_id = format!("{}", std::process::id());
667 self
668 }
669
670 pub fn set_log_level(mut self, level: &str) -> Self {
671 self.log_level = level.to_string();
672 self
673 }
674
675 pub fn set_log_to_file(mut self, to_file: bool) -> Self {
676 self.log_to_file = to_file;
677 self
678 }
679
680 pub fn set_log_path(mut self, path: &str) -> Self {
681 self.log_path = PathBuf::from(path);
682 self
683 }
684
685 pub fn set_log_file_size(mut self, size: u64) -> Self {
686 self.log_file_size = size;
687 self
688 }
689
690 pub fn set_log_file_count(mut self, count: usize) -> Self {
691 self.log_file_count = count;
692 self
693 }
694
695 pub fn set_output_to_console(mut self, output_console: bool) -> Self {
696 self.output_console = output_console;
697 self
698 }
699
700 pub fn add_module_log(mut self, module_key: &str, log_name: &str) -> Self {
701 self.module_logs.push((module_key.to_string(), log_name.to_string()));
702 self
703 }
704
705 pub fn add_filter(mut self, filter: &str) -> Self {
706 self.filter.push(filter.to_string());
707 self
708 }
709
710 fn new_log(&self, log_name: &str, filters: Vec<String>) -> Result<Box<dyn log::Log>, FlexiLoggerError> {
711 let mut logger = flexi_logger::Logger::try_with_env_or_str(self.log_level.as_str())?;
712 if self.log_to_file {
713 let mut base_name = self.app_name.clone();
714 if !self.instance_id.is_empty() {
715 base_name = format!("{}_{}", self.app_name, self.instance_id);
716 }
717 if !log_name.is_empty() {
718 base_name = format!("{}_{}", base_name, log_name);
719 }
720 logger = logger.log_to_file(FileSpec::default().directory(self.log_path.as_path()).basename(base_name.as_str()))
721 .rotate(Criterion::Size(self.log_file_size), Naming::Numbers, Cleanup::KeepLogFiles(self.log_file_count), );
725 }
726 if !self.output_console {
727 logger = logger.duplicate_to_stderr(Duplicate::None);
728 } else {
729 logger = logger.duplicate_to_stderr(Duplicate::All);
730 }
731
732 logger = logger.filter(Box::new(SfoLogFilter::new(filters)));
733
734 let (log, _) = logger.format(custom_format).build()?;
735 Ok(log)
736 }
737
738 #[cfg(not(feature = "nolog"))]
739 pub fn start(self) -> Result<(), FlexiLoggerError> {
740 let main_log = self.new_log("", self.filter.clone())?;
741 let mut module_logs = Vec::new();
742 for (match_key, log_name) in self.module_logs.iter() {
743 module_logs.push((match_key.clone(), self.new_log(log_name.as_str(), vec![])?));
744 }
745
746 let sfo_log = SfoLogger {
747 main_logger: main_log,
748 module_loggers: module_logs,
749 };
750
751 log::set_boxed_logger(Box::new(sfo_log))?;
752
753 Ok(())
754 }
755
756 #[cfg(feature = "nolog")]
757 pub fn start(self) -> Result<(), FlexiLoggerError> {
758 Ok(())
759 }
760}
761
762struct SfoLogFilter {
763 filters: HashSet<String>,
764}
765
766impl SfoLogFilter {
767 fn new(filters: Vec<String>) -> Self {
768 Self {
769 filters: filters.into_iter().map(|filter| filter.to_string()).collect(),
770 }
771 }
772}
773
774impl LogLineFilter for SfoLogFilter {
775 fn write(&self, now: &mut DeferredNow, record: &Record, log_line_writer: &dyn LogLineWriter) -> std::io::Result<()> {
776 let module = if let Some((first, _)) = record.metadata().target().split_once("::") {
777 first
778 } else {
779 record.metadata().target()
780 };
781
782 if self.filters.contains(module) {
783 return Ok(());
784 }
785
786 log_line_writer.write(now, record)
787 }
788}
789
790struct SfoLogger {
791 main_logger: Box<dyn log::Log>,
792 module_loggers: Vec<(String, Box<dyn log::Log>)>,
793}
794
795impl log::Log for SfoLogger {
796 fn enabled(&self, metadata: &Metadata) -> bool {
797 self.main_logger.enabled(metadata)
798 }
799
800 fn log(&self, record: &Record) {
801 for (module, log) in self.module_loggers.iter() {
802 if record.metadata().target().starts_with(module) {
803 log.log(record);
804 break;
805 }
806 }
807 self.main_logger.log(record);
808 }
809
810 fn flush(&self) {
811 self.main_logger.flush();
812 for (_, module_logger) in self.module_loggers.iter() {
813 module_logger.flush();
814 }
815 }
816}