tokio_metrics/
lib.rs

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