@@ -80,22 +80,22 @@ impl ConsoleWriter {
80
80
self . with_writer ( |w| {
81
81
let mut buffer = BufWriter :: new ( w) ;
82
82
for span in batch {
83
- let _ = Self :: span_to_writer ( span, & mut buffer) ;
83
+ let _ = Self :: span_to_writer ( self , span, & mut buffer) ;
84
84
}
85
85
} ) ;
86
86
}
87
87
88
88
pub fn write_tracing_event ( & self , event : & tracing:: Event < ' _ > ) {
89
89
self . with_writer ( |w| {
90
90
let mut buffer = BufWriter :: new ( w) ;
91
- let _ = Self :: event_to_writer ( event, & mut buffer) ;
91
+ let _ = Self :: event_to_writer ( self , event, & mut buffer) ;
92
92
} ) ;
93
93
}
94
94
95
95
pub fn write_tracing_opentelemetry_data ( & self , data : & OtelData ) {
96
96
self . with_writer ( |w| {
97
97
let mut buffer = BufWriter :: new ( w) ;
98
- let _ = Self :: otel_data_to_writer ( data, & mut buffer) ;
98
+ let _ = Self :: otel_data_to_writer ( self , data, & mut buffer) ;
99
99
} ) ;
100
100
}
101
101
@@ -107,13 +107,12 @@ impl ConsoleWriter {
107
107
}
108
108
}
109
109
110
- fn span_to_writer < W : io:: Write > ( span : & SpanData , w : & mut W ) -> io:: Result < ( ) > {
110
+ fn span_to_writer < W : io:: Write > ( & self , span : & SpanData , w : & mut W ) -> io:: Result < ( ) > {
111
111
// only print for pending span and logs
112
112
if span. get_span_type ( ) . is_none_or ( |ty| ty == "span" ) {
113
113
return Ok ( ( ) ) ;
114
114
}
115
115
116
- let timestamp: DateTime < Utc > = span. start_time . into ( ) ;
117
116
let mut msg = None ;
118
117
let mut level = None ;
119
118
let mut target = None ;
@@ -152,11 +151,15 @@ impl ConsoleWriter {
152
151
msg = Some ( span. name . clone ( ) ) ;
153
152
}
154
153
155
- write ! (
156
- w,
157
- "{}" ,
158
- DIMMED . paint( timestamp. format( "%Y-%m-%dT%H:%M:%S%.6fZ" ) . to_string( ) )
159
- ) ?;
154
+ if self . options . include_timestamps {
155
+ let timestamp: DateTime < Utc > = span. start_time . into ( ) ;
156
+ write ! (
157
+ w,
158
+ "{}" ,
159
+ DIMMED . paint( timestamp. format( "%Y-%m-%dT%H:%M:%S%.6fZ" ) . to_string( ) )
160
+ ) ?;
161
+ }
162
+
160
163
if let Some ( level) = level {
161
164
level_int_to_text ( level, w) ?;
162
165
}
@@ -183,8 +186,11 @@ impl ConsoleWriter {
183
186
writeln ! ( w)
184
187
}
185
188
186
- fn event_to_writer < W : io:: Write > ( event : & tracing:: Event < ' _ > , w : & mut W ) -> io:: Result < ( ) > {
187
- let timestamp: DateTime < Utc > = Utc :: now ( ) ;
189
+ fn event_to_writer < W : io:: Write > (
190
+ & self ,
191
+ event : & tracing:: Event < ' _ > ,
192
+ w : & mut W ,
193
+ ) -> io:: Result < ( ) > {
188
194
let level = level_to_level_number ( * event. metadata ( ) . level ( ) ) ;
189
195
let target = event. metadata ( ) . module_path ( ) ;
190
196
@@ -199,11 +205,14 @@ impl ConsoleWriter {
199
205
. message
200
206
. unwrap_or_else ( || event. metadata ( ) . name ( ) . to_string ( ) ) ;
201
207
202
- write ! (
203
- w,
204
- "{}" ,
205
- DIMMED . paint( timestamp. format( "%Y-%m-%dT%H:%M:%S%.6fZ" ) . to_string( ) )
206
- ) ?;
208
+ if self . options . include_timestamps {
209
+ let timestamp: DateTime < Utc > = Utc :: now ( ) ;
210
+ write ! (
211
+ w,
212
+ "{}" ,
213
+ DIMMED . paint( timestamp. format( "%Y-%m-%dT%H:%M:%S%.6fZ" ) . to_string( ) )
214
+ ) ?;
215
+ }
207
216
208
217
level_int_to_text ( level, w) ?;
209
218
@@ -226,15 +235,10 @@ impl ConsoleWriter {
226
235
}
227
236
228
237
fn otel_data_to_writer < W : io:: Write > (
238
+ & self ,
229
239
data : & tracing_opentelemetry:: OtelData ,
230
240
w : & mut W ,
231
241
) -> io:: Result < ( ) > {
232
- let timestamp: DateTime < Utc > = data
233
- . builder
234
- . start_time
235
- . unwrap_or_else ( SystemTime :: now)
236
- . into ( ) ;
237
-
238
242
let mut msg = None ;
239
243
let mut level = None ;
240
244
let mut target = None ;
@@ -273,11 +277,19 @@ impl ConsoleWriter {
273
277
msg = Some ( data. builder . name . clone ( ) ) ;
274
278
}
275
279
276
- write ! (
277
- w,
278
- "{}" ,
279
- DIMMED . paint( timestamp. format( "%Y-%m-%dT%H:%M:%S%.6fZ" ) . to_string( ) )
280
- ) ?;
280
+ if self . options . include_timestamps {
281
+ let timestamp: DateTime < Utc > = data
282
+ . builder
283
+ . start_time
284
+ . unwrap_or_else ( SystemTime :: now)
285
+ . into ( ) ;
286
+ write ! (
287
+ w,
288
+ "{}" ,
289
+ DIMMED . paint( timestamp. format( "%Y-%m-%dT%H:%M:%S%.6fZ" ) . to_string( ) )
290
+ ) ?;
291
+ }
292
+
281
293
if let Some ( level) = level {
282
294
level_int_to_text ( level, w) ?;
283
295
}
@@ -377,13 +389,60 @@ mod tests {
377
389
let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
378
390
let output = remap_timestamps_in_console_output ( output) ;
379
391
380
- assert_snapshot ! ( output, @r# "
392
+ assert_snapshot ! ( output, @r"
381
393
[2m1970-01-01T00:00:00.000000Z[0m[32m INFO[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mroot span[0m
382
394
[2m1970-01-01T00:00:00.000001Z[0m[32m INFO[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mhello world span[0m
383
395
[2m1970-01-01T00:00:00.000002Z[0m[34m DEBUG[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mdebug span[0m
384
396
[2m1970-01-01T00:00:00.000003Z[0m[34m DEBUG[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mdebug span with explicit parent[0m
385
397
[2m1970-01-01T00:00:00.000004Z[0m[32m INFO[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mhello world log[0m
386
- [2m1970-01-01T00:00:00.000005Z[0m[31m ERROR[0m [2;3mlogfire[0m [1mpanic: oh no![0m [3mlocation[0m=src/internal/exporters/console.rs:369:17, [3mbacktrace[0m=disabled backtrace
387
- "# ) ;
398
+ [2m1970-01-01T00:00:00.000005Z[0m[31m ERROR[0m [2;3mlogfire[0m [1mpanic: oh no![0m [3mlocation[0m=src/internal/exporters/console.rs:381:17, [3mbacktrace[0m=disabled backtrace
399
+ " ) ;
400
+ }
401
+
402
+ #[ test]
403
+ fn test_print_to_console_include_timestamps_false ( ) {
404
+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
405
+
406
+ let console_options = ConsoleOptions :: default ( )
407
+ . with_target ( Target :: Pipe ( output. clone ( ) ) )
408
+ . with_include_timestamps ( false ) ;
409
+
410
+ let handler = crate :: configure ( )
411
+ . local ( )
412
+ . send_to_logfire ( false )
413
+ . with_console ( Some ( console_options) )
414
+ . install_panic_handler ( )
415
+ . with_default_level_filter ( LevelFilter :: TRACE )
416
+ . finish ( )
417
+ . unwrap ( ) ;
418
+
419
+ let guard = set_local_logfire ( handler) ;
420
+
421
+ std:: panic:: catch_unwind ( std:: panic:: AssertUnwindSafe ( || {
422
+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
423
+ let root = crate :: span!( "root span" ) . entered ( ) ;
424
+ let _ = crate :: span!( "hello world span" ) . entered ( ) ;
425
+ let _ = crate :: span!( level: Level :: DEBUG , "debug span" ) ;
426
+ let _ = crate :: span!( parent: & root, level: Level :: DEBUG , "debug span with explicit parent" ) ;
427
+ crate :: info!( "hello world log" ) ;
428
+ panic ! ( "oh no!" ) ;
429
+ } ) ;
430
+ } ) )
431
+ . unwrap_err ( ) ;
432
+
433
+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
434
+
435
+ let output = output. lock ( ) . unwrap ( ) ;
436
+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
437
+ let output = remap_timestamps_in_console_output ( output) ;
438
+
439
+ assert_snapshot ! ( output, @r"
440
+ [32m INFO[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mroot span[0m
441
+ [32m INFO[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mhello world span[0m
442
+ [34m DEBUG[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mdebug span[0m
443
+ [34m DEBUG[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mdebug span with explicit parent[0m
444
+ [32m INFO[0m [2;3mlogfire::internal::exporters::console::tests[0m [1mhello world log[0m
445
+ [31m ERROR[0m [2;3mlogfire[0m [1mpanic: oh no![0m [3mlocation[0m=src/internal/exporters/console.rs:428:17, [3mbacktrace[0m=disabled backtrace
446
+ " ) ;
388
447
}
389
448
}
0 commit comments