@@ -14,164 +14,181 @@ use tracing_subscriber::{
14
14
time:: FormatTime ,
15
15
FormatEvent , FormatFields , FormattedFields ,
16
16
} ,
17
- layer:: SubscriberExt as _,
17
+ layer:: { Layered , SubscriberExt as _} ,
18
18
registry:: LookupSpan ,
19
+ reload:: { self , Handle } ,
19
20
util:: SubscriberInitExt as _,
20
- Layer ,
21
+ EnvFilter , Layer , Registry ,
21
22
} ;
22
23
23
24
use crate :: { error:: ClientError , tracing:: LogLevel } ;
24
25
25
- fn text_layers < S > ( config : TracingConfiguration ) -> impl Layer < S >
26
- where
27
- S : Subscriber + for < ' a > LookupSpan < ' a > ,
28
- {
29
- // Adjusted version of tracing_subscriber::fmt::Format
30
- struct EventFormatter {
31
- display_timestamp : bool ,
32
- display_level : bool ,
33
- }
26
+ // Adjusted version of tracing_subscriber::fmt::Format
27
+ struct EventFormatter {
28
+ display_timestamp : bool ,
29
+ display_level : bool ,
30
+ }
34
31
35
- impl EventFormatter {
36
- fn new ( ) -> Self {
37
- Self { display_timestamp : true , display_level : true }
38
- }
32
+ impl EventFormatter {
33
+ fn new ( ) -> Self {
34
+ Self { display_timestamp : true , display_level : true }
35
+ }
39
36
40
- #[ cfg( target_os = "android" ) ]
41
- fn for_logcat ( ) -> Self {
42
- // Level and time are already captured by logcat separately
43
- Self { display_timestamp : false , display_level : false }
44
- }
37
+ #[ cfg( target_os = "android" ) ]
38
+ fn for_logcat ( ) -> Self {
39
+ // Level and time are already captured by logcat separately
40
+ Self { display_timestamp : false , display_level : false }
41
+ }
45
42
46
- fn format_timestamp ( & self , writer : & mut fmt:: format:: Writer < ' _ > ) -> std:: fmt:: Result {
47
- if fmt:: time:: SystemTime . format_time ( writer) . is_err ( ) {
48
- writer. write_str ( "<unknown time>" ) ?;
49
- }
50
- Ok ( ( ) )
43
+ fn format_timestamp ( & self , writer : & mut fmt:: format:: Writer < ' _ > ) -> std:: fmt:: Result {
44
+ if fmt:: time:: SystemTime . format_time ( writer) . is_err ( ) {
45
+ writer. write_str ( "<unknown time>" ) ?;
51
46
}
47
+ Ok ( ( ) )
48
+ }
52
49
53
- fn write_filename (
54
- & self ,
55
- writer : & mut fmt:: format:: Writer < ' _ > ,
56
- filename : & str ,
57
- ) -> std:: fmt:: Result {
58
- const CRATES_IO_PATH_MATCHER : & str = ".cargo/registry/src/index.crates.io" ;
59
- let crates_io_filename = filename
60
- . split_once ( CRATES_IO_PATH_MATCHER )
61
- . and_then ( |( _, rest) | rest. split_once ( '/' ) . map ( |( _, rest) | rest) ) ;
62
-
63
- if let Some ( filename) = crates_io_filename {
64
- writer. write_str ( "<crates.io>/" ) ?;
65
- writer. write_str ( filename)
66
- } else {
67
- writer. write_str ( filename)
68
- }
50
+ fn write_filename (
51
+ & self ,
52
+ writer : & mut fmt:: format:: Writer < ' _ > ,
53
+ filename : & str ,
54
+ ) -> std:: fmt:: Result {
55
+ const CRATES_IO_PATH_MATCHER : & str = ".cargo/registry/src/index.crates.io" ;
56
+ let crates_io_filename = filename
57
+ . split_once ( CRATES_IO_PATH_MATCHER )
58
+ . and_then ( |( _, rest) | rest. split_once ( '/' ) . map ( |( _, rest) | rest) ) ;
59
+
60
+ if let Some ( filename) = crates_io_filename {
61
+ writer. write_str ( "<crates.io>/" ) ?;
62
+ writer. write_str ( filename)
63
+ } else {
64
+ writer. write_str ( filename)
69
65
}
70
66
}
67
+ }
71
68
72
- impl < S , N > FormatEvent < S , N > for EventFormatter
73
- where
74
- S : Subscriber + for < ' a > LookupSpan < ' a > ,
75
- N : for < ' a > FormatFields < ' a > + ' static ,
76
- {
77
- fn format_event (
78
- & self ,
79
- ctx : & fmt:: FmtContext < ' _ , S , N > ,
80
- mut writer : fmt:: format:: Writer < ' _ > ,
81
- event : & tracing_core:: Event < ' _ > ,
82
- ) -> std:: fmt:: Result {
83
- let meta = event. metadata ( ) ;
84
-
85
- if self . display_timestamp {
86
- self . format_timestamp ( & mut writer) ?;
87
- writer. write_char ( ' ' ) ?;
88
- }
69
+ impl < S , N > FormatEvent < S , N > for EventFormatter
70
+ where
71
+ S : Subscriber + for < ' a > LookupSpan < ' a > ,
72
+ N : for < ' a > FormatFields < ' a > + ' static ,
73
+ {
74
+ fn format_event (
75
+ & self ,
76
+ ctx : & fmt:: FmtContext < ' _ , S , N > ,
77
+ mut writer : fmt:: format:: Writer < ' _ > ,
78
+ event : & tracing_core:: Event < ' _ > ,
79
+ ) -> std:: fmt:: Result {
80
+ let meta = event. metadata ( ) ;
81
+
82
+ if self . display_timestamp {
83
+ self . format_timestamp ( & mut writer) ?;
84
+ writer. write_char ( ' ' ) ?;
85
+ }
89
86
90
- if self . display_level {
91
- // For info and warn, add a padding space to the left
92
- write ! ( writer, "{:>5} " , meta. level( ) ) ?;
93
- }
87
+ if self . display_level {
88
+ // For info and warn, add a padding space to the left
89
+ write ! ( writer, "{:>5} " , meta. level( ) ) ?;
90
+ }
94
91
95
- write ! ( writer, "{}: " , meta. target( ) ) ?;
92
+ write ! ( writer, "{}: " , meta. target( ) ) ?;
96
93
97
- ctx. format_fields ( writer. by_ref ( ) , event) ?;
94
+ ctx. format_fields ( writer. by_ref ( ) , event) ?;
98
95
99
- if let Some ( filename) = meta. file ( ) {
100
- writer. write_str ( " | " ) ?;
101
- self . write_filename ( & mut writer, filename) ?;
102
- if let Some ( line_number) = meta. line ( ) {
103
- write ! ( writer, ":{line_number}" ) ?;
104
- }
96
+ if let Some ( filename) = meta. file ( ) {
97
+ writer. write_str ( " | " ) ?;
98
+ self . write_filename ( & mut writer, filename) ?;
99
+ if let Some ( line_number) = meta. line ( ) {
100
+ write ! ( writer, ":{line_number}" ) ?;
105
101
}
102
+ }
106
103
107
- if let Some ( scope) = ctx. event_scope ( ) {
108
- writer. write_str ( " | spans: " ) ?;
104
+ if let Some ( scope) = ctx. event_scope ( ) {
105
+ writer. write_str ( " | spans: " ) ?;
109
106
110
- let mut first = true ;
107
+ let mut first = true ;
111
108
112
- for span in scope. from_root ( ) {
113
- if !first {
114
- writer. write_str ( " > " ) ?;
115
- }
109
+ for span in scope. from_root ( ) {
110
+ if !first {
111
+ writer. write_str ( " > " ) ?;
112
+ }
116
113
117
- first = false ;
114
+ first = false ;
118
115
119
- write ! ( writer, "{}" , span. name( ) ) ?;
116
+ write ! ( writer, "{}" , span. name( ) ) ?;
120
117
121
- if let Some ( fields) = & span. extensions ( ) . get :: < FormattedFields < N > > ( ) {
122
- if !fields. is_empty ( ) {
123
- write ! ( writer, "{{{fields}}}" ) ?;
124
- }
118
+ if let Some ( fields) = & span. extensions ( ) . get :: < FormattedFields < N > > ( ) {
119
+ if !fields. is_empty ( ) {
120
+ write ! ( writer, "{{{fields}}}" ) ?;
125
121
}
126
122
}
127
123
}
128
-
129
- writeln ! ( writer)
130
124
}
131
- }
132
125
133
- let file_layer = config. write_to_files . map ( |c| {
134
- let mut builder = RollingFileAppender :: builder ( )
135
- . rotation ( Rotation :: HOURLY )
136
- . filename_prefix ( & c. file_prefix ) ;
126
+ writeln ! ( writer)
127
+ }
128
+ }
137
129
138
- if let Some ( max_files) = c. max_files {
139
- builder = builder. max_log_files ( max_files as usize )
140
- }
141
- if let Some ( file_suffix) = c. file_suffix {
142
- builder = builder. filename_suffix ( file_suffix)
143
- }
130
+ // Another fields formatter is necessary because of this bug
131
+ // https://github.com/tokio-rs/tracing/issues/1372. Using a new
132
+ // formatter for the fields forces to record them in different span
133
+ // extensions, and thus remove the duplicated fields in the span.
134
+ #[ derive( Default ) ]
135
+ struct FieldsFormatterForFiles ( DefaultFields ) ;
136
+
137
+ impl < ' writer > FormatFields < ' writer > for FieldsFormatterForFiles {
138
+ fn format_fields < R : RecordFields > (
139
+ & self ,
140
+ writer : Writer < ' writer > ,
141
+ fields : R ,
142
+ ) -> std:: fmt:: Result {
143
+ self . 0 . format_fields ( writer, fields)
144
+ }
145
+ }
144
146
145
- let writer = builder. build ( & c. path ) . expect ( "Failed to create a rolling file appender." ) ;
146
-
147
- // Another fields formatter is necessary because of this bug
148
- // https://github.com/tokio-rs/tracing/issues/1372. Using a new
149
- // formatter for the fields forces to record them in different span
150
- // extensions, and thus remove the duplicated fields in the span.
151
- #[ derive( Default ) ]
152
- struct FieldsFormatterForFiles ( DefaultFields ) ;
153
-
154
- impl < ' writer > FormatFields < ' writer > for FieldsFormatterForFiles {
155
- fn format_fields < R : RecordFields > (
156
- & self ,
157
- writer : Writer < ' writer > ,
158
- fields : R ,
159
- ) -> std:: fmt:: Result {
160
- self . 0 . format_fields ( writer, fields)
147
+ type ReloadHandle = Handle <
148
+ tracing_subscriber:: fmt:: Layer <
149
+ Layered < EnvFilter , Registry > ,
150
+ FieldsFormatterForFiles ,
151
+ EventFormatter ,
152
+ RollingFileAppender ,
153
+ > ,
154
+ Layered < EnvFilter , Registry > ,
155
+ > ;
156
+
157
+ fn text_layers (
158
+ config : TracingConfiguration ,
159
+ ) -> ( impl Layer < Layered < EnvFilter , Registry > > , Option < ReloadHandle > ) {
160
+ let ( file_layer, reload_handle) = config
161
+ . write_to_files
162
+ . map ( |c| {
163
+ let mut builder = RollingFileAppender :: builder ( )
164
+ . rotation ( Rotation :: HOURLY )
165
+ . filename_prefix ( & c. file_prefix ) ;
166
+
167
+ if let Some ( max_files) = c. max_files {
168
+ builder = builder. max_log_files ( max_files as usize )
169
+ } ;
170
+ if let Some ( file_suffix) = c. file_suffix {
171
+ builder = builder. filename_suffix ( file_suffix)
161
172
}
162
- }
163
173
164
- fmt:: layer ( )
165
- . fmt_fields ( FieldsFormatterForFiles :: default ( ) )
166
- . event_format ( EventFormatter :: new ( ) )
167
- // EventFormatter doesn't support ANSI colors anyways, but the
168
- // default field formatter does, which is unhelpful for iOS +
169
- // Android logs, but enabled by default.
170
- . with_ansi ( false )
171
- . with_writer ( writer)
172
- } ) ;
174
+ let writer = builder. build ( & c. path ) . expect ( "Failed to create a rolling file appender." ) ;
173
175
174
- Layer :: and_then (
176
+ let layer = fmt:: layer ( )
177
+ . fmt_fields ( FieldsFormatterForFiles :: default ( ) )
178
+ . event_format ( EventFormatter :: new ( ) )
179
+ // EventFormatter doesn't support ANSI colors anyways, but the
180
+ // default field formatter does, which is unhelpful for iOS +
181
+ // Android logs, but enabled by default.
182
+ . with_ansi ( false )
183
+ . with_writer ( writer) ;
184
+
185
+ let ( layer, reload_handle) = reload:: Layer :: new ( layer) ;
186
+
187
+ ( layer, reload_handle)
188
+ } )
189
+ . unzip ( ) ;
190
+
191
+ let layers = Layer :: and_then (
175
192
file_layer,
176
193
config. write_to_stdout_or_system . then ( || {
177
194
// Another fields formatter is necessary because of this bug
@@ -209,7 +226,9 @@ where
209
226
"org.matrix.rust.sdk" . to_owned ( ) ,
210
227
) ) ;
211
228
} ) ,
212
- )
229
+ ) ;
230
+
231
+ ( layers, reload_handle)
213
232
}
214
233
215
234
/// Configuration to save logs to (rotated) log-files.
@@ -359,6 +378,7 @@ struct SentryLoggingCtx {
359
378
}
360
379
361
380
struct LoggingCtx {
381
+ reload_handle : Option < ReloadHandle > ,
362
382
#[ cfg( feature = "sentry" ) ]
363
383
sentry : Option < SentryLoggingCtx > ,
364
384
}
@@ -463,20 +483,23 @@ impl TracingConfiguration {
463
483
} else {
464
484
( None , None )
465
485
} ;
486
+ let ( text_layers, reload_handle) = crate :: platform:: text_layers ( self ) ;
487
+
466
488
tracing_subscriber:: registry ( )
467
489
. with ( tracing_subscriber:: EnvFilter :: new ( & env_filter) )
468
- . with ( crate :: platform :: text_layers ( self ) )
490
+ . with ( text_layers)
469
491
. with ( sentry_layer)
470
492
. init ( ) ;
471
- logging_ctx = LoggingCtx { sentry : sentry_logging_ctx } ;
493
+ logging_ctx = LoggingCtx { reload_handle , sentry : sentry_logging_ctx } ;
472
494
}
473
495
#[ cfg( not( feature = "sentry" ) ) ]
474
496
{
497
+ let ( text_layers, reload_handle) = crate :: platform:: text_layers ( self ) ;
475
498
tracing_subscriber:: registry ( )
476
499
. with ( tracing_subscriber:: EnvFilter :: new ( & env_filter) )
477
- . with ( crate :: platform :: text_layers ( self ) )
500
+ . with ( text_layers)
478
501
. init ( ) ;
479
- logging_ctx = LoggingCtx { } ;
502
+ logging_ctx = LoggingCtx { reload_handle } ;
480
503
}
481
504
482
505
// Log the log levels 🧠.
0 commit comments