Skip to content

Commit

Permalink
tracing, tracing-futures: instrument Future inside Drop (tokio-rs…
Browse files Browse the repository at this point in the history
…#2562)

## Motivation

Currently it is not possible to disable ANSI in `fmt::Subscriber`
without enabling the "ansi" crate feature. This makes it difficult for
users to implement interoperable settings that are controllable with
crate features without having to pull in the dependencies "ansi" does.

I hit this while writing an application with multiple logging options
set during compile-time and I wanted to cut down on dependencies if
possible.

## Solution

This changes `fmt::Subscriber::with_ansi()` to not require the "ansi"
feature flag. This way, `with_ansi(false)` can be called even when the
"ansi" feature is disabled. Calling `with_ansi(true)` when the "ansi"
feature is not enabled will panic in debug mode, or print a warning if
debug assertions are disabled.

Co-authored-by: daxpedda <daxpedda@gmail.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
  • Loading branch information
3 people authored and kaffarell committed May 22, 2024
1 parent 5a30de9 commit 9e2dd0f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
6 changes: 6 additions & 0 deletions tracing-attributes/tests/async_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ fn async_fn_nested() {
.exit(span2.clone())
.enter(span2.clone())
.exit(span2.clone())
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
.exit(span.clone())
.enter(span.clone())
Expand Down Expand Up @@ -207,13 +209,17 @@ fn async_fn_with_async_trait() {
.exit(span3.clone())
.enter(span3.clone())
.exit(span3.clone())
.enter(span3.clone())
.exit(span3.clone())
.drop_span(span3)
.new_span(span2.clone().with_fields(expect::field("self")))
.enter(span2.clone())
.event(expect::event().with_fields(expect::field("val").with_value(&5u64)))
.exit(span2.clone())
.enter(span2.clone())
.exit(span2.clone())
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
.exit(span.clone())
.enter(span.clone())
Expand Down
4 changes: 4 additions & 0 deletions tracing-attributes/tests/err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ fn test_async() {
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
Expand Down Expand Up @@ -137,6 +139,8 @@ fn test_mut_async() {
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
Expand Down
22 changes: 20 additions & 2 deletions tracing/src/instrument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ use core::{
pin::Pin,
task::{Context, Poll},
};
use core::{
future::Future,
marker::Sized,
mem::{self, ManuallyDrop},
pin::Pin,
task::{Context, Poll},
};
use pin_project_lite::pin_project;

#[cfg(feature = "std")]
Expand Down Expand Up @@ -451,14 +458,25 @@ impl<T> WithDispatch<T> {

/// Get a pinned mutable reference to the wrapped type.
pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
self.project().inner
self.project().span_and_inner_pin_mut().1
}

/// Consumes the `Instrumented`, returning the wrapped type.
///
/// Note that this drops the span.
pub fn into_inner(self) -> T {
self.inner
// To manually destructure `Instrumented` without `Drop`, we save
// pointers to the fields and use `mem::forget` to leave those pointers
// valid.
let span: *const Span = &self.span;
let inner: *const ManuallyDrop<T> = &self.inner;
mem::forget(self);
// SAFETY: Those pointers are valid for reads, because `Drop` didn't
// run, and properly aligned, because `Instrumented` isn't
// `#[repr(packed)]`.
let _span = unsafe { span.read() };
let inner = unsafe { inner.read() };
ManuallyDrop::into_inner(inner)
}
}

Expand Down

0 comments on commit 9e2dd0f

Please sign in to comment.