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}