sfo_log/
lib.rs

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 / target / parent.
16    (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 / target.
28    (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 / parent.
40    (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 / parent.
52    (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.
64    (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.
76    (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.
88    (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    // ...
106    ({ $($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 / target / parent.
134    (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 / target.
146    (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 / parent.
158    (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 / parent.
170    (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.
182    (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.
194    (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.
206    (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    // ...
224    ({ $($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 / target / parent.
252    (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 / target.
264    (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 / parent.
276    (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 / parent.
288    (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.
300    (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.
312    (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.
324    (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    // ...
342    ({ $($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 / target / parent.
370    (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 / target.
382    (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 / parent.
394    (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 / parent.
406    (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.
418    (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.
430    (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.
442    (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    // ...
460    ({ $($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 / target / parent.
489    (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 / target.
501    (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 / parent.
513    (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 / parent.
525    (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.
537    (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.
549    (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.
561    (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    // ...
579    ({ $($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            path.to_string()
613        }
614    };
615    write!(
616        writer,
617        "{} [{}] [{}:{}:{}] [{}] - {}",
618        now.format("%Y-%m-%d %H:%M:%S"),
619        record.level(),
620        record.metadata().target(),
621        file,
622        record.line().unwrap_or(0),
623        thread::current().name().unwrap_or(format!("{:?}", thread::current().id()).as_str()),
624        &record.args()
625    )
626}
627pub struct Logger {
628    app_name: String,
629    log_level: String,
630    log_to_file: bool,
631    log_path: PathBuf,
632    log_file_size: u64,
633    log_file_count: usize,
634    instance_id: String,
635    output_console: bool,
636    filter: Vec<String>,
637    module_logs: Vec<(String, String)>,
638}
639
640impl Logger {
641    pub fn new(app_name: &str) -> Self {
642        Self {
643            app_name: app_name.to_string(),
644            log_level: "info".to_string(),
645            log_to_file: false,
646            log_path: std::env::current_dir().unwrap().join("logs"),
647            log_file_size: 10 * 1024 * 1024,
648            log_file_count: 10,
649            instance_id: "".to_string(),
650            output_console: true,
651            filter: vec![],
652            module_logs: vec![],
653        }
654    }
655
656    pub fn set_instance_id(mut self, instance_id: &str) -> Self {
657        self.instance_id = instance_id.to_string();
658        self
659    }
660
661    pub fn set_process_id_to_instance_id(mut self) -> Self {
662        self.instance_id = format!("{}", std::process::id());
663        self
664    }
665
666    pub fn set_log_level(mut self, level: &str) -> Self {
667        self.log_level = level.to_string();
668        self
669    }
670
671    pub fn set_log_to_file(mut self, to_file: bool) -> Self {
672        self.log_to_file = to_file;
673        self
674    }
675
676    pub fn set_log_path(mut self, path: &str) -> Self {
677        self.log_path = PathBuf::from(path);
678        self
679    }
680
681    pub fn set_log_file_size(mut self, size: u64) -> Self {
682        self.log_file_size = size;
683        self
684    }
685
686    pub fn set_log_file_count(mut self, count: usize) -> Self {
687        self.log_file_count = count;
688        self
689    }
690
691    pub fn set_output_to_console(mut self, output_console: bool) -> Self {
692        self.output_console = output_console;
693        self
694    }
695
696    pub fn add_module_log(mut self, module_key: &str, log_name: &str) -> Self {
697        self.module_logs.push((module_key.to_string(), log_name.to_string()));
698        self
699    }
700
701    pub fn add_filter(mut self, filter: &str) -> Self {
702        self.filter.push(filter.to_string());
703        self
704    }
705
706    fn new_log(&self, log_name: &str, filters: Vec<String>) -> Result<Box<dyn log::Log>, FlexiLoggerError> {
707        let mut logger = flexi_logger::Logger::try_with_env_or_str(self.log_level.as_str())?;
708        if self.log_to_file {
709            let mut base_name = self.app_name.clone();
710            if !self.instance_id.is_empty() {
711                base_name = format!("{}_{}", self.app_name, self.instance_id);
712            }
713            if !log_name.is_empty() {
714                base_name = format!("{}_{}", base_name, log_name);
715            }
716            logger = logger.log_to_file(FileSpec::default().directory(self.log_path.as_path()).basename(base_name.as_str()))
717                .rotate(Criterion::Size(self.log_file_size), // 文件大小达到 10MB 时轮转
718                        Naming::Numbers, // 使用数字命名轮转文件
719                        Cleanup::KeepLogFiles(self.log_file_count), // 保留最近 7 个日志文件
720                );
721        }
722        if !self.output_console {
723            logger = logger.duplicate_to_stderr(Duplicate::None);
724        } else {
725            logger = logger.duplicate_to_stderr(Duplicate::All);
726        }
727
728        logger = logger.filter(Box::new(SfoLogFilter::new(filters)));
729
730        let (log, _) = logger.format(custom_format).build()?;
731        Ok(log)
732    }
733
734    #[cfg(not(feature = "nolog"))]
735    pub fn start(self) -> Result<(), FlexiLoggerError> {
736        let main_log = self.new_log("", self.filter.clone())?;
737        let mut module_logs = Vec::new();
738        for (match_key, log_name) in self.module_logs.iter() {
739            module_logs.push((match_key.clone(), self.new_log(log_name.as_str(), vec![])?));
740        }
741        
742        let sfo_log = SfoLogger {
743            main_logger: main_log,
744            module_loggers: module_logs,
745        };
746        
747        log::set_boxed_logger(Box::new(sfo_log))?;
748        
749        Ok(())
750    }
751
752    #[cfg(feature = "nolog")]
753    pub fn start(self) -> Result<(), FlexiLoggerError> {
754        Ok(())
755    }
756}
757
758struct SfoLogFilter {
759    filters: HashSet<String>,
760}
761
762impl SfoLogFilter {
763    fn new(filters: Vec<String>) -> Self {
764        Self {
765            filters: filters.into_iter().map(|filter| filter.to_string()).collect(),
766        }
767    }
768}
769
770impl LogLineFilter for SfoLogFilter {
771    fn write(&self, now: &mut DeferredNow, record: &Record, log_line_writer: &dyn LogLineWriter) -> std::io::Result<()> {
772        if self.filters.contains(record.target()) {
773            return Ok(());
774        }
775
776        log_line_writer.write(now, record)
777    }
778}
779
780struct SfoLogger {
781    main_logger: Box<dyn log::Log>,
782    module_loggers: Vec<(String, Box<dyn log::Log>)>,
783}
784
785impl log::Log for SfoLogger {
786    fn enabled(&self, metadata: &Metadata) -> bool {
787        self.main_logger.enabled(metadata)
788    }
789
790    fn log(&self, record: &Record) {
791        for (module, log) in self.module_loggers.iter() {
792            if record.metadata().target().starts_with(module) {
793                log.log(record);
794                break;
795            }
796        }
797        self.main_logger.log(record);
798    }
799
800    fn flush(&self) {
801        self.main_logger.flush();
802        for (_, module_logger) in self.module_loggers.iter() {
803            module_logger.flush();
804        }
805    }
806}