Skip to content

Commit 05bbbd0

Browse files
committed
Add include_timestamps config
1 parent ac5c165 commit 05bbbd0

File tree

2 files changed

+110
-34
lines changed

2 files changed

+110
-34
lines changed

src/config.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ impl From<bool> for SendToLogfire {
6969
pub struct ConsoleOptions {
7070
/// Where to send output
7171
pub(crate) target: Target,
72+
/// Whether to include timestamps in the console output.
73+
pub include_timestamps: bool,
7274
// TODO: support the below configuration options (inherited from Python SDK)
7375

7476
// /// Whether to show colors in the console.
7577
// colors: ConsoleColors,
7678
// /// How spans are shown in the console.
7779
// span_style: SpanStyle,
78-
// /// Whether to include timestamps in the console output.
79-
// include_timestamps: bool,
8080
// /// Whether to include tags in the console output.
8181
// include_tags: bool,
8282
// /// Whether to show verbose output.
@@ -95,12 +95,12 @@ impl Default for ConsoleOptions {
9595
ConsoleOptions {
9696
// colors: ConsoleColors::default(),
9797
// span_style: SpanStyle::default(),
98-
// include_timestamps: true,
9998
// include_tags: true,
10099
// verbose: false,
101100
// min_log_level: Level::INFO,
102101
// show_project_link: true,
103102
target: Target::default(),
103+
include_timestamps: true,
104104
}
105105
}
106106
}
@@ -114,6 +114,15 @@ impl ConsoleOptions {
114114
}
115115
}
116116

117+
impl ConsoleOptions {
118+
/// Set whether to include timestamps in the console output.
119+
#[must_use]
120+
pub fn with_include_timestamps(mut self, include: bool) -> Self {
121+
self.include_timestamps = include;
122+
self
123+
}
124+
}
125+
117126
/// Whether to show colors in the console.
118127
#[derive(Default, Debug, Clone, Copy)]
119128
pub enum ConsoleColors {
@@ -367,4 +376,12 @@ mod tests {
367376
assert_eq!(SendToLogfire::from(true), SendToLogfire::Yes);
368377
assert_eq!(SendToLogfire::from(false), SendToLogfire::No);
369378
}
379+
380+
#[test]
381+
fn test_console_options_with_timestamps() {
382+
let options = super::ConsoleOptions::default().with_include_timestamps(false);
383+
assert!(!options.include_timestamps);
384+
let options = super::ConsoleOptions::default().with_include_timestamps(true);
385+
assert!(options.include_timestamps);
386+
}
370387
}

src/internal/exporters/console.rs

+90-31
Original file line numberDiff line numberDiff line change
@@ -80,22 +80,22 @@ impl ConsoleWriter {
8080
self.with_writer(|w| {
8181
let mut buffer = BufWriter::new(w);
8282
for span in batch {
83-
let _ = Self::span_to_writer(span, &mut buffer);
83+
let _ = Self::span_to_writer(self, span, &mut buffer);
8484
}
8585
});
8686
}
8787

8888
pub fn write_tracing_event(&self, event: &tracing::Event<'_>) {
8989
self.with_writer(|w| {
9090
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);
9292
});
9393
}
9494

9595
pub fn write_tracing_opentelemetry_data(&self, data: &OtelData) {
9696
self.with_writer(|w| {
9797
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);
9999
});
100100
}
101101

@@ -107,13 +107,12 @@ impl ConsoleWriter {
107107
}
108108
}
109109

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<()> {
111111
// only print for pending span and logs
112112
if span.get_span_type().is_none_or(|ty| ty == "span") {
113113
return Ok(());
114114
}
115115

116-
let timestamp: DateTime<Utc> = span.start_time.into();
117116
let mut msg = None;
118117
let mut level = None;
119118
let mut target = None;
@@ -152,11 +151,15 @@ impl ConsoleWriter {
152151
msg = Some(span.name.clone());
153152
}
154153

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+
160163
if let Some(level) = level {
161164
level_int_to_text(level, w)?;
162165
}
@@ -183,8 +186,11 @@ impl ConsoleWriter {
183186
writeln!(w)
184187
}
185188

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<()> {
188194
let level = level_to_level_number(*event.metadata().level());
189195
let target = event.metadata().module_path();
190196

@@ -199,11 +205,14 @@ impl ConsoleWriter {
199205
.message
200206
.unwrap_or_else(|| event.metadata().name().to_string());
201207

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+
}
207216

208217
level_int_to_text(level, w)?;
209218

@@ -226,15 +235,10 @@ impl ConsoleWriter {
226235
}
227236

228237
fn otel_data_to_writer<W: io::Write>(
238+
&self,
229239
data: &tracing_opentelemetry::OtelData,
230240
w: &mut W,
231241
) -> io::Result<()> {
232-
let timestamp: DateTime<Utc> = data
233-
.builder
234-
.start_time
235-
.unwrap_or_else(SystemTime::now)
236-
.into();
237-
238242
let mut msg = None;
239243
let mut level = None;
240244
let mut target = None;
@@ -273,11 +277,19 @@ impl ConsoleWriter {
273277
msg = Some(data.builder.name.clone());
274278
}
275279

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+
281293
if let Some(level) = level {
282294
level_int_to_text(level, w)?;
283295
}
@@ -377,13 +389,60 @@ mod tests {
377389
let output = std::str::from_utf8(&output).unwrap();
378390
let output = remap_timestamps_in_console_output(output);
379391

380-
assert_snapshot!(output, @r#"
392+
assert_snapshot!(output, @r"
381393
1970-01-01T00:00:00.000000Z INFO logfire::internal::exporters::console::tests root span
382394
1970-01-01T00:00:00.000001Z INFO logfire::internal::exporters::console::tests hello world span
383395
1970-01-01T00:00:00.000002Z DEBUG logfire::internal::exporters::console::tests debug span
384396
1970-01-01T00:00:00.000003Z DEBUG logfire::internal::exporters::console::tests debug span with explicit parent
385397
1970-01-01T00:00:00.000004Z INFO logfire::internal::exporters::console::tests hello world log
386-
1970-01-01T00:00:00.000005Z ERROR logfire panic: oh no! location=src/internal/exporters/console.rs:369:17, backtrace=disabled backtrace
387-
"#);
398+
1970-01-01T00:00:00.000005Z ERROR logfire panic: oh no! location=src/internal/exporters/console.rs:381:17, backtrace=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+
 INFO logfire::internal::exporters::console::tests root span
441+
 INFO logfire::internal::exporters::console::tests hello world span
442+
 DEBUG logfire::internal::exporters::console::tests debug span
443+
 DEBUG logfire::internal::exporters::console::tests debug span with explicit parent
444+
 INFO logfire::internal::exporters::console::tests hello world log
445+
 ERROR logfire panic: oh no! location=src/internal/exporters/console.rs:428:17, backtrace=disabled backtrace
446+
");
388447
}
389448
}

0 commit comments

Comments
 (0)