opentelemetry_spanprocessor_any/trace/span.rs
1//! # OpenTelemetry Span interface
2//!
3//! A `Span` represents a single operation within a trace. `Span`s can be nested to form a trace
4//! tree. Each trace contains a root span, which typically describes the end-to-end latency and,
5//! optionally, one or more sub-spans for its sub-operations.
6//!
7//! The `Span`'s start and end timestamps reflect the elapsed real time of the operation. A `Span`'s
8//! start time SHOULD be set to the current time on span creation. After the `Span` is created, it
9//! SHOULD be possible to change its name, set its `Attributes`, and add `Links` and `Events`.
10//! These MUST NOT be changed after the `Span`'s end time has been set.
11//!
12//! `Spans` are not meant to be used to propagate information within a process. To prevent misuse,
13//! implementations SHOULD NOT provide access to a `Span`'s attributes besides its `SpanContext`.
14//!
15//! Vendors may implement the `Span` interface to effect vendor-specific logic. However, alternative
16//! implementations MUST NOT allow callers to create Spans directly. All `Span`s MUST be created
17//! via a Tracer.
18use crate::{trace::SpanContext, KeyValue};
19#[cfg(feature = "serialize")]
20use serde::{Deserialize, Serialize};
21use std::borrow::Cow;
22use std::error::Error;
23use std::fmt;
24use std::time::SystemTime;
25
26/// Interface for a single operation within a trace.
27pub trait Span {
28 /// An API to record events in the context of a given `Span`.
29 ///
30 /// Events have a time associated with the moment when they are
31 /// added to the `Span`.
32 ///
33 /// Events SHOULD preserve the order in which they're set. This will typically match
34 /// the ordering of the events' timestamps.
35 ///
36 /// Note that the OpenTelemetry project documents certain ["standard event names and
37 /// keys"](https://github.com/open-telemetry/opentelemetry-specification/tree/v0.5.0/specification/trace/semantic_conventions/README.md)
38 /// which have prescribed semantic meanings.
39 fn add_event<T>(&mut self, name: T, attributes: Vec<KeyValue>)
40 where
41 T: Into<Cow<'static, str>>,
42 {
43 self.add_event_with_timestamp(name, crate::time::now(), attributes)
44 }
45
46 /// Convenience method to record an exception/error as an `Event`
47 ///
48 /// An exception SHOULD be recorded as an Event on the span during which it occurred.
49 /// The name of the event MUST be "exception".
50 ///
51 /// The semantic conventions for Errors are described in ["Semantic Conventions for Exceptions"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/exceptions.md)
52 ///
53 /// For now we will not set `exception.stacktrace` attribute since the `Error::backtrace`
54 /// method is still in nightly. Users can provide a stacktrace by using the
55 /// `record_exception_with_stacktrace` method.
56 ///
57 /// Users can custom the exception message by overriding the `fmt::Display` trait's `fmt` method
58 /// for the error.
59 fn record_exception(&mut self, err: &dyn Error) {
60 let attributes = vec![KeyValue::new("exception.message", err.to_string())];
61
62 self.add_event("exception".to_string(), attributes);
63 }
64
65 /// Convenience method to record a exception/error as an `Event` with custom stacktrace
66 ///
67 /// See `Span:record_exception` method for more details.
68 fn record_exception_with_stacktrace<T>(&mut self, err: &dyn Error, stacktrace: T)
69 where
70 T: Into<Cow<'static, str>>,
71 {
72 let attributes = vec![
73 KeyValue::new("exception.message", err.to_string()),
74 KeyValue::new("exception.stacktrace", stacktrace.into()),
75 ];
76
77 self.add_event("exception".to_string(), attributes);
78 }
79
80 /// An API to record events at a specific time in the context of a given `Span`.
81 ///
82 /// Events SHOULD preserve the order in which they're set. This will typically match
83 /// the ordering of the events' timestamps.
84 ///
85 /// Note that the OpenTelemetry project documents certain ["standard event names and
86 /// keys"](https://github.com/open-telemetry/opentelemetry-specification/tree/v0.5.0/specification/trace/semantic_conventions/README.md)
87 /// which have prescribed semantic meanings.
88 fn add_event_with_timestamp<T>(
89 &mut self,
90 name: T,
91 timestamp: SystemTime,
92 attributes: Vec<KeyValue>,
93 ) where
94 T: Into<Cow<'static, str>>;
95
96 /// Returns the `SpanContext` for the given `Span`. The returned value may be used even after
97 /// the `Span is finished. The returned value MUST be the same for the entire `Span` lifetime.
98 fn span_context(&self) -> &SpanContext;
99
100 /// Returns true if this `Span` is recording information like events with the `add_event`
101 /// operation, attributes using `set_attributes`, status with `set_status`, etc.
102 ///
103 /// This flag SHOULD be used to avoid expensive computations of a `Span` attributes or events in
104 /// case when a `Span` is definitely not recorded. Note that any child span's recording is
105 /// determined independently from the value of this flag (typically based on the sampled flag of
106 /// a `TraceFlag` on `SpanContext`).
107 ///
108 /// This flag may be true despite the entire trace being sampled out. This allows to record and
109 /// process information about the individual Span without sending it to the backend. An example
110 /// of this scenario may be recording and processing of all incoming requests for the processing
111 /// and building of SLA/SLO latency charts while sending only a subset - sampled spans - to the
112 /// backend. See also the sampling section of SDK design.
113 ///
114 /// Users of the API should only access the `is_recording` property when instrumenting code and
115 /// never access `SampledFlag` unless used in context propagators.
116 fn is_recording(&self) -> bool;
117
118 /// An API to set a single `Attribute` where the attribute properties are passed
119 /// as arguments. To avoid extra allocations some implementations may offer a separate API for
120 /// each of the possible value types.
121 ///
122 /// An `Attribute` is defined as a `KeyValue` pair.
123 ///
124 /// Attributes SHOULD preserve the order in which they're set. Setting an attribute
125 /// with the same key as an existing attribute SHOULD overwrite the existing
126 /// attribute's value.
127 ///
128 /// Note that the OpenTelemetry project documents certain ["standard
129 /// attributes"](https://github.com/open-telemetry/opentelemetry-specification/tree/v0.5.0/specification/trace/semantic_conventions/README.md)
130 /// that have prescribed semantic meanings.
131 fn set_attribute(&mut self, attribute: KeyValue);
132
133 /// Sets the status of the `Span`. `message` MUST be ignored when the status is `OK` or
134 /// `Unset`.
135 ///
136 /// The order of status is `Ok` > `Error` > `Unset`. That's means set the status
137 /// to `Unset` will always be ignore, set the status to `Error` only works when current
138 /// status is `Unset`, set the status to `Ok` will be consider final and any further call
139 /// to this function will be ignore.
140 fn set_status(&mut self, code: StatusCode, message: String);
141
142 /// Updates the `Span`'s name. After this update, any sampling behavior based on the
143 /// name will depend on the implementation.
144 ///
145 /// It is highly discouraged to update the name of a `Span` after its creation.
146 /// `Span` name is often used to group, filter and identify the logical groups of
147 /// spans. Often, filtering logic will be implemented before the `Span` creation
148 /// for performance reasons, and the name update may interfere with this logic.
149 ///
150 /// The method name is called `update_name` to differentiate this method from the
151 /// regular property. It emphasizes that this operation signifies a
152 /// major change for a `Span` and may lead to re-calculation of sampling or
153 /// filtering decisions made previously depending on the implementation.
154 fn update_name<T>(&mut self, new_name: T)
155 where
156 T: Into<Cow<'static, str>>;
157
158 /// Finishes the `Span`.
159 ///
160 /// Implementations MUST ignore all subsequent calls to `end` (there might be
161 /// exceptions when the tracer is streaming events and has no mutable state
162 /// associated with the Span).
163 ///
164 /// Calls to `end` a Span MUST not have any effects on child `Span`s as they may
165 /// still be running and can be ended later.
166 ///
167 /// This API MUST be non-blocking.
168 fn end(&mut self) {
169 self.end_with_timestamp(crate::time::now());
170 }
171
172 /// Finishes the `Span` with given timestamp
173 ///
174 /// For more details, refer to [`Span::end`]
175 ///
176 /// [`Span::end`]: Span::end()
177 fn end_with_timestamp(&mut self, timestamp: SystemTime);
178}
179
180/// `SpanKind` describes the relationship between the Span, its parents,
181/// and its children in a `Trace`. `SpanKind` describes two independent
182/// properties that benefit tracing systems during analysis.
183///
184/// The first property described by `SpanKind` reflects whether the `Span`
185/// is a remote child or parent. `Span`s with a remote parent are
186/// interesting because they are sources of external load. `Span`s with a
187/// remote child are interesting because they reflect a non-local system
188/// dependency.
189///
190/// The second property described by `SpanKind` reflects whether a child
191/// `Span` represents a synchronous call. When a child span is synchronous,
192/// the parent is expected to wait for it to complete under ordinary
193/// circumstances. It can be useful for tracing systems to know this
194/// property, since synchronous `Span`s may contribute to the overall trace
195/// latency. Asynchronous scenarios can be remote or local.
196///
197/// In order for `SpanKind` to be meaningful, callers should arrange that
198/// a single `Span` does not serve more than one purpose. For example, a
199/// server-side span should not be used directly as the parent of another
200/// remote span. As a simple guideline, instrumentation should create a
201/// new `Span` prior to extracting and serializing the span context for a
202/// remote call.
203///
204/// To summarize the interpretation of these kinds:
205///
206/// | `SpanKind` | Synchronous | Asynchronous | Remote Incoming | Remote Outgoing |
207/// |------------|-----|-----|-----|-----|
208/// | `Client` | yes | | | yes |
209/// | `Server` | yes | | yes | |
210/// | `Producer` | | yes | | yes |
211/// | `Consumer` | | yes | yes | |
212/// | `Internal` | | | | |
213#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
214#[derive(Clone, Debug, PartialEq)]
215pub enum SpanKind {
216 /// Indicates that the span describes a synchronous request to
217 /// some remote service. This span is the parent of a remote `Server`
218 /// span and waits for its response.
219 Client,
220 /// Indicates that the span covers server-side handling of a
221 /// synchronous RPC or other remote request. This span is the child of
222 /// a remote `Client` span that was expected to wait for a response.
223 Server,
224 /// Indicates that the span describes the parent of an
225 /// asynchronous request. This parent span is expected to end before
226 /// the corresponding child `Consumer` span, possibly even before the
227 /// child span starts. In messaging scenarios with batching, tracing
228 /// individual messages requires a new `Producer` span per message to
229 /// be created.
230 Producer,
231 /// Indicates that the span describes the child of an
232 /// asynchronous `Producer` request.
233 Consumer,
234 /// Default value. Indicates that the span represents an
235 /// internal operation within an application, as opposed to an
236 /// operations with remote parents or children.
237 Internal,
238}
239
240impl fmt::Display for SpanKind {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 match self {
243 SpanKind::Client => write!(f, "client"),
244 SpanKind::Server => write!(f, "server"),
245 SpanKind::Producer => write!(f, "producer"),
246 SpanKind::Consumer => write!(f, "consumer"),
247 SpanKind::Internal => write!(f, "internal"),
248 }
249 }
250}
251
252/// The `StatusCode` interface represents the status of a finished `Span`.
253/// It's composed of a canonical code in conjunction with an optional
254/// descriptive message.
255#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
256#[derive(Clone, Debug, PartialEq, Copy)]
257pub enum StatusCode {
258 /// The default status.
259 Unset,
260 /// OK is returned on success.
261 Ok,
262 /// The operation contains an error.
263 Error,
264}
265
266impl StatusCode {
267 /// Return a static str that represent the status code
268 pub fn as_str(&self) -> &'static str {
269 match self {
270 StatusCode::Unset => "",
271 StatusCode::Ok => "OK",
272 StatusCode::Error => "ERROR",
273 }
274 }
275
276 /// Return the priority of the status code.
277 /// Status code with higher priority can override the lower priority one.
278 pub(crate) fn priority(&self) -> i32 {
279 match self {
280 StatusCode::Unset => 0,
281 StatusCode::Error => 1,
282 StatusCode::Ok => 2,
283 }
284 }
285}