@@ -2,7 +2,7 @@ use regex::Regex;
2
2
use tokio_trace_core:: { subscriber:: Interest , Level , Metadata } ;
3
3
use { filter:: Filter , span:: Context } ;
4
4
5
- use std:: { cmp:: Ordering , env} ;
5
+ use std:: { cmp:: Ordering , env, error :: Error , fmt , str :: FromStr } ;
6
6
7
7
pub const DEFAULT_FILTER_ENV : & str = "RUST_LOG" ;
8
8
@@ -13,6 +13,16 @@ pub struct EnvFilter {
13
13
includes_span_directive : bool ,
14
14
}
15
15
16
+ #[ derive( Debug ) ]
17
+ pub struct FromEnvError {
18
+ kind : ErrorKind ,
19
+ }
20
+
21
+ #[ derive( Debug ) ]
22
+ pub struct ParseError {
23
+ directive : String ,
24
+ }
25
+
16
26
#[ derive( Debug ) ]
17
27
struct Directive {
18
28
target : Option < String > ,
@@ -29,21 +39,56 @@ enum LevelFilter {
29
39
Level ( Level ) ,
30
40
}
31
41
42
+ #[ derive( Debug ) ]
43
+ enum ErrorKind {
44
+ Parse ( ParseError ) ,
45
+ Env ( env:: VarError ) ,
46
+ }
47
+
32
48
// ===== impl EnvFilter =====
33
49
34
50
impl EnvFilter {
51
+ /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
52
+ /// variable, ignoring any invalid filter directives.
35
53
pub fn from_default_env ( ) -> Self {
36
54
Self :: from_env ( DEFAULT_FILTER_ENV )
37
55
}
38
56
57
+ /// Returns a new `EnvFilter` from the value of the given environment
58
+ /// variable, ignoring any invalid filter directives.
39
59
pub fn from_env < A : AsRef < str > > ( env : A ) -> Self {
40
- let directives = env:: var ( env. as_ref ( ) )
41
- . map ( |ref var| parse_directives ( var) )
42
- . unwrap_or_default ( ) ;
43
- Self :: new ( directives)
60
+ env:: var ( env. as_ref ( ) )
61
+ . map ( |ref var| Self :: new ( var) )
62
+ . unwrap_or_default ( )
63
+ }
64
+
65
+ /// Returns a new `EnvFilter` from the directives in the given string,
66
+ /// ignoring any that are invalid.
67
+ pub fn new < S : AsRef < str > > ( dirs : S ) -> Self {
68
+ Self :: new2 ( parse_directives ( dirs. as_ref ( ) ) )
69
+ }
70
+
71
+ /// Returns a new `EnvFilter` from the directives in the given string,
72
+ /// or an error if any are invalid.
73
+ pub fn try_new < S : AsRef < str > > ( dirs : S ) -> Result < Self , ParseError > {
74
+ Ok ( Self :: new2 ( try_parse_directives ( dirs. as_ref ( ) ) ?) )
75
+ }
76
+
77
+ /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
78
+ /// variable, or an error if the environment variable contains any invalid
79
+ /// filter directives.
80
+ pub fn try_from_default_env ( ) -> Result < Self , FromEnvError > {
81
+ Self :: try_from_env ( DEFAULT_FILTER_ENV )
44
82
}
45
83
46
- fn new ( mut directives : Vec < Directive > ) -> Self {
84
+ /// Returns a new `EnvFilter` from the value of the given environment
85
+ /// variable, or an error if the environment variable is unset or contains
86
+ /// any invalid filter directives.
87
+ pub fn try_from_env < A : AsRef < str > > ( env : A ) -> Result < Self , FromEnvError > {
88
+ env:: var ( env. as_ref ( ) ) ?. parse ( ) . map_err ( Into :: into)
89
+ }
90
+
91
+ fn new2 ( mut directives : Vec < Directive > ) -> Self {
47
92
if directives. is_empty ( ) {
48
93
directives. push ( Directive :: default ( ) ) ;
49
94
} else {
@@ -88,12 +133,25 @@ impl EnvFilter {
88
133
}
89
134
}
90
135
91
- impl < A > From < A > for EnvFilter
136
+ impl < S > From < S > for EnvFilter
92
137
where
93
- A : AsRef < str > ,
138
+ S : AsRef < str > ,
94
139
{
95
- fn from ( env : A ) -> Self {
96
- Self :: new ( parse_directives ( env. as_ref ( ) ) )
140
+ fn from ( s : S ) -> Self {
141
+ Self :: new ( s)
142
+ }
143
+ }
144
+
145
+ impl FromStr for EnvFilter {
146
+ type Err = ParseError ;
147
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
148
+ Self :: try_new ( s)
149
+ }
150
+ }
151
+
152
+ impl Default for EnvFilter {
153
+ fn default ( ) -> Self {
154
+ Self :: new2 ( Default :: default ( ) )
97
155
}
98
156
}
99
157
@@ -183,13 +241,19 @@ fn parse_directives(spec: &str) -> Vec<Directive> {
183
241
spec. split ( ',' )
184
242
. filter_map ( |dir| {
185
243
Directive :: parse ( dir) . or_else ( || {
186
- eprintln ! ( "ignoring invalid log directive '{}'" , dir) ;
244
+ eprintln ! ( "ignoring invalid filter directive '{}'" , dir) ;
187
245
None
188
246
} )
189
247
} )
190
248
. collect ( )
191
249
}
192
250
251
+ fn try_parse_directives ( spec : & str ) -> Result < Vec < Directive > , ParseError > {
252
+ spec. split ( ',' )
253
+ . map ( |dir| Directive :: parse ( dir) . ok_or_else ( || ParseError :: new ( dir) ) )
254
+ . collect ( )
255
+ }
256
+
193
257
// ===== impl Directive =====
194
258
195
259
impl Directive {
@@ -314,6 +378,74 @@ impl Default for Directive {
314
378
}
315
379
}
316
380
381
+ // ===== impl FromEnvError =====
382
+
383
+ impl From < ParseError > for FromEnvError {
384
+ fn from ( p : ParseError ) -> Self {
385
+ Self {
386
+ kind : ErrorKind :: Parse ( p) ,
387
+ }
388
+ }
389
+ }
390
+
391
+ impl From < env:: VarError > for FromEnvError {
392
+ fn from ( v : env:: VarError ) -> Self {
393
+ Self {
394
+ kind : ErrorKind :: Env ( v) ,
395
+ }
396
+ }
397
+ }
398
+
399
+ impl fmt:: Display for FromEnvError {
400
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
401
+ match self . kind {
402
+ ErrorKind :: Parse ( ref p) => p. fmt ( f) ,
403
+ ErrorKind :: Env ( ref e) => e. fmt ( f) ,
404
+ }
405
+ }
406
+ }
407
+
408
+ impl Error for FromEnvError {
409
+ fn description ( & self ) -> & str {
410
+ match self . kind {
411
+ ErrorKind :: Parse ( ref p) => p. description ( ) ,
412
+ ErrorKind :: Env ( ref e) => e. description ( ) ,
413
+ }
414
+ }
415
+
416
+ #[ allow( deprecated) ] // for compatibility with minimum Rust version 1.26.0
417
+ fn cause ( & self ) -> Option < & Error > {
418
+ match self . kind {
419
+ ErrorKind :: Parse ( ref p) => Some ( p) ,
420
+ ErrorKind :: Env ( ref e) => Some ( e) ,
421
+ }
422
+ }
423
+ }
424
+
425
+ // ===== impl ParseError =====
426
+
427
+ impl ParseError {
428
+ fn new ( directive : & str ) -> Self {
429
+ ParseError {
430
+ directive : directive. to_string ( ) ,
431
+ }
432
+ }
433
+ }
434
+
435
+ impl fmt:: Display for ParseError {
436
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
437
+ write ! ( f, "invalid filter directive '{}'" , self . directive)
438
+ }
439
+ }
440
+
441
+ impl Error for ParseError {
442
+ fn description ( & self ) -> & str {
443
+ "invalid filter directive"
444
+ }
445
+ }
446
+
447
+ // ===== impl LevelFilter =====
448
+
317
449
impl PartialEq < Level > for LevelFilter {
318
450
fn eq ( & self , other : & Level ) -> bool {
319
451
match self {
0 commit comments