Skip to main content

tokio_metrics/
lib.rs

1#![warn(
2    clippy::arithmetic_side_effects,
3    missing_debug_implementations,
4    missing_docs,
5    rust_2018_idioms,
6    unreachable_pub
7)]
8#![cfg_attr(docsrs, feature(doc_cfg))]
9#![cfg_attr(docsrs, allow(unused_attributes))]
10
11//! Monitor key metrics of tokio tasks and runtimes.
12//!
13//! ### Monitoring task metrics
14//! [Monitor][TaskMonitor] key [metrics][TaskMetrics] of tokio tasks.
15//!
16//! In the below example, a [`TaskMonitor`] is [constructed][TaskMonitor::new] and used to
17//! [instrument][TaskMonitor::instrument] three worker tasks; meanwhile, a fourth task
18//! prints [metrics][TaskMetrics] in 500ms [intervals][TaskMonitor::intervals]:
19//! ```
20//! use std::time::Duration;
21//!
22//! #[tokio::main]
23//! async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
24//!     // construct a metrics taskmonitor
25//!     let metrics_monitor = tokio_metrics::TaskMonitor::new();
26//!
27//!     // print task metrics every 500ms
28//!     {
29//!         let metrics_monitor = metrics_monitor.clone();
30//!         tokio::spawn(async move {
31//!             for interval in metrics_monitor.intervals() {
32//!                 // pretty-print the metric interval
33//!                 println!("{:?}", interval);
34//!                 // wait 500ms
35//!                 tokio::time::sleep(Duration::from_millis(500)).await;
36//!             }
37//!         });
38//!     }
39//!
40//!     // instrument some tasks and await them
41//!     // note that the same taskmonitor can be used for multiple tasks
42//!     tokio::join![
43//!         metrics_monitor.instrument(do_work()),
44//!         metrics_monitor.instrument(do_work()),
45//!         metrics_monitor.instrument(do_work())
46//!     ];
47//!
48//!     Ok(())
49//! }
50//!
51//! async fn do_work() {
52//!     for _ in 0..25 {
53//!         tokio::task::yield_now().await;
54//!         tokio::time::sleep(Duration::from_millis(100)).await;
55//!     }
56//! }
57//! ```
58
59#![cfg_attr(
60    feature = "rt",
61    doc = r##"
62### Monitoring runtime metrics
63[Monitor][RuntimeMonitor] key [metrics][RuntimeMetrics] of a tokio runtime.
64**This functionality requires crate feature `rt` and some metrics require `tokio_unstable`.**
65
66In the below example, a [`RuntimeMonitor`] is [constructed][RuntimeMonitor::new] and
67three tasks are spawned and awaited; meanwhile, a fourth task prints [metrics][RuntimeMetrics]
68in 500ms [intervals][RuntimeMonitor::intervals]:
69```
70use std::time::Duration;
71
72#[tokio::main]
73async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
74    let handle = tokio::runtime::Handle::current();
75    // construct the runtime metrics monitor
76    let runtime_monitor = tokio_metrics::RuntimeMonitor::new(&handle);
77
78    // print runtime metrics every 500ms
79    {
80        tokio::spawn(async move {
81            for interval in runtime_monitor.intervals() {
82                // pretty-print the metric interval
83                println!("{:?}", interval);
84                // wait 500ms
85                tokio::time::sleep(Duration::from_millis(500)).await;
86            }
87        });
88    }
89
90    // await some tasks
91    tokio::join![
92        do_work(),
93        do_work(),
94        do_work(),
95    ];
96
97    Ok(())
98}
99
100async fn do_work() {
101    for _ in 0..25 {
102        tokio::task::yield_now().await;
103        tokio::time::sleep(Duration::from_millis(100)).await;
104    }
105}
106```
107"##
108)]
109
110//! ### Monitoring and publishing metrics
111//!
112//! If the `metrics-rs-integration` feature is additionally enabled, this crate allows
113//! publishing metrics externally via [metrics-rs](metrics) exporters.
114//!
115//! For example, you can use [metrics_exporter_prometheus] to make metrics visible
116//! to [Prometheus]. You can see the [metrics_exporter_prometheus] and [metrics-rs](metrics)
117//! docs for guidance on configuring exporters.
118//!
119//! The published metrics are the same as the fields and methods of
120#![cfg_attr(feature = "rt", doc = "[RuntimeMetrics] and")]
121//! [TaskMetrics], but with a "tokio_" prefix added, for example
122#![cfg_attr(feature = "rt", doc = "`tokio_workers_count` and")]
123//! `tokio_instrumented_count`.
124//!
125//! [metrics_exporter_prometheus]: https://docs.rs/metrics_exporter_prometheus
126#![cfg_attr(feature = "rt", doc = "[RuntimeMetrics]: crate::RuntimeMetrics")]
127//! [Prometheus]: https://prometheus.io
128//! [TaskMetrics]: crate::TaskMetrics
129//!
130//! This example exports [Prometheus] metrics by listening on a local Unix socket
131//! called `prometheus.sock`, which you can access for debugging by
132//! `curl --unix-socket prometheus.sock localhost`.
133//!
134//! ```
135//! use std::time::Duration;
136//!
137//! #[tokio::main]
138//! async fn main() {
139//!     metrics_exporter_prometheus::PrometheusBuilder::new()
140//!         .with_http_uds_listener("prometheus.sock")
141//!         .install()
142//!         .unwrap();
143#![cfg_attr(
144    all(feature = "rt", feature = "metrics-rs-integration"),
145    doc = r##"
146    // This line launches the runtime reporter that monitors the Tokio runtime and exports the metrics.
147    tokio::task::spawn(
148        tokio_metrics::RuntimeMetricsReporterBuilder::default().describe_and_run(),
149    );
150"##
151)]
152//!     let monitor = tokio_metrics::TaskMonitor::new();
153#![cfg_attr(
154    all(feature = "rt", feature = "metrics-rs-integration"),
155    doc = r##"
156    use metrics::Key;
157    // This line launches the task reporter that monitors Tokio tasks and exports the metrics.
158    tokio::task::spawn(
159        tokio_metrics::TaskMetricsReporterBuilder::new(|name| {
160            let name = name.replacen("tokio_", "my_task_", 1);
161            Key::from_parts(name, &[("application", "my_app")])
162        })
163        .describe_and_run(monitor.clone()),
164    );
165"##
166)]
167//!     // Run some code.
168//!     tokio::task::spawn(monitor.instrument(async move {
169//!         for _ in 0..1000 {
170//!             tokio::time::sleep(Duration::from_millis(10)).await;
171//!         }
172//!     }))
173//!     .await
174//!     .unwrap();
175//! }
176//! ```
177
178macro_rules! cfg_rt {
179    ($($item:item)*) => {
180        $(
181            #[cfg(feature = "rt")]
182            #[cfg_attr(docsrs, doc(cfg(feature = "rt")))]
183            $item
184        )*
185    };
186}
187
188cfg_rt! {
189    mod runtime;
190    pub use runtime::{
191        RuntimeIntervals,
192        RuntimeMetrics,
193        RuntimeMonitor,
194    };
195}
196
197#[cfg(all(feature = "rt", feature = "metrics-rs-integration"))]
198#[cfg_attr(
199    docsrs,
200    doc(cfg(all(feature = "rt", feature = "metrics-rs-integration")))
201)]
202pub use runtime::metrics_rs_integration::{RuntimeMetricsReporter, RuntimeMetricsReporterBuilder};
203
204mod derived_metrics;
205#[cfg(feature = "metrics-rs-integration")]
206mod metrics_rs;
207mod task;
208
209#[cfg(feature = "metrics-rs-integration")]
210#[cfg_attr(docsrs, doc(cfg(feature = "metrics-rs-integration")))]
211pub use task::metrics_rs_integration::{TaskMetricsReporter, TaskMetricsReporterBuilder};
212pub use task::{
213    Instrumented, TaskIntervals, TaskMetrics, TaskMonitor, TaskMonitorCore, TaskMonitorCoreBuilder,
214};