opentelemetry_stdout/logs/
exporter.rs

1use chrono::{DateTime, Utc};
2use core::fmt;
3use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult};
4use opentelemetry_sdk::logs::LogBatch;
5use opentelemetry_sdk::Resource;
6use std::sync::atomic;
7use std::sync::atomic::Ordering;
8use std::time;
9
10/// An OpenTelemetry exporter that writes Logs to stdout on export.
11pub struct LogExporter {
12    resource: Resource,
13    is_shutdown: atomic::AtomicBool,
14    resource_emitted: atomic::AtomicBool,
15}
16
17impl Default for LogExporter {
18    fn default() -> Self {
19        LogExporter {
20            resource: Resource::builder().build(),
21            is_shutdown: atomic::AtomicBool::new(false),
22            resource_emitted: atomic::AtomicBool::new(false),
23        }
24    }
25}
26
27impl fmt::Debug for LogExporter {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        f.write_str("LogExporter")
30    }
31}
32
33impl opentelemetry_sdk::logs::LogExporter for LogExporter {
34    /// Export logs to stdout
35    async fn export(&self, batch: LogBatch<'_>) -> OTelSdkResult {
36        if self.is_shutdown.load(atomic::Ordering::SeqCst) {
37            Err(OTelSdkError::AlreadyShutdown)
38        } else {
39            println!("Logs");
40            if self
41                .resource_emitted
42                .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
43                .is_err()
44            {
45                print_logs(batch);
46            } else {
47                println!("Resource");
48                if let Some(schema_url) = self.resource.schema_url() {
49                    println!("\t Resource SchemaUrl: {schema_url:?}");
50                }
51                self.resource.iter().for_each(|(k, v)| {
52                    println!("\t ->  {k}={v:?}");
53                });
54                print_logs(batch);
55            }
56
57            Ok(())
58        }
59    }
60
61    fn shutdown_with_timeout(&self, _timeout: time::Duration) -> OTelSdkResult {
62        self.is_shutdown.store(true, atomic::Ordering::SeqCst);
63        Ok(())
64    }
65
66    fn set_resource(&mut self, res: &opentelemetry_sdk::Resource) {
67        self.resource = res.clone();
68    }
69}
70
71fn print_logs(batch: LogBatch<'_>) {
72    for (i, log) in batch.iter().enumerate() {
73        println!("Log #{i}");
74        let (record, library) = log;
75
76        println!("\t Instrumentation Scope: {library:?}");
77
78        if let Some(event_name) = record.event_name() {
79            println!("\t EventName: {event_name:?}");
80        }
81        if let Some(target) = record.target() {
82            println!("\t Target (Scope): {target:?}");
83        }
84        if let Some(trace_context) = record.trace_context() {
85            println!("\t TraceId: {:?}", trace_context.trace_id);
86            println!("\t SpanId: {:?}", trace_context.span_id);
87            if let Some(trace_flags) = trace_context.trace_flags {
88                println!("\t TraceFlags: {trace_flags:?}");
89            }
90        }
91        if let Some(timestamp) = record.timestamp() {
92            let datetime: DateTime<Utc> = timestamp.into();
93            println!("\t Timestamp: {}", datetime.format("%Y-%m-%d %H:%M:%S%.6f"));
94        }
95        if let Some(timestamp) = record.observed_timestamp() {
96            let datetime: DateTime<Utc> = timestamp.into();
97            println!(
98                "\t Observed Timestamp: {}",
99                datetime.format("%Y-%m-%d %H:%M:%S%.6f")
100            );
101        }
102        if let Some(severity) = record.severity_text() {
103            println!("\t SeverityText: {severity:?}");
104        }
105        if let Some(severity) = record.severity_number() {
106            println!("\t SeverityNumber: {severity:?}");
107        }
108        if let Some(body) = record.body() {
109            println!("\t Body: {body:?}");
110        }
111
112        println!("\t Attributes:");
113        for (k, v) in record.attributes_iter() {
114            println!("\t\t ->  {k}: {v:?}");
115        }
116    }
117}