aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md465
1 files changed, 465 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6947345
--- /dev/null
+++ b/README.md
@@ -0,0 +1,465 @@
+![Tracing — Structured, application-level diagnostics][splash]
+
+[splash]: https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/splash.svg
+
+# tracing
+
+Application-level tracing for Rust.
+
+[![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]
+
+[Documentation][docs-url] | [Chat][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.netlify.com/tracing
+[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
+
+## 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.
+
+*Compiler support: [requires `rustc` 1.49+][msrv]*
+
+[msrv]: #supported-rust-versions
+
+## Usage
+
+(The examples below are borrowed from the `log` crate's yak-shaving
+[example](https://docs.rs/log/0.4.10/log/index.html#examples), modified to
+idiomatic `tracing`.)
+
+### In Applications
+
+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. [`tracing_subscriber`](https://docs.rs/tracing-subscriber/)'s
+[`fmt` module](https://docs.rs/tracing-subscriber/0.3/tracing_subscriber/fmt/index.html) provides reasonable defaults.
+Additionally, `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 `set_global_default` function.
+
+```rust
+use tracing::{info, Level};
+use tracing_subscriber::FmtSubscriber;
+
+fn main() {
+ // a builder for `FmtSubscriber`.
+ let subscriber = FmtSubscriber::builder()
+ // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
+ // will be written to stdout.
+ .with_max_level(Level::TRACE)
+ // completes the builder.
+ .finish();
+
+ tracing::subscriber::set_global_default(subscriber)
+ .expect("setting default subscriber failed");
+
+ 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."
+ );
+}
+```
+
+```toml
+[dependencies]
+tracing = "0.1"
+tracing-subscriber = "0.2.0"
+```
+
+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.
+
+In addition, you can locally override the default subscriber. For example:
+
+```rust
+use tracing::{info, Level};
+use tracing_subscriber::FmtSubscriber;
+
+fn main() {
+ let subscriber = tracing_subscriber::FmtSubscriber::builder()
+ // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
+ // will be written to stdout.
+ .with_max_level(Level::TRACE)
+ // builds the subscriber.
+ .finish();
+
+ tracing::subscriber::with_default(subscriber, || {
+ info!("This will be logged to stdout");
+ });
+ info!("This will _not_ be logged to stdout");
+}
+```
+
+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.
+
+### 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
+// the function or method. Paramaters 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).entered();
+
+ 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 initalized.
+ 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* 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
+[`std::future::Future`](https://doc.rust-lang.org/stable/std/future/trait.Future.html)
+or async/await, avoid using the `Span::enter` method. The following example
+_will not_ work:
+
+```rust
+async {
+ let _s = span.enter();
+ // ...
+}
+```
+```rust
+async {
+ let _s = tracing::span!(...).entered();
+ // ...
+}
+```
+
+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](https://tracing.rs/tracing/span/index.html#closing-spans).
+
+There are two ways to instrument asynchronous code. The first is through the
+[`Future::instrument`](https://docs.rs/tracing/latest/tracing/trait.Instrument.html#method.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.
+
+The second, and preferred, option is through the
+[`#[instrument]`](https://docs.rs/tracing/0.1.37/tracing/attr.instrument.html)
+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
+}
+```
+
+Under the hood, the `#[instrument]` macro performs the same explicit span
+attachment that `Future::instrument` does.
+
+### Concepts
+
+This crate provides macros for creating `Span`s and `Event`s, 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.
+
+`Span`s are constructed using the `span!` macro, and then _entered_
+to indicate that some code takes place within the context of that `Span`:
+
+```rust
+use tracing::{span, Level};
+
+// Construct a new span named "my span".
+let mut span = span!(Level::INFO, "my span");
+span.in_scope(|| {
+ // Any trace events in this closure or code called by it will occur within
+ // the span.
+});
+// Dropping the span will close it, indicating that it has ended.
+```
+
+The [`#[instrument]`](https://docs.rs/tracing/0.1.37/tracing/attr.instrument.html) attribute macro
+can reduce some of this boilerplate:
+
+```rust
+use tracing::{instrument};
+
+#[instrument]
+pub fn my_function(my_arg: usize) {
+ // This event will be recorded inside a span named `my_function` with the
+ // field `my_arg`.
+ tracing::info!("inside my_function!");
+ // ...
+}
+```
+
+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:
+
+```rust
+use tracing::{event, Level};
+
+event!(Level::INFO, "something has happened!");
+```
+
+Users of the [`log`] crate should note that `tracing` exposes a set of macros for
+creating `Event`s (`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.
+
+## 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.
+
+## Ecosystem
+
+### Related Crates
+
+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 `Subscriber`s and instrumenting
+applications.
+
+In particular, the following crates are likely to be of interest:
+
+- [`tracing-futures`] provides a compatibility layer with the `futures`
+ crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s.
+- [`tracing-subscriber`] provides `Subscriber` implementations and
+ utilities for working with `Subscriber`s. This includes a [`FmtSubscriber`]
+ `FmtSubscriber` for logging formatted trace data to stdout, with similar
+ filtering and formatting to the [`env_logger`] crate.
+- [`tracing-log`] provides a compatibility layer with the [`log`] crate,
+ allowing log messages to be recorded as `tracing` `Event`s within the
+ trace tree. This is useful when a project using `tracing` have
+ dependencies which use `log`. Note that if you're using
+ `tracing-subscriber`'s `FmtSubscriber`, you don't need to depend on
+ `tracing-log` directly.
+
+Additionally, there 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-opentelemetry`] provides a subscriber for emitting traces to
+ [OpenTelemetry]-compatible distributed tracing systems.
+- [`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`] provides `tracing` integration for the `actix` actor
+ framework.
+- [`tracing-gelf`] implements a subscriber for exporting traces in Greylog
+ GELF format.
+- [`tracing-coz`] provides integration with the [coz] causal profiler
+ (Linux-only).
+- [`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 `Subscriber`.
+- [`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.
+- [`tracing-fluent-assertions`] provides a fluent assertions-style testing
+ framework for validating the behavior of `tracing` spans.
+- [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry].
+- [`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.
+
+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!
+
+[`tracing-timing`]: https://crates.io/crates/tracing-timing
+[`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry
+[OpenTelemetry]: https://opentelemetry.io/
+[`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-gelf`]: https://crates.io/crates/tracing-gelf
+[`tracing-coz`]: https://crates.io/crates/tracing-coz
+[coz]: https://github.com/plasma-umass/coz
+[`test-log`]: https://crates.io/crates/test-log
+[`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/tracing-etw
+[ETW]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing
+[`tracing-fluent-assertions`]: https://crates.io/crates/tracing-fluent-assertions
+[`sentry-tracing`]: https://crates.io/crates/sentry-tracing
+[Sentry]: https://sentry.io/welcome/
+[`tracing-loki`]: https://crates.io/crates/tracing-loki
+[Grafana Loki]: https://grafana.com/oss/loki/
+[`tracing-logfmt`]: https://crates.io/crates/tracing-logfmt
+
+**Note:** that some of the ecosystem crates are currently unreleased and
+undergoing active development. They may be less stable than `tracing` and
+`tracing-core`.
+
+[`log`]: https://docs.rs/log/0.4.6/log/
+[`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing
+[`tracing-futures`]: https://github.com/tokio-rs/tracing/tree/master/tracing-futures
+[`tracing-subscriber`]: https://github.com/tokio-rs/tracing/tree/master/tracing-subscriber
+[`tracing-log`]: https://github.com/tokio-rs/tracing/tree/master/tracing-log
+[`env_logger`]: https://crates.io/crates/env_logger
+[`FmtSubscriber`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/struct.Subscriber.html
+[`examples`]: https://github.com/tokio-rs/tracing/tree/master/examples
+
+## Supported Rust Versions
+
+Tracing is built against the latest stable release. The minimum supported
+version is 1.49. 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.
+
+## License
+
+This project is licensed under the [MIT license](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.