@jonhoo recorded a great resource about the crate's inner workings and included practical suggestions about patterns to follow when annotating one's code. I added the link to the YouTube video under the "Talks" header as that seemed appropriate enough.
		
			
				
	
	
		
			504 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			504 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
![Tracing — Structured, application-level diagnostics][splash]
 | 
						|
 | 
						|
[splash]: https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/splash.svg
 | 
						|
 | 
						|
[![Crates.io][crates-badge]][crates-url]
 | 
						|
[![Documentation][docs-badge]][docs-url]
 | 
						|
[![Documentation (master)][docs-master-badge]][docs-master-url]
 | 
						|
[![MIT licensed][mit-badge]][mit-url]
 | 
						|
[![Build Status][actions-badge]][actions-url]
 | 
						|
[![Discord chat][discord-badge]][discord-url]
 | 
						|
 | 
						|
[crates-badge]: https://img.shields.io/crates/v/tracing.svg
 | 
						|
[crates-url]: https://crates.io/crates/tracing
 | 
						|
[docs-badge]: https://docs.rs/tracing/badge.svg
 | 
						|
[docs-url]: https://docs.rs/tracing
 | 
						|
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
 | 
						|
[docs-master-url]: https://tracing.rs
 | 
						|
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
 | 
						|
[mit-url]: LICENSE
 | 
						|
[actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg
 | 
						|
[actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI
 | 
						|
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
 | 
						|
[discord-url]: https://discord.gg/EeF3cQw
 | 
						|
 | 
						|
[Website](https://tokio.rs) |
 | 
						|
[Chat](https://discord.gg/EeF3cQw) | [Documentation (master branch)](https://tracing-rs.netlify.com/)
 | 
						|
 | 
						|
# The master branch is the pre-release, development version of `tracing`. Please see the [v0.1.x](https://github.com/tokio-rs/tracing/tree/v0.1.x) branch for the versions of `tracing` released to crates.io.
 | 
						|
 | 
						|
## Overview
 | 
						|
 | 
						|
`tracing` is a framework for instrumenting Rust programs to collect
 | 
						|
structured, event-based diagnostic information. `tracing` is maintained by the
 | 
						|
Tokio project, but does _not_ require the `tokio` runtime to be used.
 | 
						|
 | 
						|
## Usage
 | 
						|
 | 
						|
### In Applications
 | 
						|
 | 
						|
In order to record trace events, executables have to use a collector
 | 
						|
implementation compatible with `tracing`. A collector implements a way of
 | 
						|
collecting trace data, such as by logging it to standard output.
 | 
						|
[`tracing-subscriber`][tracing-subscriber-docs]'s [`fmt` module][fmt] provides
 | 
						|
a collector for logging traces with reasonable defaults. Additionally,
 | 
						|
`tracing-subscriber` is able to consume messages emitted by `log`-instrumented
 | 
						|
libraries and modules.
 | 
						|
 | 
						|
To use `tracing-subscriber`, add the following to your `Cargo.toml`:
 | 
						|
 | 
						|
```toml
 | 
						|
[dependencies]
 | 
						|
tracing = "0.1"
 | 
						|
tracing-subscriber = "0.3"
 | 
						|
```
 | 
						|
 | 
						|
Then create and install a collector, for example using [`init()`]:
 | 
						|
 | 
						|
```rust
 | 
						|
use tracing::info;
 | 
						|
use tracing_subscriber;
 | 
						|
 | 
						|
fn main() {
 | 
						|
    // install global collector configured based on RUST_LOG env var.
 | 
						|
    tracing_subscriber::fmt::init();
 | 
						|
 | 
						|
    let number_of_yaks = 3;
 | 
						|
    // this creates a new event, outside of any spans.
 | 
						|
    info!(number_of_yaks, "preparing to shave yaks");
 | 
						|
 | 
						|
    let number_shaved = yak_shave::shave_all(number_of_yaks);
 | 
						|
    info!(
 | 
						|
        all_yaks_shaved = number_shaved == number_of_yaks,
 | 
						|
        "yak shaving completed."
 | 
						|
    );
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Using `init()` calls [`set_global_default()`] so this collector will be used
 | 
						|
as the default in all threads for the remainder of the duration of the
 | 
						|
program, similar to how loggers work in the `log` crate.
 | 
						|
 | 
						|
[tracing-subscriber-docs]: https://docs.rs/tracing-subscriber/
 | 
						|
[fmt]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/index.html
 | 
						|
[`set_global_default`]: https://docs.rs/tracing/latest/tracing/subscriber/fn.set_global_default.html
 | 
						|
 | 
						|
 | 
						|
For more control, a collector can be built in stages and not set globally,
 | 
						|
but instead used to locally override the default collector. For example:
 | 
						|
 | 
						|
```rust
 | 
						|
use tracing::{info, Level};
 | 
						|
use tracing_subscriber;
 | 
						|
 | 
						|
fn main() {
 | 
						|
    let collector = tracing_subscriber::fmt()
 | 
						|
        // filter spans/events with level TRACE or higher.
 | 
						|
        .with_max_level(Level::TRACE)
 | 
						|
        // build but do not install the subscriber.
 | 
						|
        .finish();
 | 
						|
 | 
						|
    tracing::collect::with_default(collector, || {
 | 
						|
        info!("This will be logged to stdout");
 | 
						|
    });
 | 
						|
    info!("This will _not_ be logged to stdout");
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Any trace events generated outside the context of a collector will not be collected.
 | 
						|
 | 
						|
This approach allows trace data to be collected by multiple collectors
 | 
						|
within different contexts in the program. Note that the override only applies to the
 | 
						|
currently executing thread; other threads will not see the change from with_default.
 | 
						|
 | 
						|
Once a collector has been set, instrumentation points may be added to the
 | 
						|
executable using the `tracing` crate's macros.
 | 
						|
 | 
						|
[`tracing-subscriber`]: https://docs.rs/tracing-subscriber/
 | 
						|
[fmt]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/index.html
 | 
						|
[`init()`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/fn.init.html
 | 
						|
[`set_global_default()`]: https://docs.rs/tracing/latest/tracing/subscriber/fn.set_global_default.html
 | 
						|
 | 
						|
### In Libraries
 | 
						|
 | 
						|
Libraries should only rely on the `tracing` crate and use the provided macros
 | 
						|
and types to collect whatever information might be useful to downstream consumers.
 | 
						|
 | 
						|
```rust
 | 
						|
use std::{error::Error, io};
 | 
						|
use tracing::{debug, error, info, span, warn, Level};
 | 
						|
 | 
						|
// the `#[tracing::instrument]` attribute creates and enters a span
 | 
						|
// every time the instrumented function is called. The span is named after
 | 
						|
// the function or method. Parameters passed to the function are recorded as fields.
 | 
						|
#[tracing::instrument]
 | 
						|
pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> {
 | 
						|
    // this creates an event at the DEBUG level with two fields:
 | 
						|
    // - `excitement`, with the key "excitement" and the value "yay!"
 | 
						|
    // - `message`, with the key "message" and the value "hello! I'm gonna shave a yak."
 | 
						|
    //
 | 
						|
    // unlike other fields, `message`'s shorthand initialization is just the string itself.
 | 
						|
    debug!(excitement = "yay!", "hello! I'm gonna shave a yak.");
 | 
						|
    if yak == 3 {
 | 
						|
        warn!("could not locate yak!");
 | 
						|
        // note that this is intended to demonstrate `tracing`'s features, not idiomatic
 | 
						|
        // error handling! in a library or application, you should consider returning
 | 
						|
        // a dedicated `YakError`. libraries like snafu or thiserror make this easy.
 | 
						|
        return Err(io::Error::new(io::ErrorKind::Other, "shaving yak failed!").into());
 | 
						|
    } else {
 | 
						|
        debug!("yak shaved successfully");
 | 
						|
    }
 | 
						|
    Ok(())
 | 
						|
}
 | 
						|
 | 
						|
pub fn shave_all(yaks: usize) -> usize {
 | 
						|
    // Constructs a new span named "shaving_yaks" at the TRACE level,
 | 
						|
    // and a field whose key is "yaks". This is equivalent to writing:
 | 
						|
    //
 | 
						|
    // let span = span!(Level::TRACE, "shaving_yaks", yaks = yaks);
 | 
						|
    //
 | 
						|
    // local variables (`yaks`) can be used as field values
 | 
						|
    // without an assignment, similar to struct initializers.
 | 
						|
    let span = span!(Level::TRACE, "shaving_yaks", yaks);
 | 
						|
    let _enter = span.enter();
 | 
						|
 | 
						|
    info!("shaving yaks");
 | 
						|
 | 
						|
    let mut yaks_shaved = 0;
 | 
						|
    for yak in 1..=yaks {
 | 
						|
        let res = shave(yak);
 | 
						|
        debug!(yak, shaved = res.is_ok());
 | 
						|
 | 
						|
        if let Err(ref error) = res {
 | 
						|
            // Like spans, events can also use the field initialization shorthand.
 | 
						|
            // In this instance, `yak` is the field being initialized.
 | 
						|
            error!(yak, error = error.as_ref(), "failed to shave yak!");
 | 
						|
        } else {
 | 
						|
            yaks_shaved += 1;
 | 
						|
        }
 | 
						|
        debug!(yaks_shaved);
 | 
						|
    }
 | 
						|
 | 
						|
    yaks_shaved
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
```toml
 | 
						|
[dependencies]
 | 
						|
tracing = "0.1"
 | 
						|
```
 | 
						|
 | 
						|
Note: Libraries should *NOT* install a collector by using a method that calls
 | 
						|
[`set_global_default()`], as this will cause conflicts when executables try to
 | 
						|
set the default later.
 | 
						|
 | 
						|
### In Asynchronous Code
 | 
						|
 | 
						|
To trace `async fn`s, the preferred method is using the [`#[instrument]`][instrument] attribute:
 | 
						|
 | 
						|
```rust
 | 
						|
use tracing::{info, instrument};
 | 
						|
use tokio::{io::AsyncWriteExt, net::TcpStream};
 | 
						|
use std::io;
 | 
						|
 | 
						|
#[instrument]
 | 
						|
async fn write(stream: &mut TcpStream) -> io::Result<usize> {
 | 
						|
    let result = stream.write(b"hello world\n").await;
 | 
						|
    info!("wrote to stream; success={:?}", result.is_ok());
 | 
						|
    result
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Special handling is needed for the general case of code using
 | 
						|
[`std::future::Future`][std-future] or blocks with `async`/`await`, as the
 | 
						|
following example _will not_ work:
 | 
						|
 | 
						|
```rust
 | 
						|
async {
 | 
						|
    let _s = span.enter();
 | 
						|
    // ...
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
The span guard `_s` will not exit until the future generated by the `async` block is complete.
 | 
						|
Since futures and spans can be entered and exited _multiple_ times without them completing,
 | 
						|
the span remains entered for as long as the future exists, rather than being entered only when
 | 
						|
it is polled, leading to very confusing and incorrect output.
 | 
						|
For more details, see [the documentation on closing spans][closing].
 | 
						|
 | 
						|
This problem can be solved using the [`Future::instrument`] combinator:
 | 
						|
 | 
						|
```rust
 | 
						|
use tracing::Instrument;
 | 
						|
 | 
						|
let my_future = async {
 | 
						|
    // ...
 | 
						|
};
 | 
						|
 | 
						|
my_future
 | 
						|
    .instrument(tracing::info_span!("my_future"))
 | 
						|
    .await
 | 
						|
```
 | 
						|
 | 
						|
`Future::instrument` attaches a span to the future, ensuring that the span's lifetime
 | 
						|
is as long as the future's.
 | 
						|
 | 
						|
Under the hood, the [`#[instrument]`][instrument] macro performs the same explicit span
 | 
						|
attachment that `Future::instrument` does.
 | 
						|
 | 
						|
[std-future]: https://doc.rust-lang.org/stable/std/future/trait.Future.html
 | 
						|
[closing]: https://docs.rs/tracing/latest/tracing/span/index.html#closing-spans
 | 
						|
[`Future::instrument`]: https://docs.rs/tracing/latest/tracing/trait.Instrument.html#method.instrument
 | 
						|
[instrument]: https://docs.rs/tracing/latest/tracing/attr.instrument.html
 | 
						|
 | 
						|
## Supported Rust Versions
 | 
						|
 | 
						|
Tracing is built against the latest stable release. The minimum supported
 | 
						|
version is 1.63. The current Tracing version is not guaranteed to build on Rust
 | 
						|
versions earlier than the minimum supported version.
 | 
						|
 | 
						|
Tracing follows the same compiler support policies as the rest of the Tokio
 | 
						|
project. The current stable Rust compiler and the three most recent minor
 | 
						|
versions before it will always be supported. For example, if the current stable
 | 
						|
compiler version is 1.69, the minimum supported version will not be increased
 | 
						|
past 1.66, three minor versions prior. Increasing the minimum supported compiler
 | 
						|
version is not considered a semver breaking change as long as doing so complies
 | 
						|
with this policy.
 | 
						|
 | 
						|
## Getting Help
 | 
						|
 | 
						|
First, see if the answer to your question can be found in the API documentation.
 | 
						|
If the answer is not there, there is an active community in
 | 
						|
the [Tracing Discord channel][chat]. We would be happy to try to answer your
 | 
						|
question. Last, if that doesn't work, try opening an [issue] with the question.
 | 
						|
 | 
						|
[chat]: https://discord.gg/EeF3cQw
 | 
						|
[issue]: https://github.com/tokio-rs/tracing/issues/new
 | 
						|
 | 
						|
## Contributing
 | 
						|
 | 
						|
:balloon: Thanks for your help improving the project! We are so happy to have
 | 
						|
you! We have a [contributing guide][guide] to help you get involved in the Tracing
 | 
						|
project.
 | 
						|
 | 
						|
[guide]: CONTRIBUTING.md
 | 
						|
 | 
						|
## Project layout
 | 
						|
 | 
						|
The [`tracing`] crate contains the primary _instrumentation_ API, used for
 | 
						|
instrumenting libraries and applications to emit trace data. The [`tracing-core`]
 | 
						|
crate contains the _core_ API primitives on which the rest of `tracing` is
 | 
						|
instrumented. Authors of trace subscribers may depend on `tracing-core`, which
 | 
						|
guarantees a higher level of stability.
 | 
						|
 | 
						|
Additionally, this repository contains several compatibility and utility
 | 
						|
libraries built on top of `tracing`. Some of these crates are in a pre-release
 | 
						|
state, and are less stable than the `tracing` and `tracing-core` crates.
 | 
						|
 | 
						|
The crates included as part of Tracing are:
 | 
						|
 | 
						|
* [`tracing-futures`]: Utilities for instrumenting `futures`.
 | 
						|
  ([crates.io][fut-crates]|[docs][fut-docs])
 | 
						|
 | 
						|
* [`tracing-macros`]: Experimental macros for emitting trace events (unstable).
 | 
						|
 | 
						|
* [`tracing-attributes`]: Procedural macro attributes for automatically
 | 
						|
    instrumenting functions. ([crates.io][attr-crates]|[docs][attr-docs])
 | 
						|
 | 
						|
* [`tracing-log`]: Compatibility with the `log` crate (unstable).
 | 
						|
 | 
						|
* [`tracing-serde`]: A compatibility layer for serializing trace data with
 | 
						|
    `serde` (unstable).
 | 
						|
 | 
						|
* [`tracing-subscriber`]: Collector implementations, and utilities for
 | 
						|
  implementing and composing `Collector`s.
 | 
						|
  ([crates.io][sub-crates]|[docs][sub-docs])
 | 
						|
 | 
						|
* [`tracing-tower`]: Compatibility with the `tower` ecosystem (unstable).
 | 
						|
 | 
						|
* [`tracing-appender`]: Utilities for outputting tracing data, including a file appender
 | 
						|
   and non-blocking writer. ([crates.io][app-crates]|[docs][app-docs])
 | 
						|
 | 
						|
* [`tracing-error`]: Provides `SpanTrace`, a type for instrumenting errors with
 | 
						|
  tracing spans
 | 
						|
 | 
						|
* [`tracing-flame`]; Provides a layer for generating flame graphs based on
 | 
						|
  tracing span entry / exit events.
 | 
						|
 | 
						|
* [`tracing-journald`]: Provides a layer for recording events to the
 | 
						|
  Linux `journald` service, preserving structured data.
 | 
						|
 | 
						|
[`tracing`]: tracing
 | 
						|
[`tracing-core`]: tracing-core
 | 
						|
[`tracing-futures`]: tracing-futures
 | 
						|
[`tracing-macros`]: tracing-macros
 | 
						|
[`tracing-attributes`]: tracing-attributes
 | 
						|
[`tracing-log`]: tracing-log
 | 
						|
[`tracing-serde`]: tracing-serde
 | 
						|
[`tracing-subscriber`]: tracing-subscriber
 | 
						|
[`tracing-tower`]: tracing-tower
 | 
						|
[`tracing-appender`]: tracing-appender
 | 
						|
[`tracing-error`]: tracing-error
 | 
						|
[`tracing-flame`]: tracing-flame
 | 
						|
[`tracing-journald`]: tracing-journald
 | 
						|
 | 
						|
[fut-crates]: https://crates.io/crates/tracing-futures
 | 
						|
[fut-docs]: https://docs.rs/tracing-futures
 | 
						|
 | 
						|
[attr-crates]: https://crates.io/crates/tracing-attributes
 | 
						|
[attr-docs]: https://docs.rs/tracing-attributes
 | 
						|
 | 
						|
[sub-crates]: https://crates.io/crates/tracing-subscriber
 | 
						|
[sub-docs]: https://docs.rs/tracing-subscriber
 | 
						|
 | 
						|
[otel-crates]: https://crates.io/crates/tracing-opentelemetry
 | 
						|
[otel-docs]: https://docs.rs/tracing-opentelemetry
 | 
						|
[OpenTelemetry]: https://opentelemetry.io/
 | 
						|
 | 
						|
[app-crates]: https://crates.io/crates/tracing-appender
 | 
						|
[app-docs]: https://docs.rs/tracing-appender
 | 
						|
 | 
						|
## Related Crates
 | 
						|
 | 
						|
In addition to this repository, here are also several third-party crates which
 | 
						|
are not maintained by the `tokio` project. These include:
 | 
						|
 | 
						|
- [`tracing-timing`] implements inter-event timing metrics on top of `tracing`.
 | 
						|
  It provides a subscriber that records the time elapsed between pairs of
 | 
						|
  `tracing` events and generates histograms.
 | 
						|
- [`tracing-honeycomb`] Provides a layer that reports traces spanning multiple machines to [honeycomb.io]. Backed by [`tracing-distributed`].
 | 
						|
- [`tracing-distributed`] Provides a generic implementation of a layer that reports traces spanning multiple machines to some backend.
 | 
						|
- [`tracing-actix-web`] provides `tracing` integration for the `actix-web` web framework.
 | 
						|
- [`tracing-actix`] provides `tracing` integration for the `actix` actor
 | 
						|
  framework.
 | 
						|
- [`axum-insights`] provides `tracing` integration and Application insights export for the `axum` web framework.
 | 
						|
- [`tracing-gelf`] implements a subscriber for exporting traces in Greylog
 | 
						|
  GELF format.
 | 
						|
- [`tracing-coz`] provides integration with the [coz] causal profiler
 | 
						|
  (Linux-only).
 | 
						|
- [`tracing-bunyan-formatter`] provides a layer implementation that reports events and spans in [bunyan] format, enriched with timing information.
 | 
						|
- [`tide-tracing`] provides a [tide] middleware to trace all incoming requests and responses.
 | 
						|
- [`color-spantrace`] provides a formatter for rendering span traces in the
 | 
						|
  style of `color-backtrace`
 | 
						|
- [`color-eyre`] provides customized panic and eyre report handlers for
 | 
						|
  `eyre::Report` for capturing span traces and backtraces with new errors and
 | 
						|
  pretty printing them.
 | 
						|
- [`spandoc`] provides a proc macro for constructing spans from doc comments
 | 
						|
  _inside_ of functions.
 | 
						|
- [`tracing-wasm`] provides a `Collector`/`Subscriber` implementation that reports
 | 
						|
  events and spans via browser `console.log` and [User Timing API (`window.performance`)].
 | 
						|
- [`tracing-web`] provides a layer implementation of level-aware logging of events
 | 
						|
  to web browsers' `console.*` and span events to the [User Timing API (`window.performance`)].
 | 
						|
- [`test-log`] takes care of initializing `tracing` for tests, based on
 | 
						|
  environment variables with an `env_logger` compatible syntax.
 | 
						|
- [`tracing-unwrap`] provides convenience methods to report failed unwraps on `Result` or `Option` types to a `Collector`.
 | 
						|
- [`diesel-tracing`] provides integration with [`diesel`] database connections.
 | 
						|
- [`tracing-tracy`] provides a way to collect [Tracy] profiles in instrumented
 | 
						|
  applications.
 | 
						|
- [`tracing-elastic-apm`] provides a layer for reporting traces to [Elastic APM].
 | 
						|
- [`tracing-etw`] provides a layer for emitting Windows [ETW] events.
 | 
						|
- [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry].
 | 
						|
- [`tracing-forest`] provides a subscriber that preserves contextual coherence by 
 | 
						|
  grouping together logs from the same spans during writing.
 | 
						|
- [`tracing-loki`] provides a layer for shipping logs to [Grafana Loki].
 | 
						|
- [`tracing-logfmt`] provides a layer that formats events and spans into the logfmt format.
 | 
						|
- [`tracing-chrome`] provides a layer that exports trace data that can be viewed in `chrome://tracing`.
 | 
						|
- [`reqwest-tracing`] provides a middleware to trace [`reqwest`] HTTP requests.
 | 
						|
- [`tracing-cloudwatch`] provides a layer that sends events to AWS CloudWatch Logs.
 | 
						|
- [`clippy-tracing`] provides a tool to add, remove and check for `tracing::instrument`.
 | 
						|
 | 
						|
(if you're the maintainer of a `tracing` ecosystem crate not in this list,
 | 
						|
please let us know!)
 | 
						|
 | 
						|
[`tracing-timing`]: https://crates.io/crates/tracing-timing
 | 
						|
[`tracing-honeycomb`]: https://crates.io/crates/tracing-honeycomb
 | 
						|
[`tracing-distributed`]: https://crates.io/crates/tracing-distributed
 | 
						|
[honeycomb.io]: https://www.honeycomb.io/
 | 
						|
[`tracing-actix`]: https://crates.io/crates/tracing-actix
 | 
						|
[`tracing-actix-web`]: https://crates.io/crates/tracing-actix-web
 | 
						|
[`axum-insights`]: https://crates.io/crates/axum-insights
 | 
						|
[`tracing-gelf`]: https://crates.io/crates/tracing-gelf
 | 
						|
[`tracing-coz`]: https://crates.io/crates/tracing-coz
 | 
						|
[coz]: https://github.com/plasma-umass/coz
 | 
						|
[`tracing-bunyan-formatter`]: https://crates.io/crates/tracing-bunyan-formatter
 | 
						|
[`tide-tracing`]: https://crates.io/crates/tide-tracing
 | 
						|
[tide]: https://crates.io/crates/tide
 | 
						|
[bunyan]: https://github.com/trentm/node-bunyan
 | 
						|
[`color-spantrace`]: https://docs.rs/color-spantrace
 | 
						|
[`color-eyre`]: https://docs.rs/color-eyre
 | 
						|
[`spandoc`]: https://docs.rs/spandoc
 | 
						|
[`tracing-wasm`]: https://docs.rs/tracing-wasm
 | 
						|
[`tracing-web`]: https://crates.io/crates/tracing-web
 | 
						|
[`test-log`]: https://crates.io/crates/test-log
 | 
						|
[User Timing API (`window.performance`)]: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API
 | 
						|
[`tracing-unwrap`]: https://docs.rs/tracing-unwrap
 | 
						|
[`diesel`]: https://crates.io/crates/diesel
 | 
						|
[`diesel-tracing`]: https://crates.io/crates/diesel-tracing
 | 
						|
[`tracing-tracy`]: https://crates.io/crates/tracing-tracy
 | 
						|
[Tracy]: https://github.com/wolfpld/tracy
 | 
						|
[`tracing-elastic-apm`]: https://crates.io/crates/tracing-elastic-apm
 | 
						|
[Elastic APM]: https://www.elastic.co/apm
 | 
						|
[`tracing-etw`]: https://github.com/microsoft/rust_win_etw/tree/main/win_etw_tracing
 | 
						|
[ETW]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing
 | 
						|
[`sentry-tracing`]: https://crates.io/crates/sentry-tracing
 | 
						|
[Sentry]: https://sentry.io/welcome/
 | 
						|
[`tracing-forest`]: https://crates.io/crates/tracing-forest
 | 
						|
[`tracing-loki`]: https://crates.io/crates/tracing-loki
 | 
						|
[Grafana Loki]: https://grafana.com/oss/loki/
 | 
						|
[`tracing-logfmt`]: https://crates.io/crates/tracing-logfmt
 | 
						|
[`tracing-chrome`]: https://crates.io/crates/tracing-chrome
 | 
						|
[`reqwest-tracing`]: https://crates.io/crates/reqwest-tracing
 | 
						|
[`reqwest`]: https://crates.io/crates/reqwest
 | 
						|
[`tracing-cloudwatch`]: https://crates.io/crates/tracing-cloudwatch
 | 
						|
[`clippy-tracing`]: https://crates.io/crates/clippy-tracing
 | 
						|
 | 
						|
**Note:** that some of the ecosystem crates are currently unreleased and
 | 
						|
undergoing active development. They may be less stable than `tracing` and
 | 
						|
`tracing-core`.
 | 
						|
 | 
						|
## External Resources
 | 
						|
 | 
						|
This is a list of links to blog posts, conference talks, and tutorials about
 | 
						|
Tracing.
 | 
						|
 | 
						|
#### Blog Posts
 | 
						|
 | 
						|
* [Diagnostics with Tracing][tokio-blog-2019-08] on the Tokio blog, August 2019
 | 
						|
* [Production-Grade Logging in Rust Applications][production-logging-2020], November 2020
 | 
						|
* [Custom Logging in Rust using `tracing` and `tracing-subscriber`, part 1][custom-logging-part-1] and [part 2][custom-logging-part-2], October 2021
 | 
						|
* [Instrumenting Axum projects][detsys-blog-2023-08], August 2023
 | 
						|
 | 
						|
[tokio-blog-2019-08]: https://tokio.rs/blog/2019-08-tracing/
 | 
						|
[detsys-blog-2023-08]: https://determinate.systems/posts/instrumenting-axum
 | 
						|
 | 
						|
#### Talks
 | 
						|
 | 
						|
* [Bay Area Rust Meetup talk and Q&A][bay-rust-2019-03], March 2019
 | 
						|
* [RustConf 2019 talk][rust-conf-2019-08-video] and [slides][rust-conf-2019-08-slides], August 2019
 | 
						|
* [Are we observable yet? @ RustyDays talk][rusty-days-2020-08-video] and [slides][rusty-days-2020-08-slides], August 2020
 | 
						|
* [Crabs with instruments!][tremorcon-2021-09], September 2021
 | 
						|
* [Decrusting the tracing crate by Jon Gjengset][decrusting-tracing-2024-02], February 2024
 | 
						|
 | 
						|
[bay-rust-2019-03]: https://www.youtube.com/watch?v=j_kXRg3zlec
 | 
						|
[rust-conf-2019-08-video]: https://www.youtube.com/watch?v=JjItsfqFIdo
 | 
						|
[rust-conf-2019-08-slides]: https://www.elizas.website/slides/rustconf-8-2019.pdf
 | 
						|
[rusty-days-2020-08-video]: https://youtu.be/HtKnLiFwHJM
 | 
						|
[rusty-days-2020-08-slides]: https://docs.google.com/presentation/d/1zrxJs7fJgQ29bKfnAll1bYTo9cYZxsCZUwDDtyp5Fak/edit?usp=sharing
 | 
						|
[production-logging-2020]: https://medium.com/better-programming/production-grade-logging-in-rust-applications-2c7fffd108a6
 | 
						|
[custom-logging-part-1]: https://burgers.io/custom-logging-in-rust-using-tracing
 | 
						|
[custom-logging-part-2]: https://burgers.io/custom-logging-in-rust-using-tracing-part-2
 | 
						|
[tremorcon-2021-09]: https://www.youtube.com/watch?v=ZC7fyqshun8
 | 
						|
[decrusting-tracing-2024-02]: https://www.youtube.com/watch?v=21rtHinFA40
 | 
						|
 | 
						|
Help us expand this list! If you've written or spoken about Tracing, or
 | 
						|
know of resources that aren't listed, please open a pull request adding them.
 | 
						|
 | 
						|
## License
 | 
						|
 | 
						|
This project is licensed under the [MIT license](LICENSE).
 | 
						|
 | 
						|
### Contribution
 | 
						|
 | 
						|
Unless you explicitly state otherwise, any contribution intentionally submitted
 | 
						|
for inclusion in Tracing by you, shall be licensed as MIT, without any additional
 | 
						|
terms or conditions.
 |