- Notifications
You must be signed in to change notification settings - Fork810
Application level tracing for Rust.
License
tokio-rs/tracing
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
tracing
is a framework for instrumenting Rust programs to collectstructured, event-based diagnostic information.tracing
is maintained by theTokio project, but doesnot require thetokio
runtime to be used.
main
- Default branch, crates.io releases are done from this branch. This was previously thev0.1.x
branch.v0.2.x
- Branch containing the as-yet unreleased 0.2 version oftracing-core
,tracing
, andall the other tracing crates that depend on these versions. This was previously themaster
branch.
In order to record trace events, executables have to use aSubscriber
implementation compatible withtracing
. ASubscriber
implements a way ofcollecting trace data, such as by logging it to standard output.tracing-subscriber
'sfmt
module providesa subscriber for logging traces with reasonable defaults. Additionally,tracing-subscriber
is able to consume messages emitted bylog
-instrumentedlibraries and modules.
To usetracing-subscriber
, add the following to yourCargo.toml
:
[dependencies]tracing ="0.1"tracing-subscriber ="0.3"
Then create and install aSubscriber
, for example usinginit()
:
use tracing::info;use tracing_subscriber;fnmain(){// install global subscriber configured based on RUST_LOG envvar. 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.");}
Usinginit()
callsset_global_default()
so this subscriber will be usedas the default in all threads for the remainder of the duration of theprogram, similar to how loggers work in thelog
crate.
For more control, a subscriber can be built in stages and not set globally,but instead used to locally override the default subscriber. For example:
use tracing::{info,Level};use tracing_subscriber;fnmain(){let subscriber = 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::subscriber::with_default(subscriber, ||{info!("This will be logged to stdout");});info!("This will _not_ be logged to stdout");}
Any trace events generated outside the context of a subscriber will not be collected.
This approach allows trace data to be collected by multiple subscriberswithin different contexts in the program. Note that the override only applies to thecurrently executing thread; other threads will not see the change from with_default.
Once a subscriber has been set, instrumentation points may be added to theexecutable using thetracing
crate's macros.
Libraries should only rely on thetracing
crate and use the provided macrosand types to collect whatever information might be useful to downstream consumers.
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// the function or method. Parameters passed to the function are recorded as fields.#[tracing::instrument]pubfnshave(yak:usize) ->Result<(),Box<dynError +'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.returnErr(io::Error::new(io::ErrorKind::Other,"shaving yak failed!").into());}else{debug!("yak shaved successfully");}Ok(())}pubfnshave_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");letmut yaks_shaved =0;for yakin1..=yaks{let res =shave(yak);debug!(yak, shaved = res.is_ok());ifletErr(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}
[dependencies]tracing ="0.1"
Note: Libraries shouldNOT install a subscriber by using a method that callsset_global_default()
, as this will cause conflicts when executables try toset the default later.
To traceasync fn
s, the preferred method is using the#[instrument]
attribute:
use tracing::{info, instrument};use tokio::{io::AsyncWriteExt, net::TcpStream};use std::io;#[instrument]asyncfnwrite(stream:&mutTcpStream) -> 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 usingstd::future::Future
or blocks withasync
/await
, as thefollowing examplewill not work:
async{let _s = span.enter();// ...}
The span guard_s
will not exit until the future generated by theasync
block is complete.Since futures and spans can be entered and exitedmultiple times without them completing,the span remains entered for as long as the future exists, rather than being entered only whenit is polled, leading to very confusing and incorrect output.For more details, seethe documentation on closing spans.
This problem can be solved using theFuture::instrument
combinator:
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 lifetimeis as long as the future's.
Under the hood, the#[instrument]
macro performs the same explicit spanattachment thatFuture::instrument
does.
Tracing is built against the latest stable release. The minimum supportedversion is 1.65. The current Tracing version is not guaranteed to build on Rustversions earlier than the minimum supported version.
Tracing follows the same compiler support policies as the rest of the Tokioproject. The current stable Rust compiler and the three most recent minorversions before it will always be supported. For example, if the current stablecompiler version is 1.69, the minimum supported version will not be increasedpast 1.66, three minor versions prior. Increasing the minimum supported compilerversion is not considered a semver breaking change as long as doing so complieswith this policy.
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 intheTracing Discord channel. We would be happy to try to answer yourquestion. Last, if that doesn't work, try opening anissue with the question.
🎈 Thanks for your help improving the project! We are so happy to haveyou! We have acontributing guide to help you get involved in the Tracingproject.
Thetracing
crate contains the primaryinstrumentation API, used forinstrumenting libraries and applications to emit trace data. Thetracing-core
crate contains thecore API primitives on which the rest oftracing
isinstrumented. Authors of trace subscribers may depend ontracing-core
, whichguarantees a higher level of stability.
Additionally, this repository contains several compatibility and utilitylibraries built on top oftracing
. Some of these crates are in a pre-releasestate, and are less stable than thetracing
andtracing-core
crates.
The crates included as part of Tracing are:
tracing-futures
: Utilities for instrumentingfutures
.(crates.io|docs)tracing-macros
: Experimental macros for emitting trace events (unstable).tracing-attributes
: Procedural macro attributes for automaticallyinstrumenting functions. (crates.io|docs)tracing-log
: Compatibility with thelog
crate (unstable).tracing-serde
: A compatibility layer for serializing trace data withserde
(unstable).tracing-subscriber
: Subscriber implementations, and utilities forimplementing and composingSubscriber
s.(crates.io|docs)tracing-tower
: Compatibility with thetower
ecosystem (unstable).tracing-appender
: Utilities for outputting tracing data, including a file appenderand non-blocking writer. (crates.io|docs)tracing-error
: ProvidesSpanTrace
, a type for instrumenting errors withtracing spanstracing-flame
; Provides a layer for generating flame graphs based ontracing span entry / exit events.tracing-journald
: Provides a layer for recording events to theLinuxjournald
service, preserving structured data.
In addition to this repository, here are also several third-party crates whichare not maintained by thetokio
project. These include:
tracing-timing
implements inter-event timing metrics on top oftracing
.It provides a subscriber that records the time elapsed between pairs oftracing
events and generates histograms.tracing-honeycomb
Provides a layer that reports traces spanning multiple machines tohoneycomb.io. Backed bytracing-distributed
.tracing-distributed
Provides a generic implementation of a layer that reports traces spanning multiple machines to some backend.tracing-actix-web
providestracing
integration for theactix-web
web framework.tracing-actix
providestracing
integration for theactix
actorframework.axum-insights
providestracing
integration and Application insights export for theaxum
web framework.tracing-gelf
implements a subscriber for exporting traces in GraylogGELF format.tracing-coz
provides integration with thecoz causal profiler(Linux-only).tracing-bunyan-formatter
provides a layer implementation that reports events and spans inbunyan format, enriched with timing information.tide-tracing
provides atide middleware to trace all incoming requests and responses.color-spantrace
provides a formatter for rendering span traces in thestyle ofcolor-backtrace
color-eyre
provides customized panic and eyre report handlers foreyre::Report
for capturing span traces and backtraces with new errors andpretty printing them.spandoc
provides a proc macro for constructing spans from doc commentsinside of functions.tracing-wasm
provides aSubscriber
/Layer
implementation that reportsevents and spans via browserconsole.log
andUser Timing API (window.performance
).tracing-web
provides a layer implementation of level-aware logging of eventsto web browsers'console.*
and span events to theUser Timing API (window.performance
).test-log
takes care of initializingtracing
for tests, based onenvironment variables with anenv_logger
compatible syntax.tracing-unwrap
provides convenience methods to report failed unwraps onResult
orOption
types to aSubscriber
.diesel-tracing
provides integration withdiesel
database connections.tracing-tracy
provides a way to collectTracy profiles in instrumentedapplications.tracing-elastic-apm
provides a layer for reporting traces toElastic APM.tracing-etw
provides a layer for emitting WindowsETW events.sentry-tracing
provides a layer for reporting events and traces toSentry.tracing-forest
provides a subscriber that preserves contextual coherence bygrouping together logs from the same spans during writing.tracing-loki
provides a layer for shipping logs toGrafana 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 inchrome://tracing
.reqwest-tracing
provides a middleware to tracereqwest
HTTP requests.tracing-cloudwatch
provides a layer that sends events to AWS CloudWatch Logs.clippy-tracing
provides a tool to add, remove and check fortracing::instrument
.
(if you're the maintainer of atracing
ecosystem crate not in this list,please let us know!)
Note: that some of the ecosystem crates are currently unreleased andundergoing active development. They may be less stable thantracing
andtracing-core
.
This is a list of links to blog posts, conference talks, and tutorials aboutTracing.
- Diagnostics with Tracing on the Tokio blog, August 2019
- Production-Grade Logging in Rust Applications, November 2020
- Custom Logging in Rust using
tracing
andtracing-subscriber
, part 1 andpart 2, October 2021 - Instrumenting Axum projects, August 2023
- Bay Area Rust Meetup talk and Q&A, March 2019
- RustConf 2019 talk andslides, August 2019
- Are we observable yet? @ RustyDays talk andslides, August 2020
- Crabs with instruments!, September 2021
- Decrusting the tracing crate by Jon Gjengset, February 2024
Help us expand this list! If you've written or spoken about Tracing, orknow of resources that aren't listed, please open a pull request adding them.
This project is licensed under theMIT license.
Unless you explicitly state otherwise, any contribution intentionally submittedfor inclusion in Tracing by you, shall be licensed as MIT, without any additionalterms or conditions.
About
Application level tracing for Rust.
Topics
Resources
License
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.