better_tracing/
lib.rs

1//! ## Community fork 🍴 of `tracing-subscriber` focused on usability and accessibility.
2//!
3//! [![Crates.io][crates-badge]][crates-url]
4//! [![Documentation][docs-badge]][docs-url]
5//! [![MIT licensed][mit-badge]][mit-url]
6//! [![changelog][changelog-badge]][changelog-url]
7//! ![maintenance status][maint-badge]
8//!
9//! **better-tracing** = **tracing-subscriber** + **smart defaults and features that just work**
10//!
11//! See the [CHANGELOG](https://github.com/dra11y/better-tracing/blob/main/CHANGELOG.md) for implemented features and fixes.
12//!
13//! Utilities for implementing and composing [`tracing`][tracing] subscribers. This fork provides sensible defaults, accessible formatting, and resolves architectural limitations while maintaining drop-in compatibility.
14//!
15//! **Backward compatibility and compatibility with 3rd party crates that might use `tracing_subscriber` will be maintained on a best-effort basis.**
16//!
17//! | Feature | better-tracing | tracing-subscriber |
18//! |---------|----------------|-------------------|
19//! | **Drop-in compatibility** | ✅ | ✅ |
20//! | **Easier time formats** | ✅ | ❌ |
21//! | **External formatters access exiting span on EXIT/CLOSE** | ✅ | ❌ |
22//! | **Sane defaults with zero configuration** | ⏳ | ❌ |
23//! | **Better builders** you don't have to fight with | ⏳ | ❌ |
24//!
25//! *Compiler support: [requires `rustc` 1.65+][msrv]*
26//!
27//! [msrv]: #supported-rust-versions
28//!
29//! # Fork Improvements
30//!
31//! ## Easier Time Formats
32//!
33//! Configure timestamps without extra crates and keep using `.with_timer(...)`:
34//!
35//! - RFC 3339 (UTC):
36//!   - `SystemTime::rfc3339_seconds()`     → `YYYY-MM-DDTHH:MM:SSZ`
37//!   - `SystemTime::rfc3339_millis()`      → `YYYY-MM-DDTHH:MM:SS.mmmZ`
38//!   - `SystemTime::rfc3339_nanos()`       → `YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ`
39//! - Unix epoch (UTC):
40//!   - `SystemTime::unix_seconds()` / `unix_millis()` / `unix_micros()` / `unix_nanos()`
41//! - Time-only (no date, great for dev logs):
42//!   - `SystemTime::time_only_secs()`      → `HH:MM:SS`
43//!   - `SystemTime::time_only_millis()`    → `HH:MM:SS.mmm`
44//!   - `SystemTime::time_only_micros()`    → `HH:MM:SS.uuuuuu`
45//!
46//! Examples:
47//! ```rust
48//! use better_tracing::fmt::time::SystemTime;
49//! let subscriber = better_tracing::fmt()
50//!     .with_timer(SystemTime::time_only_millis())
51//!     .finish();
52//! # drop(subscriber);
53//! ```
54//! ```rust
55//! use better_tracing::fmt::time::SystemTime;
56//! let subscriber = better_tracing::fmt()
57//!     .with_timer(SystemTime::rfc3339_millis())
58//!     .finish();
59//! # drop(subscriber);
60//! ```
61//!
62//! With optional engines, pick the matching helpers: `fmt::time::ChronoUtc::*` (chrono), `fmt::time::UtcTime::*` (time), or `fmt::time::SystemTime::*` (default).
63//!
64//! ## Fixed Span Context for EXIT/CLOSE Events
65//!
66//! In `tracing-subscriber`, `lookup_current()` returned the parent span instead of the exiting span during `FmtSpan::EXIT` and `FmtSpan::CLOSE` events. `better-tracing` fixes this.
67//!
68//! ```rust
69//! use better_tracing::fmt::format::FmtSpan;
70//!
71//! // Custom formatter that can now access the exiting span
72//! use better_tracing::{
73//!     fmt::{FmtContext, FormatEvent, FormatFields, format::Writer},
74//!     registry::LookupSpan,
75//! };
76//! use tracing::{Event, Subscriber};
77//! use std::fmt;
78//!
79//! struct MyFormatter;
80//!
81//! impl<S, N> FormatEvent<S, N> for MyFormatter
82//! where
83//!     S: Subscriber + for<'a> LookupSpan<'a>,
84//!     N: for<'a> FormatFields<'a> + 'static,
85//! {
86//!     fn format_event(
87//!         &self,
88//!         ctx: &FmtContext<'_, S, N>,
89//!         mut writer: Writer<'_>,
90//!         event: &Event<'_>,
91//!     ) -> fmt::Result {
92//!         // Now returns the correct exiting span during EXIT/CLOSE events
93//!         if let Some(span) = ctx.lookup_current() {
94//!             write!(writer, "{}:", span.name())?;
95//!         }
96//!         Ok(())
97//!     }
98//! }
99//!
100//! // Set up subscriber with the custom formatter and EXIT events
101//! let subscriber = better_tracing::fmt()
102//!     .with_span_events(FmtSpan::EXIT)
103//!     .event_format(MyFormatter)
104//!     .finish();
105//! ```
106//! # Adapted from upstream `tracing-subscriber`
107//!
108//! [`tracing`] is a framework for instrumenting Rust programs to collect
109//! scoped, structured, and async-aware diagnostics. The [`Subscriber`] trait
110//! represents the functionality necessary to collect this trace data. This
111//! crate contains tools for composing subscribers out of smaller units of
112//! behaviour, and batteries-included implementations of common subscriber
113//! functionality.
114//!
115//! `better-tracing` is intended for use by both `Subscriber` authors and
116//! application authors using `tracing` to instrument their applications.
117//!
118//! # `Layer`s and `Filter`s
119//!
120//! The most important component of the `better-tracing` API is the
121//! [`Layer`] trait, which provides a composable abstraction for building
122//! [`Subscriber`]s. Like the [`Subscriber`] trait, a [`Layer`] defines a
123//! particular behavior for collecting trace data. Unlike [`Subscriber`]s,
124//! which implement a *complete* strategy for how trace data is collected,
125//! [`Layer`]s provide *modular* implementations of specific behaviors.
126//! Therefore, they can be [composed together] to form a [`Subscriber`] which is
127//! capable of recording traces in a variety of ways. See the [`layer` module's
128//! documentation][layer] for details on using [`Layer`]s.
129//!
130//! In addition, the [`Filter`] trait defines an interface for filtering what
131//! spans and events are recorded by a particular layer. This allows different
132//! [`Layer`]s to handle separate subsets of the trace data emitted by a
133//! program. See the [documentation on per-layer filtering][plf] for more
134//! information on using [`Filter`]s.
135//!
136//! [`Layer`]: crate::layer::Layer
137//! [composed together]: crate::layer#composing-layers
138//! [layer]: crate::layer
139//! [`Filter`]: crate::layer::Filter
140//! [plf]: crate::layer#per-layer-filtering
141//!
142//! # Included Subscribers
143//!
144//! The following `Subscriber`s are provided for application authors:
145//!
146//! - [`fmt`] - Formats and logs tracing data (requires the `fmt` feature flag)
147//!
148//! # Feature Flags
149//!
150//! - `std`: Enables APIs that depend on the Rust standard library
151//!   (enabled by default).
152//! - `alloc`: Depend on [`liballoc`] (enabled by "std").
153//! - `env-filter`: Enables the [`EnvFilter`] type, which implements filtering
154//!   similar to the [`env_logger` crate]. **Requires "std"**.
155//! - `fmt`: Enables the [`fmt`] module, which provides a subscriber
156//!   implementation for printing formatted representations of trace events.
157//!   Enabled by default. **Requires "registry" and "std"**.
158//! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by
159//!   default.
160//! - `registry`: enables the [`registry`] module. Enabled by default.
161//!   **Requires "std"**.
162//! - `json`: Enables `fmt` support for JSON output. In JSON output, the ANSI
163//!   feature does nothing. **Requires "fmt" and "std"**.
164//! - `local-time`: Enables local time formatting when using the [`time`
165//!   crate]'s timestamp formatters with the `fmt` subscriber.
166//!
167//! [`registry`]: mod@registry
168//!
169//! ## Optional Dependencies
170//!
171//! - [`tracing-log`]: Enables better formatting for events emitted by `log`
172//!   macros in the `fmt` subscriber. Enabled by default.
173//! - [`time`][`time` crate]: Enables support for using the [`time` crate] for timestamp
174//!   formatting in the `fmt` subscriber.
175//! - [`smallvec`]: Causes the `EnvFilter` type to use the `smallvec` crate (rather
176//!   than `Vec`) as a performance optimization. Enabled by default.
177//! - [`parking_lot`]: Use the `parking_lot` crate's `RwLock` implementation
178//!   rather than the Rust standard library's implementation.
179//!
180//! ## `no_std` Support
181//!
182//! In embedded systems and other bare-metal applications, `tracing` can be
183//! used without requiring the Rust standard library, although some features are
184//! disabled. Although most of the APIs provided by `better-tracing`, such
185//! as [`fmt`] and [`EnvFilter`], require the standard library, some
186//! functionality, such as the [`Layer`] trait, can still be used in
187//! `no_std` environments.
188//!
189//! The dependency on the standard library is controlled by two crate feature
190//! flags, "std", which enables the dependency on [`libstd`], and "alloc", which
191//! enables the dependency on [`liballoc`] (and is enabled by the "std"
192//! feature). These features are enabled by default, but `no_std` users can
193//! disable them using:
194//!
195//! ```toml
196//! # Cargo.toml
197//! better-tracing = { version = "0.3", default-features = false }
198//! ```
199//!
200//! Additional APIs are available when [`liballoc`] is available. To enable
201//! `liballoc` but not `std`, use:
202//!
203//! ```toml
204//! # Cargo.toml
205//! better-tracing = { version = "0.3", default-features = false, features = ["alloc"] }
206//! ```
207//!
208//! ## Unstable Features
209//!
210//! These feature flags enable **unstable** features. The public API may break in 0.1.x
211//! releases. To enable these features, the `--cfg tracing_unstable` must be passed to
212//! `rustc` when compiling.
213//!
214//! The following unstable feature flags are currently available:
215//!
216//! * `valuable`: Enables support for serializing values recorded using the
217//!   [`valuable`] crate as structured JSON in the [`format::Json`] formatter.
218//!
219//! ## Enabling Unstable Features
220//!
221//! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS`
222//! env variable when running `cargo` commands:
223//!
224//! ```shell
225//! RUSTFLAGS="--cfg tracing_unstable" cargo build
226//! ```
227//! Alternatively, the following can be added to the `.cargo/config` file in a
228//! project to automatically enable the cfg flag for that project:
229//!
230//! ```toml
231//! [build]
232//! rustflags = ["--cfg", "tracing_unstable"]
233//! ```
234//!
235//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
236//! [`valuable`]: https://crates.io/crates/valuable
237//! [`format::Json`]: crate::fmt::format::Json
238//!
239//! # Supported Rust Versions
240//!
241//! This fork follows the same minimum supported Rust version as the upstream `tracing-subscriber`.
242//! The minimum supported version is 1.65. The current version is not guaranteed to build on Rust
243//! versions earlier than the minimum supported version.
244//!
245//! better-tracing follows a similar compiler support policy to the upstream 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.
246//!
247//! # License
248//!
249//! This project is licensed under the [MIT license](LICENSE).
250//!
251//! # Disclaimer
252//!
253//! This is an independent community fork of `tracing-subscriber`. This project is not affiliated with, endorsed by, sponsored by, or supported by the Tokio team, the Tokio project, or any of the original `tracing-subscriber` maintainers. All trademarks are the property of their respective owners.
254//!
255//! The name "tracing" and related trademarks belong to their respective owners. This fork exists to provide enhanced functionality while maintaining compatibility with the upstream project.
256//!
257//! # Contribution
258//!
259//! Unless you explicitly state otherwise, any contribution intentionally submitted
260//! for inclusion in better-tracing by you, shall be licensed as MIT, without any additional
261//! terms or conditions.
262//!
263//! [tracing]: https://github.com/tokio-rs/tracing/tree/main/tracing
264//! [tracing-subscriber]: https://github.com/tokio-rs/tracing/tree/main/tracing-subscriber
265//! [crates-badge]: https://img.shields.io/crates/v/better-tracing.svg
266//! [crates-url]: https://crates.io/crates/better-tracing
267//! [docs-badge]: https://docs.rs/better-tracing/badge.svg
268//! [docs-url]: https://docs.rs/better-tracing/latest
269//! [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
270//! [mit-url]: LICENSE
271//! [changelog-badge]: https://img.shields.io/badge/changelog-Keep%20a%20Changelog-E05735?labelColor=555555&logo=keepachangelog
272//! [maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg
273//! [changelog-url]: CHANGELOG.md
274//! [`Subscriber`]: tracing_core::subscriber::Subscriber
275//! [`tracing`]: https://docs.rs/tracing/latest/tracing
276//! [`EnvFilter`]: filter::EnvFilter
277//! [`fmt`]: mod@fmt
278//! [`tracing`]: https://crates.io/crates/tracing
279//! [`tracing-log`]: https://crates.io/crates/tracing-log
280//! [`smallvec`]: https://crates.io/crates/smallvec
281//! [`env_logger` crate]: https://crates.io/crates/env_logger
282//! [`parking_lot`]: https://crates.io/crates/parking_lot
283//! [`time` crate]: https://crates.io/crates/time
284//! [`liballoc`]: https://doc.rust-lang.org/alloc/index.html
285//! [`libstd`]: https://doc.rust-lang.org/std/index.html
286#![cfg_attr(
287    docsrs,
288    // Allows displaying cfgs/feature flags in the documentation.
289    feature(doc_cfg),
290    // Allows adding traits to RustDoc's list of "notable traits"
291    feature(doc_notable_trait),
292    // Fail the docs build if any intra-docs links are broken
293    deny(rustdoc::broken_intra_doc_links),
294)]
295#![warn(
296    missing_debug_implementations,
297    missing_docs,
298    rust_2018_idioms,
299    unreachable_pub,
300    bad_style,
301    dead_code,
302    improper_ctypes,
303    non_shorthand_field_patterns,
304    no_mangle_generic_items,
305    overflowing_literals,
306    path_statements,
307    patterns_in_fns_without_body,
308    private_interfaces,
309    private_bounds,
310    unconditional_recursion,
311    unused,
312    unused_allocation,
313    unused_comparisons,
314    unused_parens,
315    while_true
316)]
317// Using struct update syntax when a struct has no additional fields avoids
318// a potential source change if additional fields are added to the struct in the
319// future, reducing diff noise. Allow this even though clippy considers it
320// "needless".
321#![allow(clippy::needless_update)]
322#![cfg_attr(not(feature = "std"), no_std)]
323
324#[cfg(feature = "alloc")]
325extern crate alloc;
326
327#[macro_use]
328mod macros;
329
330pub mod field;
331pub mod filter;
332pub mod prelude;
333pub mod registry;
334
335pub mod layer;
336pub mod util;
337
338feature! {
339    #![feature = "std"]
340    pub mod reload;
341    pub(crate) mod sync;
342}
343
344feature! {
345    #![all(feature = "fmt", feature = "std")]
346    pub mod fmt;
347    pub use fmt::fmt;
348    pub use fmt::Subscriber as FmtSubscriber;
349}
350
351feature! {
352    #![all(feature = "env-filter", feature = "std")]
353    pub use filter::EnvFilter;
354}
355
356pub use layer::Layer;
357
358feature! {
359    #![all(feature = "registry", feature = "std")]
360    pub use registry::Registry;
361
362    /// Returns a default [`Registry`].
363    pub fn registry() -> Registry {
364        Registry::default()
365    }
366}
367
368mod sealed {
369    pub trait Sealed<A = ()> {}
370}