Application-level tracing for Rust.
tracing is a framework for instrumenting Rust programs to collect
structured, event-based diagnostic information.
In asynchronous systems like Tokio, interpreting traditional log messages can
often be quite challenging. Since individual tasks are multiplexed on the same
thread, associated events and log lines are intermixed making it difficult to
trace the logic flow.
tracing expands upon logging-style diagnostics by
allowing libraries and applications to record structured events with additional
information about temporality and causality — unlike a log message, a span
tracing has a beginning and end time, may be entered and exited by the
flow of execution, and may exist within a nested tree of similar spans. In
tracing spans are structured, with the ability to record typed
data as well as textual messages.
tracing crate provides the APIs necessary for instrumenting libraries
and applications to emit trace data.
Compiler support: requires
(The examples below are borrowed from the
log crate's yak-shaving
example, modified to
In order to record trace events, executables have to use a
implementation compatible with
Subscriber implements a way of
collecting trace data, such as by logging it to standard output.
fmt module provides reasonable defaults.
tracing-subscriber is able to consume messages emitted by
log-instrumented libraries and modules.
The simplest way to use a subscriber is to call the
This subscriber 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
In addition, you can locally override the default subscriber. For example:
This approach allows trace data to be collected by multiple subscribers 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.
Any trace events generated outside the context of a subscriber will not be collected.
Once a subscriber has been set, instrumentation points may be added to the
executable using the
tracing crate's macros.
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.
// the `#[tracing::instrument]` attribute creates and enters a span
// every time the instrumented function is called. The span is named after the
// the function or method. Paramaters passed to the function are recorded as fields.
Note: Libraries should NOT call
set_global_default(), as this will cause
conflicts when executables try to set the default later.
In Asynchronous Code
If you are instrumenting code that make use of
or async/await, avoid using the
Span::enter method. The following example
will not work:
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.
There are two ways to instrument asynchronous code. The first is through the
let my_future = async ;
Future::instrument attaches a span to the future, ensuring that the span's lifetime
is as long as the future's.
The second, and preferred, option is through the
Under the hood, the
#[instrument] macro performs the same explicit span
This crate provides macros for creating
Events, which represent
periods of time and momentary events within the execution of a program,
As a rule of thumb, spans should be used to represent discrete units of work (e.g., a given request's lifetime in a server) or periods of time spent in a given context (e.g., time spent interacting with an instance of an external system, such as a database). In contrast, events should be used to represent points in time within a span — a request returned with a given status code, n new items were taken from a queue, and so on.
Spans are constructed using the
span! macro, and then entered
to indicate that some code takes place within the context of that
// Construct a new span named "my span".
let mut span = span!;
// Dropping the span will close it, indicating that it has ended.
#[instrument] attribute macro
can reduce some of this boilerplate:
Event type represent an event that occurs instantaneously, and is
Span that cannot be entered. They are created using the
Users of the
log crate should note that
tracing exposes a set of macros for
error!) which may
be invoked with the same syntax as the similarly-named macros from the
crate. Often, the process of converting a project to use
tracing can begin
with a simple drop-in replacement.
Supported Rust Versions
Tracing is built against the latest stable release. The minimum supported version is 1.42. 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.45, the minimum supported version will not be increased past 1.42, 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.
In addition to
contains several additional crates designed to be used with the
This includes a collection of
Subscriber implementations, as well as utility
and adapter crates to assist in writing
Subscribers and instrumenting
In particular, the following crates are likely to be of interest:
tracing-futuresprovides a compatibility layer with the
futurescrate, allowing spans to be attached to
Subscriberimplementations and utilities for working with
Subscribers. This includes a
FmtSubscriberfor logging formatted trace data to stdout, with similar filtering and formatting to the
tracing-logprovides a compatibility layer with the
logcrate, allowing log messages to be recorded as
Events within the trace tree. This is useful when a project using
tracinghave dependencies which use
log. Note that if you're using
FmtSubscriber, you don't need to depend on
Additionally, there are also several third-party crates which are not
maintained by the
tokio project. These include:
tracing-timingimplements inter-event timing metrics on top of
tracing. It provides a subscriber that records the time elapsed between pairs of
tracingevents and generates histograms.
tracing-opentelemetryprovides a subscriber for emitting traces to OpenTelemetry-compatible distributed tracing systems.
tracing-honeycombProvides a layer that reports traces spanning multiple machines to honeycomb.io. Backed by
tracing-distributedProvides a generic implementation of a layer that reports traces spanning multiple machines to some backend.
tracingintegration for the
tracingintegration and Application insights export for the
tracing-gelfimplements a subscriber for exporting traces in Greylog GELF format.
tracing-cozprovides integration with the coz causal profiler (Linux-only).
test-logtakes care of initializing
tracingfor tests, based on environment variables with an
tracing-unwrapprovides convenience methods to report failed unwraps on
Optiontypes to a
diesel-tracingprovides integration with
tracing-tracyprovides a way to collect Tracy profiles in instrumented applications.
tracing-elastic-apmprovides a layer for reporting traces to Elastic APM.
tracing-etwprovides a layer for emitting Windows ETW events.
tracing-fluent-assertionsprovides a fluent assertions-style testing framework for validating the behavior of
sentry-tracingprovides a layer for reporting events and traces to Sentry.
tracing-lokiprovides a layer for shipping logs to Grafana Loki.
tracing-logfmtprovides a layer that formats events and spans into the logfmt format.
If you're the maintainer of a
tracing ecosystem crate not listed above,
please let us know! We'd love to add your project to the list!
Note: that some of the ecosystem crates are currently unreleased and
undergoing active development. They may be less stable than
Supported Rust Versions
Tracing is built against the latest stable release. The minimum supported version is 1.56. 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.
This project is licensed under the MIT license.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Tokio by you, shall be licensed as MIT, without any additional terms or conditions.