1mod config;
10mod events;
11mod id_generator;
12mod links;
13mod provider;
14mod sampler;
15mod span;
16mod span_limit;
17mod span_processor;
18mod tracer;
19
20pub use config::{config, Config};
21pub use events::SpanEvents;
22
23pub use id_generator::{IdGenerator, RandomIdGenerator};
24pub use links::SpanLinks;
25pub use provider::{Builder, TracerProvider};
26pub use sampler::{Sampler, ShouldSample};
27pub use span::Span;
28pub use span_limit::SpanLimits;
29pub use span_processor::{
30 BatchConfig, BatchConfigBuilder, BatchSpanProcessor, BatchSpanProcessorBuilder,
31 SimpleSpanProcessor, SpanProcessor,
32};
33pub use tracer::Tracer;
34
35#[cfg(feature = "jaeger_remote_sampler")]
36pub use sampler::{JaegerRemoteSampler, JaegerRemoteSamplerBuilder};
37
38#[cfg(test)]
39mod runtime_tests;
40
41#[cfg(all(test, feature = "testing"))]
42mod tests {
43 use super::*;
44 use crate::{
45 testing::trace::InMemorySpanExporterBuilder,
46 trace::span_limit::{DEFAULT_MAX_EVENT_PER_SPAN, DEFAULT_MAX_LINKS_PER_SPAN},
47 };
48 use opentelemetry::testing::trace::TestSpan;
49 use opentelemetry::trace::{
50 SamplingDecision, SamplingResult, SpanKind, Status, TraceContextExt, TraceState,
51 };
52 use opentelemetry::{
53 trace::{
54 Event, Link, Span, SpanBuilder, SpanContext, SpanId, TraceFlags, TraceId, Tracer,
55 TracerProvider as _,
56 },
57 Context, KeyValue,
58 };
59
60 #[test]
61 fn tracer_in_span() {
62 let exporter = InMemorySpanExporterBuilder::new().build();
64 let provider = TracerProvider::builder()
65 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
66 .build();
67
68 let tracer = provider.tracer("test_tracer");
70 tracer.in_span("span_name", |cx| {
71 let span = cx.span();
72 assert!(span.is_recording());
73 span.update_name("span_name_updated");
74 span.set_attribute(KeyValue::new("attribute1", "value1"));
75 span.add_event("test-event".to_string(), vec![]);
76 });
77
78 let exported_spans = exporter
80 .get_finished_spans()
81 .expect("Spans are expected to be exported.");
82 assert_eq!(exported_spans.len(), 1);
83 let span = &exported_spans[0];
84 assert_eq!(span.name, "span_name_updated");
85 assert_eq!(span.instrumentation_lib.name, "test_tracer");
86 assert_eq!(span.attributes.len(), 1);
87 assert_eq!(span.events.len(), 1);
88 assert_eq!(span.events[0].name, "test-event");
89 assert_eq!(span.span_context.trace_flags(), TraceFlags::SAMPLED);
90 assert!(!span.span_context.is_remote());
91 assert_eq!(span.status, Status::Unset);
92 }
93
94 #[test]
95 fn tracer_start() {
96 let exporter = InMemorySpanExporterBuilder::new().build();
98 let provider = TracerProvider::builder()
99 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
100 .build();
101
102 let tracer = provider.tracer("test_tracer");
104 let mut span = tracer.start("span_name");
105 span.set_attribute(KeyValue::new("attribute1", "value1"));
106 span.add_event("test-event".to_string(), vec![]);
107 span.set_status(Status::error("cancelled"));
108 span.end();
109
110 span.update_name("span_name_updated");
112
113 let exported_spans = exporter
115 .get_finished_spans()
116 .expect("Spans are expected to be exported.");
117 assert_eq!(exported_spans.len(), 1);
118 let span = &exported_spans[0];
119 assert_eq!(span.name, "span_name");
120 assert_eq!(span.instrumentation_lib.name, "test_tracer");
121 assert_eq!(span.attributes.len(), 1);
122 assert_eq!(span.events.len(), 1);
123 assert_eq!(span.events[0].name, "test-event");
124 assert_eq!(span.span_context.trace_flags(), TraceFlags::SAMPLED);
125 assert!(!span.span_context.is_remote());
126 let status_expected = Status::error("cancelled");
127 assert_eq!(span.status, status_expected);
128 }
129
130 #[test]
131 fn tracer_span_builder() {
132 let exporter = InMemorySpanExporterBuilder::new().build();
134 let provider = TracerProvider::builder()
135 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
136 .build();
137
138 let tracer = provider.tracer("test_tracer");
140 let mut span = tracer
141 .span_builder("span_name")
142 .with_kind(SpanKind::Server)
143 .start(&tracer);
144 span.set_attribute(KeyValue::new("attribute1", "value1"));
145 span.add_event("test-event".to_string(), vec![]);
146 span.set_status(Status::Ok);
147 drop(span);
148
149 let exported_spans = exporter
151 .get_finished_spans()
152 .expect("Spans are expected to be exported.");
153 assert_eq!(exported_spans.len(), 1);
154 let span = &exported_spans[0];
155 assert_eq!(span.name, "span_name");
156 assert_eq!(span.span_kind, SpanKind::Server);
157 assert_eq!(span.instrumentation_lib.name, "test_tracer");
158 assert_eq!(span.attributes.len(), 1);
159 assert_eq!(span.events.len(), 1);
160 assert_eq!(span.events[0].name, "test-event");
161 assert_eq!(span.span_context.trace_flags(), TraceFlags::SAMPLED);
162 assert!(!span.span_context.is_remote());
163 assert_eq!(span.status, Status::Ok);
164 }
165
166 #[test]
167 fn exceed_span_links_limit() {
168 let exporter = InMemorySpanExporterBuilder::new().build();
170 let provider = TracerProvider::builder()
171 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
172 .build();
173
174 let tracer = provider.tracer("test_tracer");
176
177 let mut links = Vec::new();
178 for _i in 0..(DEFAULT_MAX_LINKS_PER_SPAN * 2) {
179 links.push(Link::with_context(SpanContext::new(
180 TraceId::from_u128(12),
181 SpanId::from_u64(12),
182 TraceFlags::default(),
183 false,
184 Default::default(),
185 )))
186 }
187
188 let span_builder = SpanBuilder::from_name("span_name").with_links(links);
189 let mut span = tracer.build(span_builder);
190 span.end();
191
192 let exported_spans = exporter
194 .get_finished_spans()
195 .expect("Spans are expected to be exported.");
196 assert_eq!(exported_spans.len(), 1);
197 let span = &exported_spans[0];
198 assert_eq!(span.name, "span_name");
199 assert_eq!(span.links.len(), DEFAULT_MAX_LINKS_PER_SPAN as usize);
200 }
201
202 #[test]
203 fn exceed_span_events_limit() {
204 let exporter = InMemorySpanExporterBuilder::new().build();
206 let provider = TracerProvider::builder()
207 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
208 .build();
209
210 let tracer = provider.tracer("test_tracer");
212
213 let mut events = Vec::new();
214 for _i in 0..(DEFAULT_MAX_EVENT_PER_SPAN * 2) {
215 events.push(Event::with_name("test event"))
216 }
217
218 let span_builder = SpanBuilder::from_name("span_name").with_events(events);
220 let mut span = tracer.build(span_builder);
221
222 span.add_event("test event again, after span builder", Vec::new());
224 span.add_event("test event once again, after span builder", Vec::new());
225 span.end();
226
227 let exported_spans = exporter
229 .get_finished_spans()
230 .expect("Spans are expected to be exported.");
231 assert_eq!(exported_spans.len(), 1);
232 let span = &exported_spans[0];
233 assert_eq!(span.name, "span_name");
234 assert_eq!(span.events.len(), DEFAULT_MAX_EVENT_PER_SPAN as usize);
235 assert_eq!(span.events.dropped_count, DEFAULT_MAX_EVENT_PER_SPAN + 2);
236 }
237
238 #[test]
239 fn trace_state_for_dropped_sampler() {
240 let exporter = InMemorySpanExporterBuilder::new().build();
241 let provider = TracerProvider::builder()
242 .with_config(Config::default().with_sampler(Sampler::AlwaysOff))
243 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
244 .build();
245
246 let tracer = provider.tracer("test");
247 let trace_state = TraceState::from_key_value(vec![("foo", "bar")]).unwrap();
248
249 let parent_context = Context::new().with_span(TestSpan(SpanContext::new(
250 TraceId::from_u128(10000),
251 SpanId::from_u64(20),
252 TraceFlags::SAMPLED,
253 true,
254 trace_state.clone(),
255 )));
256
257 let span = tracer.start_with_context("span", &parent_context);
258 assert_eq!(
259 span.span_context().trace_state().get("foo"),
260 trace_state.get("foo")
261 )
262 }
263
264 #[derive(Clone, Debug, Default)]
265 struct TestRecordOnlySampler {}
266
267 impl ShouldSample for TestRecordOnlySampler {
268 fn should_sample(
269 &self,
270 parent_context: Option<&Context>,
271 _trace_id: TraceId,
272 _name: &str,
273 _span_kind: &SpanKind,
274 _attributes: &[KeyValue],
275 _links: &[Link],
276 ) -> SamplingResult {
277 let trace_state = parent_context
278 .unwrap()
279 .span()
280 .span_context()
281 .trace_state()
282 .clone();
283 SamplingResult {
284 decision: SamplingDecision::RecordOnly,
285 attributes: vec![KeyValue::new("record_only_key", "record_only_value")],
286 trace_state,
287 }
288 }
289 }
290
291 #[test]
292 fn trace_state_for_record_only_sampler() {
293 let exporter = InMemorySpanExporterBuilder::new().build();
294 let provider = TracerProvider::builder()
295 .with_config(Config::default().with_sampler(TestRecordOnlySampler::default()))
296 .with_span_processor(SimpleSpanProcessor::new(Box::new(exporter.clone())))
297 .build();
298
299 let tracer = provider.tracer("test");
300 let trace_state = TraceState::from_key_value(vec![("foo", "bar")]).unwrap();
301
302 let parent_context = Context::new().with_span(TestSpan(SpanContext::new(
303 TraceId::from_u128(10000),
304 SpanId::from_u64(20),
305 TraceFlags::SAMPLED,
306 true,
307 trace_state.clone(),
308 )));
309
310 let span = tracer.build_with_context(
311 SpanBuilder::from_name("span")
312 .with_attributes(vec![KeyValue::new("extra_attr_key", "extra_attr_value")]),
313 &parent_context,
314 );
315 assert!(!span.span_context().trace_flags().is_sampled());
316 assert_eq!(
317 span.exported_data().unwrap().attributes,
318 vec![
319 KeyValue::new("extra_attr_key", "extra_attr_value"),
320 KeyValue::new("record_only_key", "record_only_value")
321 ]
322 );
323 assert_eq!(span.span_context().trace_state().get("foo"), Some("bar"));
324 }
325
326 #[test]
327 fn tracer_attributes() {
328 let provider = TracerProvider::builder().build();
329 let tracer = provider
330 .tracer_builder("test_tracer")
331 .with_attributes(vec![KeyValue::new("test_k", "test_v")])
332 .build();
333 let instrumentation_library = tracer.instrumentation_library();
334 let attributes = &instrumentation_library.attributes;
335 assert_eq!(attributes.len(), 1);
336 assert_eq!(attributes[0].key, "test_k".into());
337 assert_eq!(attributes[0].value, "test_v".into());
338 }
339
340 #[test]
341 #[allow(deprecated)]
342 fn versioned_tracer_options() {
343 let provider = TracerProvider::builder().build();
344 let tracer = provider.versioned_tracer(
345 "test_tracer",
346 Some(String::from("v1.2.3")),
347 Some(String::from("https://opentelemetry.io/schema/1.0.0")),
348 Some(vec![(KeyValue::new("test_k", "test_v"))]),
349 );
350 let instrumentation_library = tracer.instrumentation_library();
351 let attributes = &instrumentation_library.attributes;
352 assert_eq!(instrumentation_library.name, "test_tracer");
353 assert_eq!(instrumentation_library.version, Some("v1.2.3".into()));
354 assert_eq!(
355 instrumentation_library.schema_url,
356 Some("https://opentelemetry.io/schema/1.0.0".into())
357 );
358 assert_eq!(attributes.len(), 1);
359 assert_eq!(attributes[0].key, "test_k".into());
360 assert_eq!(attributes[0].value, "test_v".into());
361 }
362}