1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! # Tracing OpenTelemetry
//!
//! [`tracing`] is a framework for instrumenting Rust programs to collect
//! structured, event-based diagnostic information. This crate provides a layer
//! that connects spans from multiple systems into a trace and emits them to
//! [OpenTelemetry]-compatible distributed tracing systems for processing and
//! visualization.
//!
//! [OpenTelemetry]: https://opentelemetry.io
//! [`tracing`]: https://github.com/tokio-rs/tracing
//!
//! *Compiler support: [requires `rustc` 1.65+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
//! ### Special Fields
//!
//! Fields with an `otel.` prefix are reserved for this crate and have specific
//! meaning. They are treated as ordinary fields by other layers. The current
//! special fields are:
//!
//! * `otel.name`: Override the span name sent to OpenTelemetry exporters.
//!    Setting this field is useful if you want to display non-static information
//!    in your span name.
//! * `otel.kind`: Set the span kind to one of the supported OpenTelemetry [span kinds].
//! * `otel.status_code`: Set the span status code to one of the supported OpenTelemetry [span status codes].
//! * `otel.status_message`: Set the span status message.
//!
//! [span kinds]: opentelemetry::trace::SpanKind
//! [span status codes]: opentelemetry::trace::Status
//!
//! ### Semantic Conventions
//!
//! OpenTelemetry defines conventional names for attributes of common
//! operations. These names can be assigned directly as fields, e.g.
//! `trace_span!("request", "otel.kind" = %SpanKind::Client, "url.full" = ..)`, and they
//! will be passed through to your configured OpenTelemetry exporter. You can
//! find the full list of the operations and their expected field names in the
//! [semantic conventions] spec.
//!
//! [semantic conventions]: https://github.com/open-telemetry/semantic-conventions
//!
//! ### Stability Status
//!
//! The OpenTelemetry specification is currently in beta so some breaking
//! changes may still occur on the path to 1.0. You can follow the changes via
//! the [spec repository] to track progress toward stabilization.
//!
//! [spec repository]: https://github.com/open-telemetry/opentelemetry-specification
//!
//! ## Examples
//!
//! ```
//! use opentelemetry_sdk::trace::TracerProvider;
//! use opentelemetry::trace::{Tracer, TracerProvider as _};
//! use tracing::{error, span};
//! use tracing_subscriber::layer::SubscriberExt;
//! use tracing_subscriber::Registry;
//!
//! // Create a new OpenTelemetry trace pipeline that prints to stdout
//! let provider = TracerProvider::builder()
//!     .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
//!     .build();
//! let tracer = provider.tracer("readme_example");
//!
//! // Create a tracing layer with the configured tracer
//! let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
//!
//! // Use the tracing subscriber `Registry`, or any other subscriber
//! // that impls `LookupSpan`
//! let subscriber = Registry::default().with(telemetry);
//!
//! // Trace executed code
//! tracing::subscriber::with_default(subscriber, || {
//!     // Spans will be sent to the configured OpenTelemetry exporter
//!     let root = span!(tracing::Level::TRACE, "app_start", work_units = 2);
//!     let _enter = root.enter();
//!
//!     error!("This event will be logged in the root span.");
//! });
//! ```
//!
//! ## Feature Flags
//!
//! - `metrics`: Enables the [`MetricsLayer`] type, a [layer] that
//!   exports OpenTelemetry metrics from specifically-named events. This enables
//!   the `metrics` feature flag on the `opentelemetry` crate.  *Enabled by
//!   default*.
//!
//! [layer]: tracing_subscriber::layer
//!
//! ## Supported Rust Versions
//!
//! Tracing is built against the latest stable release. The minimum supported
//! version is 1.60. The current Tracing version is not guaranteed to build on
//! Rust versions earlier than the minimum supported version.
//!
//! Tracing follows the same compiler support policies as the rest of the Tokio
//! project. The current stable Rust compiler and the three most recent minor
//! versions before it will always be supported. For example, if the current
//! stable compiler version is 1.45, the minimum supported version will not be
//! increased past 1.42, three minor versions prior. Increasing the minimum
//! supported compiler version is not considered a semver breaking change as
//! long as doing so complies with this policy.
//!
//! [subscriber]: tracing_subscriber::subscribe
#![deny(unreachable_pub)]
#![cfg_attr(test, deny(warnings))]
#![doc(html_root_url = "https://docs.rs/tracing-opentelemetry/0.22.0")]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
    issue_tracker_base_url = "https://github.com/tokio-rs/tracing-opentelemetry/issues/"
)]
#![cfg_attr(
    docsrs,
    // Allows displaying cfgs/feature flags in the documentation.
    feature(doc_cfg, doc_auto_cfg),
    // Allows adding traits to RustDoc's list of "notable traits"
    feature(doc_notable_trait),
    // Fail the docs build if any intra-docs links are broken
    deny(rustdoc::broken_intra_doc_links),
)]

/// Implementation of the trace::Subscriber trait; publishes OpenTelemetry metrics.
#[cfg(feature = "metrics")]
mod metrics;

/// Implementation of the trace::Layer as a source of OpenTelemetry data.
mod layer;
/// Span extension which enables OpenTelemetry context management.
mod span_ext;
/// Protocols for OpenTelemetry Tracers that are compatible with Tracing
mod tracer;

pub use layer::{layer, OpenTelemetryLayer};

#[cfg(feature = "metrics")]
pub use metrics::MetricsLayer;
pub use span_ext::OpenTelemetrySpanExt;
pub use tracer::PreSampledTracer;

/// Per-span OpenTelemetry data tracked by this crate.
///
/// Useful for implementing [PreSampledTracer] in alternate otel SDKs.
#[derive(Debug, Clone)]
pub struct OtelData {
    /// The parent otel `Context` for the current tracing span.
    pub parent_cx: opentelemetry::Context,

    /// The otel span data recorded during the current tracing span.
    pub builder: opentelemetry::trace::SpanBuilder,
}

pub(crate) mod time {
    use std::time::SystemTime;

    #[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
    pub(crate) fn now() -> SystemTime {
        SystemTime::now()
    }

    #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
    pub(crate) fn now() -> SystemTime {
        SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(js_sys::Date::now() as u64)
    }
}