- Notifications
You must be signed in to change notification settings - Fork0
Application level tracing for Rust.
License
matrix-construct/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.xbranch.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 themasterbranch.
In order to record trace events, executables have to use aSubscriberimplementation 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 fns, 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-corecrate 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 thelogcrate (unstable).tracing-serde: A compatibility layer for serializing trace data withserde(unstable).tracing-subscriber: Subscriber implementations, and utilities forimplementing and composingSubscribers.(crates.io|docs)tracing-tower: Compatibility with thetowerecosystem (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 theLinuxjournaldservice, preserving structured data.
In addition to this repository, here are also several third-party crates whichare not maintained by thetokio project. These include:
tracing-timingimplements inter-event timing metrics on top oftracing.It provides a subscriber that records the time elapsed between pairs oftracingevents and generates histograms.tracing-honeycombProvides a layer that reports traces spanning multiple machines tohoneycomb.io. Backed bytracing-distributed.tracing-distributedProvides a generic implementation of a layer that reports traces spanning multiple machines to some backend.tracing-actix-webprovidestracingintegration for theactix-webweb framework.tracing-actixprovidestracingintegration for theactixactorframework.axum-insightsprovidestracingintegration and Application insights export for theaxumweb framework.tracing-gelfimplements a subscriber for exporting traces in GraylogGELF format.tracing-cozprovides integration with thecoz causal profiler(Linux-only).tracing-bunyan-formatterprovides a layer implementation that reports events and spans inbunyan format, enriched with timing information.tide-tracingprovides atide middleware to trace all incoming requests and responses.color-spantraceprovides a formatter for rendering span traces in thestyle ofcolor-backtracecolor-eyreprovides customized panic and eyre report handlers foreyre::Reportfor capturing span traces and backtraces with new errors andpretty printing them.spandocprovides a proc macro for constructing spans from doc commentsinside of functions.tracing-wasmprovides aSubscriber/Layerimplementation that reportsevents and spans via browserconsole.logandUser Timing API (window.performance).tracing-webprovides a layer implementation of level-aware logging of eventsto web browsers'console.*and span events to theUser Timing API (window.performance).test-logtakes care of initializingtracingfor tests, based onenvironment variables with anenv_loggercompatible syntax.tracing-unwrapprovides convenience methods to report failed unwraps onResultorOptiontypes to aSubscriber.diesel-tracingprovides integration withdieseldatabase connections.tracing-tracyprovides a way to collectTracy profiles in instrumentedapplications.tracing-elastic-apmprovides a layer for reporting traces toElastic APM.tracing-etwprovides a layer for emitting WindowsETW events.sentry-tracingprovides a layer for reporting events and traces toSentry.tracing-forestprovides a subscriber that preserves contextual coherence bygrouping together logs from the same spans during writing.tracing-lokiprovides a layer for shipping logs toGrafana Loki.tracing-logfmtprovides a layer that formats events and spans into the logfmt format.tracing-chromeprovides a layer that exports trace data that can be viewed inchrome://tracing.reqwest-tracingprovides a middleware to tracereqwestHTTP requests.tracing-cloudwatchprovides a layer that sends events to AWS CloudWatch Logs.clippy-tracingprovides 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
tracingandtracing-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.
Resources
License
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Languages
- Rust99.8%
- Other0.2%