opentelemetry_stdout/trace/
exporter.rs1use chrono::{DateTime, Utc};
2use core::fmt;
3use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult};
4use opentelemetry_sdk::trace::SpanData;
5use std::sync::atomic::{AtomicBool, Ordering};
6
7use opentelemetry_sdk::resource::Resource;
8
9pub struct SpanExporter {
11 resource: Resource,
12 is_shutdown: AtomicBool,
13 resource_emitted: AtomicBool,
14}
15
16impl fmt::Debug for SpanExporter {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 f.write_str("SpanExporter")
19 }
20}
21
22impl Default for SpanExporter {
23 fn default() -> Self {
24 SpanExporter {
25 resource: Resource::builder().build(),
26 is_shutdown: AtomicBool::new(false),
27 resource_emitted: AtomicBool::new(false),
28 }
29 }
30}
31
32impl opentelemetry_sdk::trace::SpanExporter for SpanExporter {
33 async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
35 if self.is_shutdown.load(Ordering::SeqCst) {
36 Err(OTelSdkError::AlreadyShutdown)
37 } else {
38 println!("Spans");
39 if self
40 .resource_emitted
41 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
42 .is_err()
43 {
44 print_spans(batch);
45 } else {
46 println!("Resource");
47 if let Some(schema_url) = self.resource.schema_url() {
48 println!("\tResource SchemaUrl: {schema_url:?}");
49 }
50
51 self.resource.iter().for_each(|(k, v)| {
52 println!("\t -> {k}={v:?}");
53 });
54
55 print_spans(batch);
56 }
57
58 Ok(())
59 }
60 }
61
62 fn shutdown(&mut self) -> OTelSdkResult {
63 self.is_shutdown.store(true, Ordering::SeqCst);
64 Ok(())
65 }
66
67 fn set_resource(&mut self, res: &opentelemetry_sdk::Resource) {
68 self.resource = res.clone();
69 }
70}
71
72fn print_spans(batch: Vec<SpanData>) {
73 for (i, span) in batch.into_iter().enumerate() {
74 println!("Span #{i}");
75 println!("\tInstrumentation Scope");
76 println!(
77 "\t\tName : {:?}",
78 &span.instrumentation_scope.name()
79 );
80 if let Some(version) = &span.instrumentation_scope.version() {
81 println!("\t\tVersion : {version:?}");
82 }
83 if let Some(schema_url) = &span.instrumentation_scope.schema_url() {
84 println!("\t\tSchemaUrl: {schema_url:?}");
85 }
86 span.instrumentation_scope
87 .attributes()
88 .enumerate()
89 .for_each(|(index, kv)| {
90 if index == 0 {
91 println!("\t\tScope Attributes:");
92 }
93 println!("\t\t\t -> {}: {}", kv.key, kv.value);
94 });
95
96 println!();
97 println!("\tName : {}", &span.name);
98 println!("\tTraceId : {}", &span.span_context.trace_id());
99 println!("\tSpanId : {}", &span.span_context.span_id());
100 println!("\tTraceFlags : {:?}", &span.span_context.trace_flags());
101 if span.parent_span_id == opentelemetry::SpanId::INVALID {
102 println!("\tParentSpanId : None (root span)");
103 } else {
104 println!("\tParentSpanId : {}", &span.parent_span_id);
105 }
106 println!("\tKind : {:?}", &span.span_kind);
107
108 let datetime: DateTime<Utc> = span.start_time.into();
109 println!(
110 "\tStart time : {}",
111 datetime.format("%Y-%m-%d %H:%M:%S%.6f")
112 );
113 let datetime: DateTime<Utc> = span.end_time.into();
114 println!(
115 "\tEnd time : {}",
116 datetime.format("%Y-%m-%d %H:%M:%S%.6f")
117 );
118 println!("\tStatus : {:?}", &span.status);
119
120 let mut print_header = true;
121 for kv in span.attributes.iter() {
122 if print_header {
123 println!("\tAttributes:");
124 print_header = false;
125 }
126 println!("\t\t -> {}: {:?}", kv.key, kv.value);
127 }
128
129 span.events.iter().enumerate().for_each(|(index, event)| {
130 if index == 0 {
131 println!("\tEvents:");
132 }
133 println!("\tEvent #{index}");
134 println!("\tName : {}", event.name);
135 let datetime: DateTime<Utc> = event.timestamp.into();
136 println!("\tTimestamp : {}", datetime.format("%Y-%m-%d %H:%M:%S%.6f"));
137
138 event.attributes.iter().enumerate().for_each(|(index, kv)| {
139 if index == 0 {
140 println!("\tAttributes:");
141 }
142 println!("\t\t -> {}: {:?}", kv.key, kv.value);
143 });
144 });
145
146 span.links.iter().enumerate().for_each(|(index, link)| {
147 if index == 0 {
148 println!("\tLinks:");
149 }
150 println!("\tLink #{index}");
151 println!("\tTraceId: {}", link.span_context.trace_id());
152 println!("\tSpanId : {}", link.span_context.span_id());
153
154 link.attributes.iter().enumerate().for_each(|(index, kv)| {
155 if index == 0 {
156 println!("\tAttributes:");
157 }
158 println!("\t\t -> {}: {:?}", kv.key, kv.value);
159 });
160 });
161 }
162}