README.md
1![Tracing — Structured, application-level diagnostics][splash]
2
3[splash]: https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/splash.svg
4
5# tracing
6
7Application-level tracing for Rust.
8
9[![Crates.io][crates-badge]][crates-url]
10[![Documentation][docs-badge]][docs-url]
11[![Documentation (master)][docs-master-badge]][docs-master-url]
12[![MIT licensed][mit-badge]][mit-url]
13[![Build Status][actions-badge]][actions-url]
14[![Discord chat][discord-badge]][discord-url]
15
16[Documentation][docs-url] | [Chat][discord-url]
17
18[crates-badge]: https://img.shields.io/crates/v/tracing.svg
19[crates-url]: https://crates.io/crates/tracing
20[docs-badge]: https://docs.rs/tracing/badge.svg
21[docs-url]: https://docs.rs/tracing
22[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
23[docs-master-url]: https://tracing-rs.netlify.com/tracing
24[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
25[mit-url]: LICENSE
26[actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg
27[actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI
28[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
29[discord-url]: https://discord.gg/EeF3cQw
30
31## Overview
32
33`tracing` is a framework for instrumenting Rust programs to collect
34structured, event-based diagnostic information.
35
36In asynchronous systems like Tokio, interpreting traditional log messages can
37often be quite challenging. Since individual tasks are multiplexed on the same
38thread, associated events and log lines are intermixed making it difficult to
39trace the logic flow. `tracing` expands upon logging-style diagnostics by
40allowing libraries and applications to record structured events with additional
41information about *temporality* and *causality* — unlike a log message, a span
42in `tracing` has a beginning and end time, may be entered and exited by the
43flow of execution, and may exist within a nested tree of similar spans. In
44addition, `tracing` spans are *structured*, with the ability to record typed
45data as well as textual messages.
46
47The `tracing` crate provides the APIs necessary for instrumenting libraries
48and applications to emit trace data.
49
50*Compiler support: [requires `rustc` 1.49+][msrv]*
51
52[msrv]: #supported-rust-versions
53
54## Usage
55
56(The examples below are borrowed from the `log` crate's yak-shaving
57[example](https://docs.rs/log/0.4.10/log/index.html#examples), modified to
58idiomatic `tracing`.)
59
60### In Applications
61
62In order to record trace events, executables have to use a `Subscriber`
63implementation compatible with `tracing`. A `Subscriber` implements a way of
64collecting trace data, such as by logging it to standard output. [`tracing_subscriber`](https://docs.rs/tracing-subscriber/)'s
65[`fmt` module](https://docs.rs/tracing-subscriber/0.3/tracing_subscriber/fmt/index.html) provides reasonable defaults.
66Additionally, `tracing-subscriber` is able to consume messages emitted by `log`-instrumented libraries and modules.
67
68The simplest way to use a subscriber is to call the `set_global_default` function.
69
70```rust
71use tracing::{info, Level};
72use tracing_subscriber::FmtSubscriber;
73
74fn main() {
75 // a builder for `FmtSubscriber`.
76 let subscriber = FmtSubscriber::builder()
77 // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
78 // will be written to stdout.
79 .with_max_level(Level::TRACE)
80 // completes the builder.
81 .finish();
82
83 tracing::subscriber::set_global_default(subscriber)
84 .expect("setting default subscriber failed");
85
86 let number_of_yaks = 3;
87 // this creates a new event, outside of any spans.
88 info!(number_of_yaks, "preparing to shave yaks");
89
90 let number_shaved = yak_shave::shave_all(number_of_yaks);
91 info!(
92 all_yaks_shaved = number_shaved == number_of_yaks,
93 "yak shaving completed."
94 );
95}
96```
97
98```toml
99[dependencies]
100tracing = "0.1"
101tracing-subscriber = "0.2.0"
102```
103
104This subscriber will be used as the default in all threads for the remainder of the duration
105of the program, similar to how loggers work in the `log` crate.
106
107In addition, you can locally override the default subscriber. For example:
108
109```rust
110use tracing::{info, Level};
111use tracing_subscriber::FmtSubscriber;
112
113fn main() {
114 let subscriber = tracing_subscriber::FmtSubscriber::builder()
115 // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
116 // will be written to stdout.
117 .with_max_level(Level::TRACE)
118 // builds the subscriber.
119 .finish();
120
121 tracing::subscriber::with_default(subscriber, || {
122 info!("This will be logged to stdout");
123 });
124 info!("This will _not_ be logged to stdout");
125}
126```
127
128This approach allows trace data to be collected by multiple subscribers
129within different contexts in the program. Note that the override only applies to the
130currently executing thread; other threads will not see the change from with_default.
131
132Any trace events generated outside the context of a subscriber will not be collected.
133
134Once a subscriber has been set, instrumentation points may be added to the
135executable using the `tracing` crate's macros.
136
137### In Libraries
138
139Libraries should only rely on the `tracing` crate and use the provided macros
140and types to collect whatever information might be useful to downstream consumers.
141
142```rust
143use std::{error::Error, io};
144use tracing::{debug, error, info, span, warn, Level};
145
146// the `#[tracing::instrument]` attribute creates and enters a span
147// every time the instrumented function is called. The span is named after the
148// the function or method. Paramaters passed to the function are recorded as fields.
149#[tracing::instrument]
150pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> {
151 // this creates an event at the DEBUG level with two fields:
152 // - `excitement`, with the key "excitement" and the value "yay!"
153 // - `message`, with the key "message" and the value "hello! I'm gonna shave a yak."
154 //
155 // unlike other fields, `message`'s shorthand initialization is just the string itself.
156 debug!(excitement = "yay!", "hello! I'm gonna shave a yak.");
157 if yak == 3 {
158 warn!("could not locate yak!");
159 // note that this is intended to demonstrate `tracing`'s features, not idiomatic
160 // error handling! in a library or application, you should consider returning
161 // a dedicated `YakError`. libraries like snafu or thiserror make this easy.
162 return Err(io::Error::new(io::ErrorKind::Other, "shaving yak failed!").into());
163 } else {
164 debug!("yak shaved successfully");
165 }
166 Ok(())
167}
168
169pub fn shave_all(yaks: usize) -> usize {
170 // Constructs a new span named "shaving_yaks" at the TRACE level,
171 // and a field whose key is "yaks". This is equivalent to writing:
172 //
173 // let span = span!(Level::TRACE, "shaving_yaks", yaks = yaks);
174 //
175 // local variables (`yaks`) can be used as field values
176 // without an assignment, similar to struct initializers.
177 let _span_ = span!(Level::TRACE, "shaving_yaks", yaks).entered();
178
179 info!("shaving yaks");
180
181 let mut yaks_shaved = 0;
182 for yak in 1..=yaks {
183 let res = shave(yak);
184 debug!(yak, shaved = res.is_ok());
185
186 if let Err(ref error) = res {
187 // Like spans, events can also use the field initialization shorthand.
188 // In this instance, `yak` is the field being initalized.
189 error!(yak, error = error.as_ref(), "failed to shave yak!");
190 } else {
191 yaks_shaved += 1;
192 }
193 debug!(yaks_shaved);
194 }
195
196 yaks_shaved
197}
198```
199
200```toml
201[dependencies]
202tracing = "0.1"
203```
204
205Note: Libraries should *NOT* call `set_global_default()`, as this will cause
206conflicts when executables try to set the default later.
207
208### In Asynchronous Code
209
210If you are instrumenting code that make use of
211[`std::future::Future`](https://doc.rust-lang.org/stable/std/future/trait.Future.html)
212or async/await, avoid using the `Span::enter` method. The following example
213_will not_ work:
214
215```rust
216async {
217 let _s = span.enter();
218 // ...
219}
220```
221```rust
222async {
223 let _s = tracing::span!(...).entered();
224 // ...
225}
226```
227
228The span guard `_s` will not exit until the future generated by the `async` block is complete.
229Since futures and spans can be entered and exited _multiple_ times without them completing,
230the span remains entered for as long as the future exists, rather than being entered only when
231it is polled, leading to very confusing and incorrect output.
232For more details, see [the documentation on closing spans](https://tracing.rs/tracing/span/index.html#closing-spans).
233
234There are two ways to instrument asynchronous code. The first is through the
235[`Future::instrument`](https://docs.rs/tracing/latest/tracing/trait.Instrument.html#method.instrument) combinator:
236
237```rust
238use tracing::Instrument;
239
240let my_future = async {
241 // ...
242};
243
244my_future
245 .instrument(tracing::info_span!("my_future"))
246 .await
247```
248
249`Future::instrument` attaches a span to the future, ensuring that the span's lifetime
250is as long as the future's.
251
252The second, and preferred, option is through the
253[`#[instrument]`](https://docs.rs/tracing/0.1.37/tracing/attr.instrument.html)
254attribute:
255
256```rust
257use tracing::{info, instrument};
258use tokio::{io::AsyncWriteExt, net::TcpStream};
259use std::io;
260
261#[instrument]
262async fn write(stream: &mut TcpStream) -> io::Result<usize> {
263 let result = stream.write(b"hello world\n").await;
264 info!("wrote to stream; success={:?}", result.is_ok());
265 result
266}
267```
268
269Under the hood, the `#[instrument]` macro performs the same explicit span
270attachment that `Future::instrument` does.
271
272### Concepts
273
274This crate provides macros for creating `Span`s and `Event`s, which represent
275periods of time and momentary events within the execution of a program,
276respectively.
277
278As a rule of thumb, _spans_ should be used to represent discrete units of work
279(e.g., a given request's lifetime in a server) or periods of time spent in a
280given context (e.g., time spent interacting with an instance of an external
281system, such as a database). In contrast, _events_ should be used to represent
282points in time within a span — a request returned with a given status code,
283_n_ new items were taken from a queue, and so on.
284
285`Span`s are constructed using the `span!` macro, and then _entered_
286to indicate that some code takes place within the context of that `Span`:
287
288```rust
289use tracing::{span, Level};
290
291// Construct a new span named "my span".
292let mut span = span!(Level::INFO, "my span");
293span.in_scope(|| {
294 // Any trace events in this closure or code called by it will occur within
295 // the span.
296});
297// Dropping the span will close it, indicating that it has ended.
298```
299
300The [`#[instrument]`](https://docs.rs/tracing/0.1.37/tracing/attr.instrument.html) attribute macro
301can reduce some of this boilerplate:
302
303```rust
304use tracing::{instrument};
305
306#[instrument]
307pub fn my_function(my_arg: usize) {
308 // This event will be recorded inside a span named `my_function` with the
309 // field `my_arg`.
310 tracing::info!("inside my_function!");
311 // ...
312}
313```
314
315The `Event` type represent an event that occurs instantaneously, and is
316essentially a `Span` that cannot be entered. They are created using the `event!`
317macro:
318
319```rust
320use tracing::{event, Level};
321
322event!(Level::INFO, "something has happened!");
323```
324
325Users of the [`log`] crate should note that `tracing` exposes a set of macros for
326creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and `error!`) which may
327be invoked with the same syntax as the similarly-named macros from the `log`
328crate. Often, the process of converting a project to use `tracing` can begin
329with a simple drop-in replacement.
330
331## Supported Rust Versions
332
333Tracing is built against the latest stable release. The minimum supported
334version is 1.42. The current Tracing version is not guaranteed to build on Rust
335versions earlier than the minimum supported version.
336
337Tracing follows the same compiler support policies as the rest of the Tokio
338project. The current stable Rust compiler and the three most recent minor
339versions before it will always be supported. For example, if the current stable
340compiler version is 1.45, the minimum supported version will not be increased
341past 1.42, three minor versions prior. Increasing the minimum supported compiler
342version is not considered a semver breaking change as long as doing so complies
343with this policy.
344
345## Ecosystem
346
347### Related Crates
348
349In addition to `tracing` and `tracing-core`, the [`tokio-rs/tracing`] repository
350contains several additional crates designed to be used with the `tracing` ecosystem.
351This includes a collection of `Subscriber` implementations, as well as utility
352and adapter crates to assist in writing `Subscriber`s and instrumenting
353applications.
354
355In particular, the following crates are likely to be of interest:
356
357- [`tracing-futures`] provides a compatibility layer with the `futures`
358 crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s.
359- [`tracing-subscriber`] provides `Subscriber` implementations and
360 utilities for working with `Subscriber`s. This includes a [`FmtSubscriber`]
361 `FmtSubscriber` for logging formatted trace data to stdout, with similar
362 filtering and formatting to the [`env_logger`] crate.
363- [`tracing-log`] provides a compatibility layer with the [`log`] crate,
364 allowing log messages to be recorded as `tracing` `Event`s within the
365 trace tree. This is useful when a project using `tracing` have
366 dependencies which use `log`. Note that if you're using
367 `tracing-subscriber`'s `FmtSubscriber`, you don't need to depend on
368 `tracing-log` directly.
369
370Additionally, there are also several third-party crates which are not
371maintained by the `tokio` project. These include:
372
373- [`tracing-timing`] implements inter-event timing metrics on top of `tracing`.
374 It provides a subscriber that records the time elapsed between pairs of
375 `tracing` events and generates histograms.
376- [`tracing-opentelemetry`] provides a subscriber for emitting traces to
377 [OpenTelemetry]-compatible distributed tracing systems.
378- [`tracing-honeycomb`] Provides a layer that reports traces spanning multiple machines to [honeycomb.io]. Backed by [`tracing-distributed`].
379- [`tracing-distributed`] Provides a generic implementation of a layer that reports traces spanning multiple machines to some backend.
380- [`tracing-actix`] provides `tracing` integration for the `actix` actor
381 framework.
382- [`tracing-gelf`] implements a subscriber for exporting traces in Greylog
383 GELF format.
384- [`tracing-coz`] provides integration with the [coz] causal profiler
385 (Linux-only).
386- [`test-log`] takes care of initializing `tracing` for tests, based on
387 environment variables with an `env_logger` compatible syntax.
388- [`tracing-unwrap`] provides convenience methods to report failed unwraps on `Result` or `Option` types to a `Subscriber`.
389- [`diesel-tracing`] provides integration with [`diesel`] database connections.
390- [`tracing-tracy`] provides a way to collect [Tracy] profiles in instrumented
391 applications.
392- [`tracing-elastic-apm`] provides a layer for reporting traces to [Elastic APM].
393- [`tracing-etw`] provides a layer for emitting Windows [ETW] events.
394- [`tracing-fluent-assertions`] provides a fluent assertions-style testing
395 framework for validating the behavior of `tracing` spans.
396- [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry].
397- [`tracing-loki`] provides a layer for shipping logs to [Grafana Loki].
398- [`tracing-logfmt`] provides a layer that formats events and spans into the logfmt format.
399
400If you're the maintainer of a `tracing` ecosystem crate not listed above,
401please let us know! We'd love to add your project to the list!
402
403[`tracing-timing`]: https://crates.io/crates/tracing-timing
404[`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry
405[OpenTelemetry]: https://opentelemetry.io/
406[`tracing-honeycomb`]: https://crates.io/crates/tracing-honeycomb
407[`tracing-distributed`]: https://crates.io/crates/tracing-distributed
408[honeycomb.io]: https://www.honeycomb.io/
409[`tracing-actix`]: https://crates.io/crates/tracing-actix
410[`tracing-gelf`]: https://crates.io/crates/tracing-gelf
411[`tracing-coz`]: https://crates.io/crates/tracing-coz
412[coz]: https://github.com/plasma-umass/coz
413[`test-log`]: https://crates.io/crates/test-log
414[`tracing-unwrap`]: https://docs.rs/tracing-unwrap
415[`diesel`]: https://crates.io/crates/diesel
416[`diesel-tracing`]: https://crates.io/crates/diesel-tracing
417[`tracing-tracy`]: https://crates.io/crates/tracing-tracy
418[Tracy]: https://github.com/wolfpld/tracy
419[`tracing-elastic-apm`]: https://crates.io/crates/tracing-elastic-apm
420[Elastic APM]: https://www.elastic.co/apm
421[`tracing-etw`]: https://github.com/microsoft/tracing-etw
422[ETW]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing
423[`tracing-fluent-assertions`]: https://crates.io/crates/tracing-fluent-assertions
424[`sentry-tracing`]: https://crates.io/crates/sentry-tracing
425[Sentry]: https://sentry.io/welcome/
426[`tracing-loki`]: https://crates.io/crates/tracing-loki
427[Grafana Loki]: https://grafana.com/oss/loki/
428[`tracing-logfmt`]: https://crates.io/crates/tracing-logfmt
429
430**Note:** that some of the ecosystem crates are currently unreleased and
431undergoing active development. They may be less stable than `tracing` and
432`tracing-core`.
433
434[`log`]: https://docs.rs/log/0.4.6/log/
435[`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing
436[`tracing-futures`]: https://github.com/tokio-rs/tracing/tree/master/tracing-futures
437[`tracing-subscriber`]: https://github.com/tokio-rs/tracing/tree/master/tracing-subscriber
438[`tracing-log`]: https://github.com/tokio-rs/tracing/tree/master/tracing-log
439[`env_logger`]: https://crates.io/crates/env_logger
440[`FmtSubscriber`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/struct.Subscriber.html
441[`examples`]: https://github.com/tokio-rs/tracing/tree/master/examples
442
443## Supported Rust Versions
444
445Tracing is built against the latest stable release. The minimum supported
446version is 1.49. The current Tracing version is not guaranteed to build on Rust
447versions earlier than the minimum supported version.
448
449Tracing follows the same compiler support policies as the rest of the Tokio
450project. The current stable Rust compiler and the three most recent minor
451versions before it will always be supported. For example, if the current stable
452compiler version is 1.45, the minimum supported version will not be increased
453past 1.42, three minor versions prior. Increasing the minimum supported compiler
454version is not considered a semver breaking change as long as doing so complies
455with this policy.
456
457## License
458
459This project is licensed under the [MIT license](LICENSE).
460
461### Contribution
462
463Unless you explicitly state otherwise, any contribution intentionally submitted
464for inclusion in Tokio by you, shall be licensed as MIT, without any additional
465terms or conditions.
466