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}