opentelemetry_instrumentation_tokio/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(clippy::all, clippy::pedantic)]
3
4use opentelemetry::{Key, KeyValue, Value};
5
6mod runtime;
7
8/// Configuration for Tokio runtime instrumentation.
9///
10/// ## Multiple Runtimes with Custom Labels
11///
12/// ```no_run
13/// use opentelemetry::KeyValue;
14/// use opentelemetry_instrumentation_tokio::Config;
15///
16/// let rt1 = Runtime::new().unwrap();
17/// let rt2 = Runtime::new().unwrap();
18///
19/// // Add custom labels to distinguish runtimes
20/// Config::new()
21///     .with_label("runtime.name", "api-server")
22///     .observe_runtime(rt1.handle());
23/// Config::new()
24///     .with_label("runtime.name", "worker")
25///     .observe_runtime(rt2.handle());
26/// ```
27#[derive(Debug, Clone)]
28pub struct Config {
29    labels: Vec<KeyValue>,
30}
31
32impl Config {
33    /// Create a new configuration with default settings.
34    #[must_use]
35    pub fn new() -> Self {
36        Self { labels: Vec::new() }
37    }
38
39    /// Add custom labels to this runtime's metrics.
40    ///
41    /// Labels help distinguish metrics from different runtimes when observing
42    /// multiple runtimes in the same process.
43    ///
44    /// When `tokio_unstable` is enabled, a `tokio.runtime.id` label is
45    /// automatically added in addition to any custom labels.
46    ///
47    /// # Examples
48    ///
49    /// ```no_run
50    /// use opentelemetry::KeyValue;
51    /// use opentelemetry_instrumentation_tokio::Config;
52    ///
53    /// # #[tokio::main]
54    /// # async fn main() {
55    /// Config::new()
56    ///     .with_labels([
57    ///         KeyValue::new("runtime.name", "worker-pool"),
58    ///         KeyValue::new("env", "production"),
59    ///     ])
60    ///     .observe_current_runtime();
61    /// # }
62    /// ```
63    #[must_use]
64    pub fn with_labels(mut self, labels: impl IntoIterator<Item = KeyValue>) -> Self {
65        self.labels.extend(labels);
66        self
67    }
68
69    /// Add a single custom label to this runtime's metrics.
70    ///
71    /// This method can be chained to add multiple labels.
72    ///
73    /// # Examples
74    ///
75    /// ```no_run
76    /// use opentelemetry_instrumentation_tokio::Config;
77    ///
78    /// # #[tokio::main]
79    /// # async fn main() {
80    /// Config::new()
81    ///     .with_label("runtime.name", "api-server")
82    ///     .with_label("runtime.purpose", "http-requests")
83    ///     .observe_current_runtime();
84    /// # }
85    /// ```
86    #[must_use]
87    pub fn with_label(mut self, key: impl Into<Key>, value: impl Into<Value>) -> Self {
88        self.labels.push(KeyValue::new(key, value));
89        self
90    }
91
92    /// Observe metrics for the current Tokio runtime.
93    ///
94    /// This is a convenience method that calls [`Self::observe_runtime`] with
95    /// the current runtime handle.
96    ///
97    /// # Panics
98    ///
99    /// Panics if called outside of a Tokio runtime context.
100    ///
101    /// # Examples
102    ///
103    /// ```no_run
104    /// use opentelemetry_instrumentation_tokio::Config;
105    ///
106    /// # #[tokio::main]
107    /// # async fn main() {
108    /// Config::new().observe_current_runtime();
109    /// # }
110    /// ```
111    pub fn observe_current_runtime(self) {
112        let handle = tokio::runtime::Handle::current();
113        self.observe_runtime(&handle);
114    }
115
116    /// Observe metrics for a specific Tokio runtime.
117    ///
118    /// Registers OpenTelemetry observable instruments that expose Tokio runtime
119    /// metrics. The metrics are collected on-demand by the configured meter
120    /// provider.
121    ///
122    /// This function can be called multiple times to observe multiple runtimes.
123    /// Each runtime's metrics will be distinguished by the labels configured
124    /// via [`Self::with_labels`] or [`Self::with_label`].
125    ///
126    /// When `tokio_unstable` is enabled, a `tokio.runtime.id` label is
127    /// automatically added.
128    ///
129    /// # Examples
130    ///
131    /// ```no_run
132    /// use opentelemetry_instrumentation_tokio::Config;
133    ///
134    /// # #[tokio::main]
135    /// # async fn main() {
136    /// let handle = tokio::runtime::Handle::current();
137    /// Config::new().observe_runtime(&handle);
138    /// # }
139    /// ```
140    ///
141    /// # Panics
142    ///
143    /// Panics if the global runtime registry is poisoned.
144    pub fn observe_runtime(self, handle: &tokio::runtime::Handle) {
145        self::runtime::track_runtime(handle, &self.labels);
146    }
147}
148
149impl Default for Config {
150    fn default() -> Self {
151        Self::new()
152    }
153}
154
155/// Observe metrics for the current Tokio runtime.
156///
157/// This is a convenience function that uses default configuration.
158/// For more control, use [`Config`].
159///
160/// # Panics
161///
162/// Panics if called outside of a Tokio runtime context.
163///
164/// # Examples
165///
166/// ```no_run
167/// use opentelemetry_instrumentation_tokio;
168///
169/// # #[tokio::main]
170/// # async fn main() {
171/// opentelemetry_instrumentation_tokio::observe_current_runtime();
172/// # }
173/// ```
174pub fn observe_current_runtime() {
175    Config::default().observe_current_runtime();
176}
177
178/// Observe metrics for a specific Tokio runtime.
179///
180/// This is a convenience function that uses default configuration.
181/// For more control, use [`Config`].
182///
183/// # Examples
184///
185/// ```no_run
186/// use opentelemetry_instrumentation_tokio;
187///
188/// # #[tokio::main]
189/// # async fn main() {
190/// let handle = tokio::runtime::Handle::current();
191/// opentelemetry_instrumentation_tokio::observe_runtime(&handle);
192/// # }
193/// ```
194pub fn observe_runtime(handle: &tokio::runtime::Handle) {
195    Config::default().observe_runtime(handle);
196}