opentelemetry_spanprocessor_any/testing/
trace.rs1use crate::{
2 sdk::export::{
3 trace::{ExportResult, SpanData, SpanExporter},
4 ExportError,
5 },
6 sdk::{
7 trace::{Config, EvictedHashMap, EvictedQueue},
8 InstrumentationLibrary,
9 },
10 trace::{Span, SpanContext, SpanId, SpanKind, StatusCode, TraceId},
11 KeyValue,
12};
13use async_trait::async_trait;
14use std::borrow::Cow;
15use std::fmt::{Display, Formatter};
16use std::sync::mpsc::{channel, Receiver, Sender};
17
18#[derive(Debug)]
19pub struct TestSpan(pub SpanContext);
20
21impl Span for TestSpan {
22 fn add_event_with_timestamp<T>(
23 &mut self,
24 _name: T,
25 _timestamp: std::time::SystemTime,
26 _attributes: Vec<KeyValue>,
27 ) where
28 T: Into<Cow<'static, str>>,
29 {
30 }
31 fn span_context(&self) -> &SpanContext {
32 &self.0
33 }
34 fn is_recording(&self) -> bool {
35 false
36 }
37 fn set_attribute(&mut self, _attribute: KeyValue) {}
38 fn set_status(&mut self, _code: StatusCode, _message: String) {}
39 fn update_name<T>(&mut self, _new_name: T)
40 where
41 T: Into<Cow<'static, str>>,
42 {
43 }
44 fn end_with_timestamp(&mut self, _timestamp: std::time::SystemTime) {}
45}
46
47pub fn new_test_export_span_data() -> SpanData {
48 let config = Config::default();
49 SpanData {
50 span_context: SpanContext::empty_context(),
51 parent_span_id: SpanId::INVALID,
52 span_kind: SpanKind::Internal,
53 name: "opentelemetry".into(),
54 start_time: crate::time::now(),
55 end_time: crate::time::now(),
56 attributes: EvictedHashMap::new(config.span_limits.max_attributes_per_span, 0),
57 events: EvictedQueue::new(config.span_limits.max_events_per_span),
58 links: EvictedQueue::new(config.span_limits.max_links_per_span),
59 status_code: StatusCode::Unset,
60 status_message: "".into(),
61 resource: config.resource,
62 instrumentation_lib: InstrumentationLibrary::default(),
63 }
64}
65
66#[derive(Debug)]
67pub struct TestSpanExporter {
68 tx_export: Sender<SpanData>,
69 tx_shutdown: Sender<()>,
70}
71
72#[async_trait]
73impl SpanExporter for TestSpanExporter {
74 async fn export(&mut self, batch: Vec<SpanData>) -> ExportResult {
75 for span_data in batch {
76 self.tx_export
77 .send(span_data)
78 .map_err::<TestExportError, _>(Into::into)?;
79 }
80 Ok(())
81 }
82
83 fn shutdown(&mut self) {
84 self.tx_shutdown.send(()).unwrap();
85 }
86}
87
88pub fn new_test_exporter() -> (TestSpanExporter, Receiver<SpanData>, Receiver<()>) {
89 let (tx_export, rx_export) = channel();
90 let (tx_shutdown, rx_shutdown) = channel();
91 let exporter = TestSpanExporter {
92 tx_export,
93 tx_shutdown,
94 };
95 (exporter, rx_export, rx_shutdown)
96}
97
98#[derive(Debug)]
99pub struct TokioSpanExporter {
100 tx_export: tokio::sync::mpsc::UnboundedSender<SpanData>,
101 tx_shutdown: tokio::sync::mpsc::UnboundedSender<()>,
102}
103
104#[async_trait]
105impl SpanExporter for TokioSpanExporter {
106 async fn export(&mut self, batch: Vec<SpanData>) -> ExportResult {
107 for span_data in batch {
108 self.tx_export
109 .send(span_data)
110 .map_err::<TestExportError, _>(Into::into)?;
111 }
112 Ok(())
113 }
114
115 fn shutdown(&mut self) {
116 self.tx_shutdown.send(()).unwrap();
117 }
118}
119
120pub fn new_tokio_test_exporter() -> (
121 TokioSpanExporter,
122 tokio::sync::mpsc::UnboundedReceiver<SpanData>,
123 tokio::sync::mpsc::UnboundedReceiver<()>,
124) {
125 let (tx_export, rx_export) = tokio::sync::mpsc::unbounded_channel();
126 let (tx_shutdown, rx_shutdown) = tokio::sync::mpsc::unbounded_channel();
127 let exporter = TokioSpanExporter {
128 tx_export,
129 tx_shutdown,
130 };
131 (exporter, rx_export, rx_shutdown)
132}
133
134#[derive(Debug)]
135pub struct TestExportError(String);
136
137impl std::error::Error for TestExportError {}
138
139impl ExportError for TestExportError {
140 fn exporter_name(&self) -> &'static str {
141 "test"
142 }
143}
144
145impl Display for TestExportError {
146 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
147 write!(f, "{}", self.0)
148 }
149}
150
151impl<T> From<tokio::sync::mpsc::error::SendError<T>> for TestExportError {
152 fn from(err: tokio::sync::mpsc::error::SendError<T>) -> Self {
153 TestExportError(err.to_string())
154 }
155}
156
157impl<T> From<std::sync::mpsc::SendError<T>> for TestExportError {
158 fn from(err: std::sync::mpsc::SendError<T>) -> Self {
159 TestExportError(err.to_string())
160 }
161}
162
163impl TraceId {
165 pub fn from_u128(num: u128) -> Self {
166 TraceId(num)
167 }
168}
169
170impl SpanId {
172 pub fn from_u64(num: u64) -> Self {
173 SpanId(num)
174 }
175}