tokio_trace/lib.rs
1#![doc(html_root_url = "https://docs.rs/tokio-trace/0.1.0")]
2#![deny(missing_debug_implementations, missing_docs, unreachable_pub)]
3#![cfg_attr(test, deny(warnings))]
4//! A scoped, structured logging and diagnostics system.
5//!
6//! # Overview
7//!
8//! `tokio-trace` is a framework for instrumenting Rust programs to collect
9//! structured, event-based diagnostic information.
10//!
11//! In asynchronous systems like Tokio, interpreting traditional log messages can
12//! often be quite challenging. Since individual tasks are multiplexed on the same
13//! thread, associated events and log lines are intermixed making it difficult to
14//! trace the logic flow. `tokio-trace` expands upon logging-style diagnostics by
15//! allowing libraries and applications to record structured events with additional
16//! information about *temporality* and *causality* — unlike a log message, a span
17//! in `tokio-trace` has a beginning and end time, may be entered and exited by the
18//! flow of execution, and may exist within a nested tree of similar spans. In
19//! addition, `tokio-trace` spans are *structured*, with the ability to record typed
20//! data as well as textual messages.
21//!
22//! The `tokio-trace` crate provides the APIs necessary for instrumenting libraries
23//! and applications to emit trace data.
24//!
25//! # Core Concepts
26//!
27//! The core of `tokio-trace`'s API is composed of `Event`s, `Span`s, and
28//! `Subscriber`s. We'll cover these in turn.
29//!
30//! ## `Span`s
31//!
32//! A [`Span`] represents a _period of time_ during which a program was executing
33//! in some context. A thread of execution is said to _enter_ a span when it
34//! begins executing in that context, and to _exit_ the span when switching to
35//! another context. The span in which a thread is currently executing is
36//! referred to as the _current_ span.
37//!
38//! For example:
39//! ```
40//! #[macro_use]
41//! extern crate tokio_trace;
42//!
43//! use tokio_trace::Level;
44//!
45//! # fn main() {
46//! span!(Level::TRACE, "my_span").enter(|| {
47//! // perform some work in the context of `my_span`...
48//! });
49//! # }
50//!```
51//!
52//! Spans form a tree structure — unless it is a root span, all spans have a
53//! _parent_, and may have one or more _children_. When a new span is created,
54//! the current span becomes the new span's parent. The total execution time of
55//! a span consists of the time spent in that span and in the entire subtree
56//! represented by its children. Thus, a parent span always lasts for at least
57//! as long as the longest-executing span in its subtree.
58//!
59//! ```
60//! # #[macro_use] extern crate tokio_trace;
61//! # use tokio_trace::Level;
62//! # fn main() {
63//! // this span is considered the "root" of a new trace tree:
64//! span!(Level::INFO, "root").enter(|| {
65//! // since we are now inside "root", this span is considered a child
66//! // of "root":
67//! span!(Level::DEBUG, "outer_child").enter(|| {
68//! // this span is a child of "outer_child", which is in turn a
69//! // child of "root":
70//! span!(Level::TRACE, "inner_child").enter(|| {
71//! // and so on...
72//! });
73//! });
74//! });
75//! # }
76//!```
77//!
78//! In addition, data may be associated with spans. A span may have _fields_ —
79//! a set of key-value pairs describing the state of the program during that
80//! span; an optional name, and metadata describing the source code location
81//! where the span was originally entered.
82//! ```
83//! # #[macro_use] extern crate tokio_trace;
84//! # use tokio_trace::Level;
85//! # fn main() {
86//! // construct a new span with three fields:
87//! // - "foo", with a value of 42,
88//! // - "bar", with the value "false"
89//! // - "baz", with no initial value
90//! let my_span = span!(Level::INFO, "my_span", foo = 42, bar = false, baz);
91//!
92//! // record a value for the field "baz" declared above:
93//! my_span.record("baz", &"hello world");
94//! # }
95//!```
96//!
97//! ### When to use spans
98//!
99//! As a rule of thumb, spans should be used to represent discrete units of work
100//! (e.g., a given request's lifetime in a server) or periods of time spent in a
101//! given context (e.g., time spent interacting with an instance of an external
102//! system, such as a database).
103//!
104//! Which scopes in a program correspond to new spans depend somewhat on user
105//! intent. For example, consider the case of a loop in a program. Should we
106//! construct one span and perform the entire loop inside of that span, like:
107//! ```rust
108//! # #[macro_use] extern crate tokio_trace;
109//! # use tokio_trace::Level;
110//! # fn main() {
111//! # let n = 1;
112//! span!(Level::TRACE, "my loop").enter(|| {
113//! for i in 0..n {
114//! # let _ = i;
115//! // ...
116//! }
117//! })
118//! # }
119//! ```
120//! Or, should we create a new span for each iteration of the loop, as in:
121//! ```rust
122//! # #[macro_use] extern crate tokio_trace;
123//! # use tokio_trace::Level;
124//! # fn main() {
125//! # let n = 1u64;
126//! for i in 0..n {
127//! # let _ = i;
128//! span!(Level::TRACE, "my loop", iteration = i).enter(|| {
129//! // ...
130//! })
131//! }
132//! # }
133//! ```
134//!
135//! Depending on the circumstances, we might want to do either, or both. For
136//! example, if we want to know how long was spent in the loop overall, we would
137//! create a single span around the entire loop; whereas if we wanted to know how
138//! much time was spent in each individual iteration, we would enter a new span
139//! on every iteration.
140//!
141//! ## Events
142//!
143//! An [`Event`] represents a _point_ in time. It signifies something that
144//! happened while the trace was executing. `Event`s are comparable to the log
145//! records emitted by unstructured logging code, but unlike a typical log line,
146//! an `Event` may occur within the context of a `Span`. Like a `Span`, it
147//! may have fields, and implicitly inherits any of the fields present on its
148//! parent span.
149//!
150//! For example:
151//! ```
152//! # #[macro_use] extern crate tokio_trace;
153//! # use tokio_trace::Level;
154//! # fn main() {
155//! // records an event outside of any span context:
156//! event!(Level::INFO, "something happened");
157//!
158//! span!(Level::INFO, "my_span").enter(|| {
159//! // records an event within "my_span".
160//! event!(Level::DEBUG, "something happened inside my_span");
161//! });
162//! # }
163//!```
164//!
165//! Essentially, `Event`s exist to bridge the gap between traditional
166//! unstructured logging and span-based tracing. Similar to log records, they
167//! may be recorded at a number of levels, and can have unstructured,
168//! human-readable messages; however, they also carry key-value data and exist
169//! within the context of the tree of spans that comprise a trace. Thus,
170//! individual log record-like events can be pinpointed not only in time, but
171//! in the logical execution flow of the system.
172//!
173//! Events are represented as a special case of spans — they are created, they
174//! may have fields added, and then they close immediately, without being
175//! entered.
176//!
177//! In general, events should be used to represent points in time _within_ a
178//! span — a request returned with a given status code, _n_ new items were
179//! taken from a queue, and so on.
180//!
181//! ## `Subscriber`s
182//!
183//! As `Span`s and `Event`s occur, they are recorded or aggregated by
184//! implementations of the [`Subscriber`] trait. `Subscriber`s are notified
185//! when an `Event` takes place and when a `Span` is entered or exited. These
186//! notifications are represented by the following `Subscriber` trait methods:
187//! + [`observe_event`], called when an `Event` takes place,
188//! + [`enter`], called when execution enters a `Span`,
189//! + [`exit`], called when execution exits a `Span`
190//!
191//! In addition, subscribers may implement the [`enabled`] function to _filter_
192//! the notifications they receive based on [metadata] describing each `Span`
193//! or `Event`. If a call to `Subscriber::enabled` returns `false` for a given
194//! set of metadata, that `Subscriber` will *not* be notified about the
195//! corresponding `Span` or `Event`. For performance reasons, if no currently
196//! active subscribers express interest in a given set of metadata by returning
197//! `true`, then the corresponding `Span` or `Event` will never be constructed.
198//!
199//! # Usage
200//!
201//! First, add this to your `Cargo.toml`:
202//!
203//! ```toml
204//! [dependencies]
205//! tokio-trace = "0.1"
206//! ```
207//!
208//! Next, add this to your crate:
209//!
210//! ```rust
211//! #[macro_use]
212//! extern crate tokio_trace;
213//! # fn main() {}
214//! ```
215//!
216//! `Span`s are constructed using the `span!` macro, and then _entered_
217//! to indicate that some code takes place within the context of that `Span`:
218//!
219//! ```rust
220//! # #[macro_use]
221//! # extern crate tokio_trace;
222//! # use tokio_trace::Level;
223//! # fn main() {
224//! // Construct a new span named "my span" with trace log level.
225//! let span = span!(Level::TRACE, "my span");
226//! span.enter(|| {
227//! // Any trace events in this closure or code called by it will occur within
228//! // the span.
229//! });
230//! // Dropping the span will close it, indicating that it has ended.
231//! # }
232//! ```
233//!
234//! `Event`s are created using the `event!` macro, and are recorded when the
235//! event is dropped:
236//!
237//! ```rust
238//! # #[macro_use]
239//! # extern crate tokio_trace;
240//! # fn main() {
241//! use tokio_trace::Level;
242//! event!(Level::INFO, "something has happened!");
243//! # }
244//! ```
245//!
246//! Users of the [`log`] crate should note that `tokio-trace` exposes a set of
247//! macros for creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and
248//! `error!`) which may be invoked with the same syntax as the similarly-named
249//! macros from the `log` crate. Often, the process of converting a project to
250//! use `tokio-trace` can begin with a simple drop-in replacement.
251//!
252//! Let's consider the `log` crate's yak-shaving example:
253//!
254//! ```rust
255//! #[macro_use]
256//! extern crate tokio_trace;
257//! use tokio_trace::{field, Level};
258//! # #[derive(Debug)] pub struct Yak(String);
259//! # impl Yak { fn shave(&mut self, _: u32) {} }
260//! # fn find_a_razor() -> Result<u32, u32> { Ok(1) }
261//! # fn main() {
262//! pub fn shave_the_yak(yak: &mut Yak) {
263//! // Create a new span for this invocation of `shave_the_yak`, annotated
264//! // with the yak being shaved as a *field* on the span.
265//! span!(Level::TRACE, "shave_the_yak", yak = field::debug(&yak)).enter(|| {
266//! // Since the span is annotated with the yak, it is part of the context
267//! // for everything happening inside the span. Therefore, we don't need
268//! // to add it to the message for this event, as the `log` crate does.
269//! info!(target: "yak_events", "Commencing yak shaving");
270//!
271//! loop {
272//! match find_a_razor() {
273//! Ok(razor) => {
274//! // We can add the razor as a field rather than formatting it
275//! // as part of the message, allowing subscribers to consume it
276//! // in a more structured manner:
277//! info!({ razor = field::display(razor) }, "Razor located");
278//! yak.shave(razor);
279//! break;
280//! }
281//! Err(err) => {
282//! // However, we can also create events with formatted messages,
283//! // just as we would for log records.
284//! warn!("Unable to locate a razor: {}, retrying", err);
285//! }
286//! }
287//! }
288//! })
289//! }
290//! # }
291//! ```
292//!
293//! You can find examples showing how to use this crate in the examples
294//! directory.
295//!
296//! ## In libraries
297//!
298//! Libraries should link only to the `tokio-trace` crate, and use the provided
299//! macros to record whatever information will be useful to downstream
300//! consumers.
301//!
302//! ## In executables
303//!
304//! In order to record trace events, executables have to use a `Subscriber`
305//! implementation compatible with `tokio-trace`. A `Subscriber` implements a
306//! way of collecting trace data, such as by logging it to standard output.
307//!
308//! Unlike the `log` crate, `tokio-trace` does *not* use a global `Subscriber`
309//! which is initialized once. Instead, it follows the `tokio` pattern of
310//! executing code in a context. For example:
311//!
312//! ```rust
313//! #[macro_use]
314//! extern crate tokio_trace;
315//! # pub struct FooSubscriber;
316//! # use tokio_trace::{span::{Id, Attributes, Record}, Metadata};
317//! # impl tokio_trace::Subscriber for FooSubscriber {
318//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
319//! # fn record(&self, _: &Id, _: &Record) {}
320//! # fn event(&self, _: &tokio_trace::Event) {}
321//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
322//! # fn enabled(&self, _: &Metadata) -> bool { false }
323//! # fn enter(&self, _: &Id) {}
324//! # fn exit(&self, _: &Id) {}
325//! # }
326//! # impl FooSubscriber {
327//! # fn new() -> Self { FooSubscriber }
328//! # }
329//! # fn main() {
330//!
331//! let my_subscriber = FooSubscriber::new();
332//!
333//! tokio_trace::subscriber::with_default(my_subscriber, || {
334//! // Any trace events generated in this closure or by functions it calls
335//! // will be collected by `my_subscriber`.
336//! })
337//! # }
338//! ```
339//!
340//! This approach allows trace data to be collected by multiple subscribers
341//! within different contexts in the program. Alternatively, a single subscriber
342//! may be constructed by the `main` function and all subsequent code executed
343//! with that subscriber as the default. Any trace events generated outside the
344//! context of a subscriber will not be collected.
345//!
346//! The executable itself may use the `tokio-trace` crate to instrument itself
347//! as well.
348//!
349//! The [`tokio-trace-nursery`] repository contains less stable crates designed
350//! to be used with the `tokio-trace` ecosystem. It includes a collection of
351//! `Subscriber` implementations, as well as utility and adapter crates.
352//!
353//! In particular, the following `tokio-trace-nursery` crates are likely to be
354//! of interest:
355//!
356//! - [`tokio-trace-futures`] provides a compatibility layer with the `futures`
357//! crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s.
358//! - [`tokio-trace-fmt`] provides a `Subscriber` implementation for
359//! logging formatted trace data to stdout, with similar filtering and
360//! formatting to the `env-logger` crate.
361//! - [`tokio-trace-log`] provides a compatibility layer with the `log` crate,
362//! allowing log `Record`s to be recorded as `tokio-trace` `Event`s within the
363//! trace tree. This is useful when a project using `tokio-trace` have
364//! dependencies which use `log`.
365//!
366//!
367//! ## Crate Feature Flags
368//!
369//! The following crate feature flags are available:
370//!
371//! * A set of features controlling the [static verbosity level].
372//! * `log` causes trace instrumentation points to emit [`log`] records as well
373//! as trace events. This is inteded for use in libraries whose users may be
374//! using either `tokio-trace` or `log`.
375//!
376//! ```toml
377//! [dependencies]
378//! tokio-trace = { version = "0.1", features = ["log"] }
379//! ```
380//!
381//! [`log`]: https://docs.rs/log/0.4.6/log/
382//! [`Span`]: span/struct.Span
383//! [`Event`]: struct.Event.html
384//! [`Subscriber`]: subscriber/trait.Subscriber.html
385//! [`observe_event`]: subscriber/trait.Subscriber.html#tymethod.observe_event
386//! [`enter`]: subscriber/trait.Subscriber.html#tymethod.enter
387//! [`exit`]: subscriber/trait.Subscriber.html#tymethod.exit
388//! [`enabled`]: subscriber/trait.Subscriber.html#tymethod.enabled
389//! [metadata]: struct.Metadata.html
390//! [`tokio-trace-nursery`]: https://github.com/tokio-rs/tokio-trace-nursery
391//! [`tokio-trace-futures`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-futures
392//! [`tokio-trace-fmt`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-fmt
393//! [`tokio-trace-log`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-log
394//! [static verbosity level]: level_filters/index.html#compile-time-filters
395#[macro_use]
396extern crate cfg_if;
397extern crate tokio_trace_core;
398
399#[cfg(feature = "log")]
400#[doc(hidden)]
401pub extern crate log;
402
403// Somehow this `use` statement is necessary for us to re-export the `core`
404// macros on Rust 1.26.0. I'm not sure how this makes it work, but it does.
405#[allow(unused_imports)]
406#[doc(hidden)]
407use tokio_trace_core::*;
408
409pub use self::{
410 dispatcher::Dispatch,
411 event::Event,
412 field::Value,
413 span::Span,
414 subscriber::Subscriber,
415 tokio_trace_core::{dispatcher, event, Level, Metadata},
416};
417
418#[doc(hidden)]
419pub use self::{
420 span::Id,
421 tokio_trace_core::{
422 callsite::{self, Callsite},
423 metadata,
424 },
425};
426
427#[macro_use]
428mod macros;
429
430pub mod field;
431pub mod level_filters;
432pub mod span;
433pub mod subscriber;
434
435mod sealed {
436 pub trait Sealed {}
437}