tracing
Application-level tracing for Rust.
Overview
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
in 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
addition, tracing spans are structured, with the ability to record typed
data as well as textual messages.
The tracing crate provides the APIs necessary for instrumenting libraries
and applications to emit trace data.
Usage
First, add this to your Cargo.toml:
[]
= "0.1.7"
This crate provides macros for creating Spans and Events, which represent
periods of time and momentary events within the execution of a program,
respectively.
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 Span:
use ;
// Construct a new span named "my span".
let mut span = span!;
span.in_scope;
// Dropping the span will close it, indicating that it has ended.
The Event type represent an event that occurs instantaneously, and is
essentially a Span that cannot be entered. They are created using the event!
macro:
use ;
event!;
Users of the log crate should note that tracing exposes a set of macros for
creating Events (trace!, debug!, info!, warn!, and error!) which may
be invoked with the same syntax as the similarly-named macros from the log
crate. Often, the process of converting a project to use tracing can begin
with a simple drop-in replacement.
Let's consider the log crate's yak-shaving
example, modified to use
tracing:
// Import `tracing`'s macros rather than `log`'s
use ;
// unchanged from here forward
// Dummy impls to make the example compile
;
We can change it even further to better utilize features in tracing.
use ;
;
You can find further examples showing how to use this crate in the examples directory.
In libraries
Libraries should link only to the tracing crate, and use the provided
macros to record whatever information will be useful to downstream consumers.
In executables
In order to record trace events, executables have to use a Subscriber
implementation compatible with tracing. A Subscriber implements a way of
collecting trace data, such as by logging it to standard output.
There currently aren't too many subscribers to choose from. The best one to use right now
is probably tracing-fmt, which logs to the terminal. It is not currently
published to crates.io so you will need to add tracing-fmt as a git
dependency to use it.
The simplest way to use a subscriber is to call the set_global_default function:
use ;
;
let my_subscriber = new;
set_global_default
.expect;
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 log crate.
Note: Libraries should NOT call set_global_default()! That will cause conflicts when
executables try to set the default later.
In addition, you can locally override the default subscriber, using the tokio pattern
of executing code in a context. For example:
use ;
;
let my_subscriber = new;
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.
In addition to tracing and tracing-core, the tokio-rs/tracing repository
contains several additional crates designed to be used with the tracing ecosystem.
This includes a collection of Subscriber implementations, as well as utility
and adapter crates to assist in writing Subscribers and instrumenting
applications.
In particular, the following crates are likely to be of interest:
tracing-futuresprovides a compatibility layer with thefuturescrate, allowing spans to be attached toFutures,Streams, andExecutors.tracing-fmtprovides aSubscriberimplementation for logging formatted trace data to stdout, with similar filtering and formatting to theenv-loggercrate.tracing-logprovides a compatibility layer with thelogcrate, allowing log messages to be recorded astracingEvents within the trace tree. This is useful when a project usingtracinghave dependencies which uselog.tracing-timingimplements inter-event timing metrics on top oftracing. It provides a subscriber that records the time elapsed between pairs oftracingevents and generates histograms.
Note: that some of the ecosystem crates are currently unreleased and
undergoing active development. They may be less stable than tracing and
tracing-core.
License
This project is licensed under the MIT license.
Contribution
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.