Skip to content

Backport everything up to May 2025 #3283

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jun 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ce3c257
chore: fix Rust 1.85.0 lints and errors (#3240)
hds Mar 24, 2025
de5e1c0
chore: fix Rust 1.86.0 lints (#3253)
hds Apr 10, 2025
a9096c4
Update README.md docs link (#3145)
kaffarell Nov 30, 2024
5995024
fix: Update incorrect tracing-futures feature docs (#2802)
jayvdb Nov 30, 2024
6a64d83
chore: remove outdated release instructions (#3154)
0xPoe Dec 1, 2024
1d5431b
chore: corrected typos in the example readme (#2718)
ilsubyeega Dec 1, 2024
12823c0
docs: add link to a stream recording by @jonhoo (#3106)
porkbrain Dec 1, 2024
89ea410
subscriber: skip padding when skipping `log.*` fields in `DefaultVisi…
Porges Dec 2, 2024
c47aeb5
tracing: add `record_all!` macro for recording multiple values in one…
matildasmeds Mar 27, 2025
6017d2c
subscriber: increase `EnvFilter` test coverage (#3262)
hds Apr 30, 2025
c382f05
subscriber: use state machine to parse `EnvFilter` directives (#3243)
djc May 8, 2025
f5444f5
macros: Remove 'r#' prefix from raw identifiers in field names (#3130)
dtolnay May 13, 2025
8f57bf9
examples: add env-filter-explorer example (#3233)
joshka May 15, 2025
da14f9b
subscriber: update matchers to 0.2 (#3033)
oscargus May 27, 2025
5671f34
subscriber: enable TestWriter to write to stderr (#3187)
d-e-s-o May 27, 2025
8b07355
Fix typo in README.md (#3062)
mchristou May 27, 2025
d7d390c
Fix typos in subscriber docs (#2831)
kaffarell May 27, 2025
ebd2009
chore: Bump thiserror to v2 (#3172)
paolobarbolini May 27, 2025
4410778
Update nu-ansi-term to 0.50 (#3049)
ChrisDenton May 27, 2025
addc9c2
attributes: Globally qualify attribute paths (#3126)
heaths May 28, 2025
5366628
chore: fix doc issues (#3292)
hds May 30, 2025
0c5af12
Let `dead_code` lint work on `#[instrument]`ed functions (#3108)
9999years May 30, 2025
4fbd377
fix: Do not compare references to pointers to compare pointers (#3236)
samueltardieu May 30, 2025
49bde06
appender: introduce weekly rotation (#3218)
NickCaplinger May 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:
shell: bash

check-msrv:
# Run `cargo check` on our minimum supported Rust version (1.63.0). This
# Run `cargo check` on our minimum supported Rust version (1.65.0). This
# checks with minimal versions; maximal versions are checked above.
name: "cargo check (+MSRV -Zminimal-versions)"
needs: check
Expand All @@ -143,7 +143,7 @@ jobs:
- tracing-tower
- tracing
toolchain:
- 1.63.0
- 1.65.0
- stable
steps:
- uses: actions/checkout@v4
Expand Down
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ be viewed by clicking the `details` link on the
### Building Documentation

Tracing's documentation uses nightly-only RustDoc features and lints, like
`doc(cfg)` and `broken_intra_doc_lints`. These features are enabled by
`doc(cfg)` and `broken_intra_doc_lints`. These features are enabled by
passing `--cfg docsrs` to RustDoc. Therefore, in order to build Tracing's
documentation the same way it would be built by docs.rs, it's necessary to
use the following command:
Expand Down Expand Up @@ -430,8 +430,7 @@ When releasing a new version of a crate, follow these steps:
2. **Update Cargo metadata.** After releasing any path dependencies, update the
`version` field in `Cargo.toml` to the new version, and the `documentation`
field to the docs.rs URL of the new version.
3. **Update other documentation links.** Update the `#![doc(html_root_url)]`
attribute in the crate's `lib.rs` and the "Documentation" link in the crate's
3. **Update the "Documentation" link in the crate's
`README.md` to point to the docs.rs URL of the new version.
4. **Update the changelog for the crate.** Each crate in the Tokio repository
has its own `CHANGELOG.md` in that crate's subdirectory. Any changes to that
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ members = [
# This will be ignored with Rust older than 1.74, but for now that's okay;
# we're only using it to fix check-cfg issues that first appeared in Rust 1.80.
[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(flaky_tests)", "cfg(tracing_unstable)"] }
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(flaky_tests)", "cfg(tracing_unstable)", "cfg(unsound_local_offset)"] }
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
[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
[docs-master-url]: https://tracing.rs
[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
Expand Down Expand Up @@ -252,7 +252,7 @@ attachment that `Future::instrument` does.
## Supported Rust Versions

Tracing is built against the latest stable release. The minimum supported
version is 1.63. The current Tracing version is not guaranteed to build on Rust
version is 1.65. 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
Expand Down Expand Up @@ -370,7 +370,7 @@ are not maintained by the `tokio` project. These include:
- [`tracing-actix`] provides `tracing` integration for the `actix` actor
framework.
- [`axum-insights`] provides `tracing` integration and Application insights export for the `axum` web framework.
- [`tracing-gelf`] implements a subscriber for exporting traces in Greylog
- [`tracing-gelf`] implements a subscriber for exporting traces in Graylog
GELF format.
- [`tracing-coz`] provides integration with the [coz] causal profiler
(Linux-only).
Expand All @@ -396,7 +396,7 @@ are not maintained by the `tokio` project. These include:
- [`tracing-elastic-apm`] provides a layer for reporting traces to [Elastic APM].
- [`tracing-etw`] provides a layer for emitting Windows [ETW] events.
- [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry].
- [`tracing-forest`] provides a subscriber that preserves contextual coherence by
- [`tracing-forest`] provides a subscriber that preserves contextual coherence by
grouping together logs from the same spans during writing.
- [`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.
Expand Down Expand Up @@ -475,6 +475,7 @@ Tracing.
* [RustConf 2019 talk][rust-conf-2019-08-video] and [slides][rust-conf-2019-08-slides], August 2019
* [Are we observable yet? @ RustyDays talk][rusty-days-2020-08-video] and [slides][rusty-days-2020-08-slides], August 2020
* [Crabs with instruments!][tremorcon-2021-09], September 2021
* [Decrusting the tracing crate by Jon Gjengset][decrusting-tracing-2024-02], February 2024

[bay-rust-2019-03]: https://www.youtube.com/watch?v=j_kXRg3zlec
[rust-conf-2019-08-video]: https://www.youtube.com/watch?v=JjItsfqFIdo
Expand All @@ -485,6 +486,7 @@ Tracing.
[custom-logging-part-1]: https://burgers.io/custom-logging-in-rust-using-tracing
[custom-logging-part-2]: https://burgers.io/custom-logging-in-rust-using-tracing-part-2
[tremorcon-2021-09]: https://www.youtube.com/watch?v=ZC7fyqshun8
[decrusting-tracing-2024-02]: https://www.youtube.com/watch?v=21rtHinFA40

Help us expand this list! If you've written or spoken about Tracing, or
know of resources that aren't listed, please open a pull request adding them.
Expand Down
10 changes: 8 additions & 2 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ bytes = "1"
argh = "0.1.8"

# sloggish example
nu-ansi-term = "0.46.0"
nu-ansi-term = "0.50.0"
humantime = "2.1.0"
log = "0.4.17"

Expand All @@ -48,7 +48,13 @@ tempfile = "3"

# fmt examples
snafu = "0.6.10"
thiserror = "1.0.31"
thiserror = "2"

# env-filter-explorer example
ansi-to-tui = "7.0.0"
ratatui = "0.29.0"
crossterm = "0.28.1"
tui-textarea = "0.7.0"

# valuable examples
valuable = { version = "0.1.0", features = ["derive"] }
Expand Down
4 changes: 2 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ This directory contains a collection of examples that demonstrate the use of the
+ `futures-proxy-server`: Demonstrates the use of `tracing-futures` by
implementing a simple proxy server, based on [this example][tokio-proxy]
from `tokio`.
+ `async_fn`: Demonstrates how asynchronous functions can be
+ `async-fn`: Demonstrates how asynchronous functions can be
instrumented.
+ `echo`: Demonstrates a `tracing`-instrumented variant of Tokio's `echo` example.
- **tracing-flame**:
+ `infero-flame`: Demonstrates the use of `tracing-flame` to generate a flamegraph
+ `inferno-flame`: Demonstrates the use of `tracing-flame` to generate a flamegraph
from spans.
- **tracing-tower**:
+ `tower-client`: Demonstrates the use of `tracing-tower` to instrument a
Expand Down
251 changes: 251 additions & 0 deletions examples/examples/env-filter-explorer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
use std::{
io::{self},
sync::{Arc, Mutex},
};

use ansi_to_tui::IntoText;
use crossterm::event;
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Rect},
style::Stylize,
widgets::{Block, Widget},
DefaultTerminal, Frame,
};
use tracing_subscriber::{filter::ParseError, fmt::MakeWriter, EnvFilter};
use tui_textarea::{Input, Key, TextArea};

/// A list of preset filters to make it easier to explore the filter syntax.
///
/// The UI allows you to select a preset filter with the up/down arrow keys.
const PRESET_FILTERS: &[&str] = &[
"trace",
"debug",
"info",
"warn",
"error",
"[with_fields]",
"[with_fields{foo}]",
"[with_fields{bar}]",
"[with_fields{foo=42}]",
"[with_fields{bar=bar}]",
"[with_fields{foo=99}]",
"[with_fields{bar=nope}]",
"[with_fields{nonexistent}]",
"other_crate=info",
"other_crate=debug",
"trace,other_crate=warn",
"warn,other_crate=info",
];

fn main() -> io::Result<()> {
let terminal = ratatui::init();
let result = App::new().run(terminal);
ratatui::restore();
result
}

struct App {
filter: TextArea<'static>,
preset_index: usize,
exit: bool,
log_widget: Result<LogWidget, ParseError>,
}

impl App {
/// Creates a new instance of the application, ready to run
fn new() -> Self {
let mut filter = TextArea::new(vec![PRESET_FILTERS[0].to_string()]);
let title = "Env Filter Explorer. <Esc> to quit, <Up>/<Down> to select preset";
filter.set_block(Block::bordered().title(title));
Self {
filter,
preset_index: 0,
exit: false,
log_widget: Ok(LogWidget::default()),
}
}

/// The application's main loop until the user exits.
fn run(mut self, mut terminal: DefaultTerminal) -> io::Result<()> {
while !self.exit {
self.log_widget = self.evaluate_filter();
terminal.draw(|frame| self.render(frame))?;
self.handle_event()?;
}
Ok(())
}

/// Render the application with a filter input area and a log output area.
fn render(&self, frame: &mut Frame) {
let layout = Layout::vertical([Constraint::Length(3), Constraint::Fill(1)]);
let [filter_area, main_area] = layout.areas(frame.area());
frame.render_widget(&self.filter, filter_area);
match &self.log_widget {
Ok(log_widget) => frame.render_widget(log_widget, main_area),
Err(error) => frame.render_widget(error.to_string().red(), main_area),
}
}

/// Handles a single terminal event (e.g. mouse, keyboard, resize).
fn handle_event(&mut self) -> io::Result<()> {
let event = event::read()?;
let input = Input::from(event);
match input.key {
Key::Enter => return Ok(()), // ignore new lines
Key::Esc => self.exit = true,
Key::Up => self.select_previous_preset(),
Key::Down => self.select_next_preset(),
_ => self.add_input(input),
}
Ok(())
}

/// Selects the previous preset filter in the list.
fn select_previous_preset(&mut self) {
self.select_preset(self.preset_index.saturating_sub(1));
}

/// Selects the next preset filter in the list.
fn select_next_preset(&mut self) {
self.select_preset((self.preset_index + 1).min(PRESET_FILTERS.len() - 1));
}

/// Selects a preset filter by index and updates the filter text area.
fn select_preset(&mut self, index: usize) {
self.preset_index = index;
self.filter.select_all();
self.filter.delete_line_by_head();
self.filter.insert_str(PRESET_FILTERS[self.preset_index]);
}

/// Handles normal keyboard input by adding it to the filter text area.
fn add_input(&mut self, input: Input) {
self.filter.input(input);
}

/// Evaluates the current filter and returns a log widget with the filtered logs or an error.
fn evaluate_filter(&mut self) -> Result<LogWidget, ParseError> {
let filter = self.filter.lines()[0].to_string();
let env_filter = EnvFilter::builder().parse(filter)?;
let log_widget = LogWidget::default();
let subscriber = tracing_subscriber::fmt()
.with_env_filter(env_filter)
.with_writer(log_widget.clone())
.finish();
tracing::subscriber::with_default(subscriber, || {
simulate_logging();
other_crate_span();
});
Ok(log_widget)
}
}

/// A writer that collects logs into a buffer and can be displayed as a widget.
#[derive(Clone, Default, Debug)]
struct LogWidget {
buffer: Arc<Mutex<Vec<u8>>>,
}

impl io::Write for LogWidget {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buffer.lock().unwrap().write(buf)
}

fn flush(&mut self) -> io::Result<()> {
self.buffer.lock().unwrap().flush()
}
}

impl<'a> MakeWriter<'a> for LogWidget {
type Writer = Self;

fn make_writer(&'a self) -> Self::Writer {
self.clone()
}
}

impl Widget for &LogWidget {
/// Displays the logs that have been collected in the buffer.
///
/// If the buffer is empty, it displays "No matching logs".
fn render(self, area: Rect, buf: &mut Buffer) {
let buffer = self.buffer.lock().unwrap();
let string = String::from_utf8_lossy(&buffer).to_string();
if string.is_empty() {
"No matching logs".render(area, buf);
return;
}
string
.into_text() // convert a string with ANSI escape codes into ratatui Text
.unwrap_or_else(|err| format!("Error parsing output: {err}").into())
.render(area, buf);
}
}

#[tracing::instrument]
fn simulate_logging() {
tracing::info!("This is an info message");
tracing::error!("This is an error message");
tracing::warn!("This is a warning message");
tracing::debug!("This is a debug message");
tracing::trace!("This is a trace message");

with_fields(42, "bar");
with_fields(99, "nope");

trace_span();
debug_span();
info_span();
warn_span();
error_span();
}

#[tracing::instrument]
fn with_fields(foo: u32, bar: &'static str) {
tracing::info!(foo, bar, "This is an info message with fields");
}

#[tracing::instrument(level = "trace")]
fn trace_span() {
tracing::error!("Error message inside a span with trace level");
tracing::info!("Info message inside a span with trace level");
tracing::trace!("Trace message inside a span with trace level");
}

#[tracing::instrument]
fn debug_span() {
tracing::error!("Error message inside a span with debug level");
tracing::info!("Info message inside a span with debug level");
tracing::debug!("Debug message inside a span with debug level");
}

#[tracing::instrument]
fn info_span() {
tracing::error!("Error message inside a span with info level");
tracing::info!("Info message inside a span with info level");
tracing::debug!("Debug message inside a span with info level");
}

#[tracing::instrument]
fn warn_span() {
tracing::error!("Error message inside a span with warn level");
tracing::info!("Info message inside a span with warn level");
tracing::debug!("Debug message inside a span with warn level");
}

#[tracing::instrument]
fn error_span() {
tracing::error!("Error message inside a span with error level");
tracing::info!("Info message inside a span with error level");
tracing::debug!("Debug message inside a span with error level");
}

#[tracing::instrument(target = "other_crate")]
fn other_crate_span() {
tracing::error!(target: "other_crate", "An error message from another crate");
tracing::warn!(target: "other_crate", "A warning message from another crate");
tracing::info!(target: "other_crate", "An info message from another crate");
tracing::debug!(target: "other_crate", "A debug message from another crate");
tracing::trace!(target: "other_crate", "A trace message from another crate");
}
2 changes: 1 addition & 1 deletion tracing-appender/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ rust-version = "1.63.0"
crossbeam-channel = "0.5.6"
time = { version = "0.3.2", default-features = false, features = ["formatting", "parsing"] }
parking_lot = { optional = true, version = "0.12.1" }
thiserror = "1"
thiserror = "2"

[dependencies.tracing-subscriber]
path = "../tracing-subscriber"
Expand Down
Loading