11//! Simple logger that logs either to stderr or to a file, using `tracing_subscriber`
22//! filter syntax and `tracing_appender` for non blocking output.
33
4- use std:: io;
4+ use std:: io:: { self } ;
55
66use anyhow:: Context ;
77use tracing:: level_filters:: LevelFilter ;
88use 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 ,
1113} ;
1214use tracing_tree:: HierarchicalLayer ;
1315
1416use crate :: tracing:: hprof;
17+ use crate :: tracing:: json;
1518
1619#[ derive( Debug ) ]
1720pub struct Config < T > {
@@ -34,14 +37,20 @@ pub struct Config<T> {
3437 /// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10
3538 /// ```
3639 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 > ,
3746}
3847
3948impl < T > Config < T >
4049where
4150 T : for < ' writer > MakeWriter < ' writer > + Send + Sync + ' static ,
4251{
4352 pub fn init ( self ) -> anyhow:: Result < ( ) > {
44- let filter : Targets = self
53+ let targets_filter : Targets = self
4554 . filter
4655 . parse ( )
4756 . with_context ( || format ! ( "invalid log filter: `{}`" , self . filter) ) ?;
@@ -52,30 +61,58 @@ where
5261 . with_target ( false )
5362 . with_ansi ( false )
5463 . 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.
6776 HierarchicalLayer :: default ( )
6877 . with_indent_lines ( true )
6978 . with_ansi ( false )
7079 . with_indent_amount ( 2 )
7180 . 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 ,
74107 } ;
75108
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) ;
77114
78- Registry :: default ( ) . with ( ra_fmt_layer ) . with ( chalk_layer ) . with ( profiler_layer ) . try_init ( ) ?;
115+ tracing :: subscriber :: set_global_default ( subscriber ) ?;
79116
80117 Ok ( ( ) )
81118 }
0 commit comments