1
1
//! Simple logger that logs either to stderr or to a file, using `tracing_subscriber`
2
2
//! filter syntax and `tracing_appender` for non blocking output.
3
3
4
- use std:: io;
4
+ use std:: io:: { self } ;
5
5
6
6
use anyhow:: Context ;
7
7
use tracing:: level_filters:: LevelFilter ;
8
8
use tracing_subscriber:: {
9
- filter:: Targets , fmt:: MakeWriter , layer:: SubscriberExt , util:: SubscriberInitExt , Layer ,
10
- Registry ,
9
+ filter:: { filter_fn, Targets } ,
10
+ fmt:: MakeWriter ,
11
+ layer:: SubscriberExt ,
12
+ Layer , Registry ,
11
13
} ;
12
14
use tracing_tree:: HierarchicalLayer ;
13
15
14
16
use crate :: tracing:: hprof;
17
+ use crate :: tracing:: json;
15
18
16
19
#[ derive( Debug ) ]
17
20
pub struct Config < T > {
@@ -34,14 +37,20 @@ pub struct Config<T> {
34
37
/// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10
35
38
/// ```
36
39
pub profile_filter : Option < String > ,
40
+
41
+ /// Filtering syntax, set in a shell:
42
+ /// ```
43
+ /// env RA_PROFILE_JSON=foo|bar|baz
44
+ /// ```
45
+ pub json_profile_filter : Option < String > ,
37
46
}
38
47
39
48
impl < T > Config < T >
40
49
where
41
50
T : for < ' writer > MakeWriter < ' writer > + Send + Sync + ' static ,
42
51
{
43
52
pub fn init ( self ) -> anyhow:: Result < ( ) > {
44
- let filter : Targets = self
53
+ let targets_filter : Targets = self
45
54
. filter
46
55
. parse ( )
47
56
. with_context ( || format ! ( "invalid log filter: `{}`" , self . filter) ) ?;
@@ -52,30 +61,58 @@ where
52
61
. with_target ( false )
53
62
. with_ansi ( false )
54
63
. with_writer ( writer)
55
- . with_filter ( filter ) ;
56
-
57
- let mut chalk_layer = None ;
58
- if let Some ( chalk_filter) = self . chalk_filter {
59
- let level: LevelFilter =
60
- chalk_filter. parse ( ) . with_context ( || "invalid chalk log filter" ) ?;
61
-
62
- let chalk_filter = Targets :: new ( )
63
- . with_target ( "chalk_solve" , level)
64
- . with_target ( "chalk_ir" , level)
65
- . with_target ( "chalk_recursive" , level) ;
66
- chalk_layer = Some (
64
+ . with_filter ( targets_filter ) ;
65
+
66
+ let chalk_layer = match self . chalk_filter {
67
+ Some ( chalk_filter) => {
68
+ let level: LevelFilter =
69
+ chalk_filter. parse ( ) . with_context ( || "invalid chalk log filter" ) ?;
70
+
71
+ let chalk_filter = Targets :: new ( )
72
+ . with_target ( "chalk_solve" , level)
73
+ . with_target ( "chalk_ir" , level)
74
+ . with_target ( "chalk_recursive" , level) ;
75
+ // TODO: remove `.with_filter(LevelFilter::OFF)` on the `None` branch.
67
76
HierarchicalLayer :: default ( )
68
77
. with_indent_lines ( true )
69
78
. with_ansi ( false )
70
79
. with_indent_amount ( 2 )
71
80
. with_writer ( io:: stderr)
72
- . with_filter ( chalk_filter) ,
73
- ) ;
81
+ . with_filter ( chalk_filter)
82
+ . boxed ( )
83
+ }
84
+ None => None :: < HierarchicalLayer > . with_filter ( LevelFilter :: OFF ) . boxed ( ) ,
85
+ } ;
86
+
87
+ // TODO: remove `.with_filter(LevelFilter::OFF)` on the `None` branch.
88
+ let profiler_layer = match self . profile_filter {
89
+ Some ( spec) => Some ( hprof:: SpanTree :: new ( & spec) ) . with_filter ( LevelFilter :: INFO ) ,
90
+ None => None . with_filter ( LevelFilter :: OFF ) ,
91
+ } ;
92
+
93
+ let json_profiler_layer = match self . json_profile_filter {
94
+ Some ( spec) => {
95
+ let filter = json:: JsonFilter :: from_spec ( & spec) ;
96
+ let filter = filter_fn ( move |metadata| {
97
+ let allowed = match & filter. allowed_names {
98
+ Some ( names) => names. contains ( metadata. name ( ) ) ,
99
+ None => true ,
100
+ } ;
101
+
102
+ allowed && metadata. is_span ( )
103
+ } ) ;
104
+ Some ( json:: TimingLayer :: new ( std:: io:: stderr) . with_filter ( filter) )
105
+ }
106
+ None => None ,
74
107
} ;
75
108
76
- let profiler_layer = self . profile_filter . map ( |spec| hprof:: layer ( & spec) ) ;
109
+ let subscriber = Registry :: default ( )
110
+ . with ( ra_fmt_layer)
111
+ . with ( json_profiler_layer)
112
+ . with ( profiler_layer)
113
+ . with ( chalk_layer) ;
77
114
78
- Registry :: default ( ) . with ( ra_fmt_layer ) . with ( chalk_layer ) . with ( profiler_layer ) . try_init ( ) ?;
115
+ tracing :: subscriber :: set_global_default ( subscriber ) ?;
79
116
80
117
Ok ( ( ) )
81
118
}
0 commit comments