1
1
use std:: borrow:: Cow ;
2
2
use std:: env;
3
+ use std:: fmt:: { self , Display } ;
3
4
use std:: path:: PathBuf ;
5
+ use std:: str:: FromStr ;
4
6
7
+ use relay_common:: impl_str_serde;
5
8
use sentry:: types:: Dsn ;
6
9
use serde:: { Deserialize , Serialize } ;
7
- use tracing:: { level_filters:: LevelFilter , Level } ;
10
+ use tracing:: level_filters:: LevelFilter ;
8
11
use tracing_subscriber:: { prelude:: * , EnvFilter , Layer } ;
9
12
10
13
#[ cfg( feature = "dashboard" ) ]
@@ -47,53 +50,78 @@ pub enum LogFormat {
47
50
Json ,
48
51
}
49
52
50
- mod level_serde {
51
- use std:: fmt;
52
-
53
- use serde:: de:: { Error , Unexpected , Visitor } ;
54
- use serde:: { Deserializer , Serializer } ;
55
- use tracing:: Level ;
56
-
57
- pub fn serialize < S > ( filter : & Level , serializer : S ) -> Result < S :: Ok , S :: Error >
58
- where
59
- S : Serializer ,
60
- {
61
- serializer. collect_str ( filter)
53
+ /// The logging level parse error.
54
+ #[ derive( Clone , Debug ) ]
55
+ pub struct LevelParseError ( String ) ;
56
+
57
+ impl Display for LevelParseError {
58
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
59
+ write ! (
60
+ f,
61
+ r#"error parsing "{}" as level: expected one of "error", "warn", "info", "debug", "trace", "off""# ,
62
+ self . 0
63
+ )
62
64
}
65
+ }
63
66
64
- pub fn deserialize < ' de , D > ( deserializer : D ) -> Result < Level , D :: Error >
65
- where
66
- D : Deserializer < ' de > ,
67
- {
68
- struct V ;
69
-
70
- impl < ' de > Visitor < ' de > for V {
71
- type Value = Level ;
72
-
73
- fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
74
- formatter. write_str ( "a log level" )
75
- }
67
+ #[ derive( Clone , Copy , Debug ) ]
68
+ pub enum Level {
69
+ Error ,
70
+ Warn ,
71
+ Info ,
72
+ Debug ,
73
+ Trace ,
74
+ Off ,
75
+ }
76
76
77
- fn visit_str < E > ( self , value : & str ) -> Result < Level , E >
78
- where
79
- E : Error ,
80
- {
81
- value
82
- . parse ( )
83
- . map_err ( |_| Error :: invalid_value ( Unexpected :: Str ( value) , & self ) )
84
- }
77
+ impl_str_serde ! ( Level , "The logging level." ) ;
78
+
79
+ impl Level {
80
+ /// Returns the tracing [`LevelFilter`].
81
+ pub const fn level_filter ( & self ) -> LevelFilter {
82
+ match self {
83
+ Level :: Error => LevelFilter :: ERROR ,
84
+ Level :: Warn => LevelFilter :: WARN ,
85
+ Level :: Info => LevelFilter :: INFO ,
86
+ Level :: Debug => LevelFilter :: DEBUG ,
87
+ Level :: Trace => LevelFilter :: TRACE ,
88
+ Level :: Off => LevelFilter :: OFF ,
85
89
}
90
+ }
91
+ }
92
+
93
+ impl Display for Level {
94
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
95
+ write ! ( f, "{}" , format!( "{:?}" , self ) . to_lowercase( ) )
96
+ }
97
+ }
86
98
87
- deserializer. deserialize_str ( V )
99
+ impl FromStr for Level {
100
+ type Err = LevelParseError ;
101
+
102
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
103
+ let result = match s {
104
+ "" => Level :: Error ,
105
+ s if s. eq_ignore_ascii_case ( "error" ) => Level :: Error ,
106
+ s if s. eq_ignore_ascii_case ( "warn" ) => Level :: Warn ,
107
+ s if s. eq_ignore_ascii_case ( "info" ) => Level :: Info ,
108
+ s if s. eq_ignore_ascii_case ( "debug" ) => Level :: Debug ,
109
+ s if s. eq_ignore_ascii_case ( "trace" ) => Level :: Trace ,
110
+ s if s. eq_ignore_ascii_case ( "off" ) => Level :: Off ,
111
+ s => return Err ( LevelParseError ( s. into ( ) ) ) ,
112
+ } ;
113
+
114
+ Ok ( result)
88
115
}
89
116
}
90
117
118
+ impl std:: error:: Error for LevelParseError { }
119
+
91
120
/// Controls the logging system.
92
121
#[ derive( Clone , Debug , Deserialize , Serialize ) ]
93
122
#[ serde( default ) ]
94
123
pub struct LogConfig {
95
124
/// The log level for Relay.
96
- #[ serde( with = "level_serde" ) ]
97
125
pub level : Level ,
98
126
99
127
/// Controls the log output format.
@@ -112,10 +140,17 @@ pub struct LogConfig {
112
140
pub traces_sample_rate : f32 ,
113
141
}
114
142
143
+ impl LogConfig {
144
+ /// Returns the tracing [`LevelFilter`].
145
+ pub const fn level_filter ( & self ) -> LevelFilter {
146
+ self . level . level_filter ( )
147
+ }
148
+ }
149
+
115
150
impl Default for LogConfig {
116
151
fn default ( ) -> Self {
117
152
Self {
118
- level : Level :: INFO ,
153
+ level : Level :: Info ,
119
154
format : LogFormat :: Auto ,
120
155
enable_backtraces : false ,
121
156
#[ cfg( debug_assertions) ]
@@ -240,7 +275,7 @@ pub fn init(config: &LogConfig, sentry: &SentryConfig) {
240
275
} ;
241
276
242
277
let logs_subscriber = tracing_subscriber:: registry ( )
243
- . with ( format. with_filter ( LevelFilter :: from ( config. level ) ) )
278
+ . with ( format. with_filter ( config. level_filter ( ) ) )
244
279
. with ( sentry:: integrations:: tracing:: layer ( ) )
245
280
. with ( match env:: var ( EnvFilter :: DEFAULT_ENV ) {
246
281
Ok ( value) => EnvFilter :: new ( value) ,
0 commit comments