await_tree/
lib.rs

1// Copyright 2023 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Generate accurate and informative tree dumps of asynchronous tasks.
16//!
17//! # Example
18//!
19//! Below is a basic example of how to trace asynchronous tasks with the global registry of the
20//! `await-tree` crate.
21//!
22//! ```rust
23//! # use std::time::Duration;
24//! # use tokio::time::sleep;
25//! # use await_tree::{InstrumentAwait, Registry, span};
26//! # use futures::future::join;
27//! #
28//! # async fn work() { futures::future::pending::<()>().await }
29//! #
30//! async fn bar(i: i32) {
31//!     // `&'static str` span
32//!     baz(i).instrument_await("baz in bar").await
33//! }
34//!
35//! async fn baz(i: i32) {
36//!     // runtime `String` span is also supported
37//!     work().instrument_await(span!("working in baz {i}")).await
38//! }
39//!
40//! async fn foo() {
41//!     // spans of joined futures will be siblings in the tree
42//!     join(
43//!         bar(3).instrument_await("bar"),
44//!         baz(2).instrument_await("baz"),
45//!     )
46//!     .await;
47//! }
48//!
49//! # #[tokio::main]
50//! # async fn main() {
51//! // Init the global registry to start tracing the tasks.
52//! await_tree::init_global_registry(Default::default());
53//! // Spawn a task with root span "foo" and key "foo".
54//! await_tree::spawn("foo", "foo", foo());
55//! // Let the tasks run for a while.
56//! sleep(Duration::from_secs(1)).await;
57//! // Get the tree of the task with key "foo".
58//! let tree = Registry::current().get("foo").unwrap();
59//!
60//! // foo [1.006s]
61//! //   bar [1.006s]
62//! //     baz in bar [1.006s]
63//! //       working in baz 3 [1.006s]
64//! //   baz [1.006s]
65//! //     working in baz 2 [1.006s]
66//! println!("{tree}");
67//! # }
68//! ```
69
70#![forbid(missing_docs)]
71
72use std::future::Future;
73
74mod context;
75mod future;
76mod global;
77mod obj_utils;
78mod registry;
79mod root;
80mod span;
81#[cfg(feature = "tokio")]
82mod spawn;
83
84pub use context::{current_tree, Tree};
85pub use future::Instrumented;
86pub use global::init_global_registry;
87pub use registry::{AnyKey, Config, ConfigBuilder, ConfigBuilderError, Key, Registry};
88pub use root::TreeRoot;
89pub use span::{Span, SpanExt};
90#[cfg(feature = "tokio")]
91pub use spawn::{spawn, spawn_anonymous};
92
93#[doc(hidden)]
94pub mod __private {
95    pub use crate::span::fmt_span;
96}
97
98/// Attach spans to a future to be traced in the await-tree.
99pub trait InstrumentAwait: Future + Sized {
100    /// Instrument the future with a span.
101    fn instrument_await(self, span: impl Into<Span>) -> Instrumented<Self> {
102        Instrumented::new(self, span.into())
103    }
104}
105impl<F> InstrumentAwait for F where F: Future {}
106
107#[cfg(test)]
108mod tests;