opentelemetry/trace/mod.rs
1//! API for tracing applications and libraries.
2//!
3//! The `trace` module includes types for tracking the progression of a single
4//! request while it is handled by services that make up an application. A trace
5//! is a tree of [`Span`]s which are objects that represent the work being done
6//! by individual services or components involved in a request as it flows
7//! through a system. This module implements the OpenTelemetry [trace
8//! specification].
9//!
10//! [trace specification]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md
11//!
12//! ## Getting Started
13//!
14//! In application code:
15//!
16//! ```
17//! use opentelemetry::trace::{Tracer, noop::NoopTracerProvider};
18//! use opentelemetry::global;
19//!
20//! fn init_tracer() {
21//! // Swap this no-op provider for your tracing service of choice (jaeger, zipkin, etc)
22//! let provider = NoopTracerProvider::new();
23//!
24//! // Configure the global `TracerProvider` singleton when your app starts
25//! // (there is a no-op default if this is not set by your application)
26//! let _ = global::set_tracer_provider(provider);
27//! }
28//!
29//! fn do_something_tracked() {
30//! // Then you can get a named tracer instance anywhere in your codebase.
31//! let tracer = global::tracer("my-component");
32//!
33//! tracer.in_span("doing_work", |cx| {
34//! // Traced app logic here...
35//! });
36//! }
37//!
38//! // in main or other app start
39//! init_tracer();
40//! do_something_tracked();
41//! ```
42//!
43//! In library code:
44//!
45//! ```
46//! use opentelemetry::{global, trace::{Span, Tracer, TracerProvider}};
47//! use opentelemetry::InstrumentationScope;
48//! use std::sync::Arc;
49//!
50//! fn my_library_function() {
51//! // Use the global tracer provider to get access to the user-specified
52//! // tracer configuration
53//! let tracer_provider = global::tracer_provider();
54//!
55//! // Get a tracer for this library
56//! let scope = InstrumentationScope::builder("my_name")
57//! .with_version(env!("CARGO_PKG_VERSION"))
58//! .with_schema_url("https://opentelemetry.io/schemas/1.17.0")
59//! .build();
60//!
61//! let tracer = tracer_provider.tracer_with_scope(scope);
62//!
63//! // Create spans
64//! let mut span = tracer.start("doing_work");
65//!
66//! // Do work...
67//!
68//! // End the span
69//! span.end();
70//! }
71//! ```
72//!
73//! ## Overview
74//!
75//! The tracing API consists of a three main traits:
76//!
77//! * [`TracerProvider`]s are the entry point of the API. They provide access to
78//! `Tracer`s.
79//! * [`Tracer`]s are types responsible for creating `Span`s.
80//! * [`Span`]s provide the API to trace an operation.
81//!
82//! ## Working with Async Runtimes
83//!
84//! Exporting spans often involves sending data over a network or performing
85//! other I/O tasks. OpenTelemetry allows you to schedule these tasks using
86//! whichever runtime you are already using such as [Tokio].
87//! When using an async runtime it's best to use the batch span processor
88//! where the spans will be sent in batches as opposed to being sent once ended,
89//! which often ends up being more efficient.
90//!
91//! [Tokio]: https://tokio.rs
92//!
93//! ## Managing Active Spans
94//!
95//! Spans can be marked as "active" for a given [`Context`], and all newly
96//! created spans will automatically be children of the currently active span.
97//!
98//! The active span for a given thread can be managed via [`get_active_span`]
99//! and [`mark_span_as_active`].
100//!
101//! [`Context`]: crate::Context
102//!
103//! ```
104//! use opentelemetry::{global, trace::{self, Span, Status, Tracer, TracerProvider}};
105//!
106//! fn may_error(rand: f32) {
107//! if rand < 0.5 {
108//! // Get the currently active span to record additional attributes,
109//! // status, etc.
110//! trace::get_active_span(|span| {
111//! span.set_status(Status::error("value too small"));
112//! });
113//! }
114//! }
115//!
116//! // Get a tracer
117//! let tracer = global::tracer("my_tracer");
118//!
119//! // Create a span
120//! let span = tracer.start("parent_span");
121//!
122//! // Mark the span as active
123//! let active = trace::mark_span_as_active(span);
124//!
125//! // Any span created here will be a child of `parent_span`...
126//!
127//! // Drop the guard and the span will no longer be active
128//! drop(active)
129//! ```
130//!
131//! Additionally [`Tracer::in_span`] can be used as shorthand to simplify
132//! managing the parent context.
133//!
134//! ```
135//! use opentelemetry::{global, trace::Tracer};
136//!
137//! // Get a tracer
138//! let tracer = global::tracer("my_tracer");
139//!
140//! // Use `in_span` to create a new span and mark it as the parent, dropping it
141//! // at the end of the block.
142//! tracer.in_span("parent_span", |cx| {
143//! // spans created here will be children of `parent_span`
144//! });
145//! ```
146//!
147//! #### Async active spans
148//!
149//! Async spans can be propagated with [`TraceContextExt`] and [`FutureExt`].
150//!
151//! ```
152//! use opentelemetry::{Context, global, trace::{FutureExt, TraceContextExt, Tracer}};
153//!
154//! async fn some_work() { }
155//! # async fn in_an_async_context() {
156//!
157//! // Get a tracer
158//! let tracer = global::tracer("my_tracer");
159//!
160//! // Start a span
161//! let span = tracer.start("my_span");
162//!
163//! // Perform some async work with this span as the currently active parent.
164//! some_work().with_context(Context::current_with_span(span)).await;
165//! # }
166//! ```
167
168use std::borrow::Cow;
169use std::time;
170
171pub(crate) mod context;
172pub mod noop;
173mod span;
174mod span_context;
175mod tracer;
176mod tracer_provider;
177
178pub use self::{
179 context::{
180 get_active_span, mark_span_as_active, FutureExt, SpanRef, TraceContextExt, WithContext,
181 },
182 span::{Span, SpanKind, Status},
183 span_context::{SpanContext, TraceState},
184 tracer::{SamplingDecision, SamplingResult, SpanBuilder, Tracer},
185 tracer_provider::TracerProvider,
186};
187use crate::KeyValue;
188pub use crate::{SpanId, TraceFlags, TraceId};
189
190/// Events record things that happened during a [`Span`]'s lifetime.
191#[non_exhaustive]
192#[derive(Clone, Debug, PartialEq)]
193pub struct Event {
194 /// The name of this event.
195 pub name: Cow<'static, str>,
196
197 /// The time at which this event occurred.
198 pub timestamp: time::SystemTime,
199
200 /// Attributes that describe this event.
201 pub attributes: Vec<KeyValue>,
202
203 /// The number of attributes that were above the configured limit, and thus
204 /// dropped.
205 pub dropped_attributes_count: u32,
206}
207
208impl Event {
209 /// Create new `Event`
210 pub fn new<T: Into<Cow<'static, str>>>(
211 name: T,
212 timestamp: time::SystemTime,
213 attributes: Vec<KeyValue>,
214 dropped_attributes_count: u32,
215 ) -> Self {
216 Event {
217 name: name.into(),
218 timestamp,
219 attributes,
220 dropped_attributes_count,
221 }
222 }
223
224 /// Create new `Event` with a given name.
225 pub fn with_name<T: Into<Cow<'static, str>>>(name: T) -> Self {
226 Event {
227 name: name.into(),
228 timestamp: crate::time::now(),
229 attributes: Vec::new(),
230 dropped_attributes_count: 0,
231 }
232 }
233}
234
235/// Link is the relationship between two Spans.
236///
237/// The relationship can be within the same trace or across different traces.
238#[non_exhaustive]
239#[derive(Clone, Debug, PartialEq)]
240pub struct Link {
241 /// The span context of the linked span.
242 pub span_context: SpanContext,
243
244 /// Attributes that describe this link.
245 pub attributes: Vec<KeyValue>,
246
247 /// The number of attributes that were above the configured limit, and thus
248 /// dropped.
249 pub dropped_attributes_count: u32,
250}
251
252impl Link {
253 /// Create new `Link`
254 pub fn new(
255 span_context: SpanContext,
256 attributes: Vec<KeyValue>,
257 dropped_attributes_count: u32,
258 ) -> Self {
259 Link {
260 span_context,
261 attributes,
262 dropped_attributes_count,
263 }
264 }
265
266 /// Create new `Link` with given context
267 pub fn with_context(span_context: SpanContext) -> Self {
268 Link {
269 span_context,
270 attributes: Vec::new(),
271 dropped_attributes_count: 0,
272 }
273 }
274}