Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 4 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ jobs:
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
# All features includes rt-tracing-exec-force, testing span propagation.
- run: cargo test --all-features
# full excludes that opt-in, so also check that TokioExecutor does not
# propagate spans by default. Limit this extra run to runtime tests.
- run: "cargo test --features full --lib rt::"

msrv:
name: Check MSRV (${{ matrix.rust }}) on ${{ matrix.os }}
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ tokio = { version = "1", features = ["macros", "test-util", "signal", "net", "io
tokio-test = "0.4"
tower-test = "0.4"
pretty_env_logger = "0.5"
tracing-subscriber = { version = "0.3", default-features = false, features = ["registry", "std"] }

[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dev-dependencies]
pnet_datalink = "0.35.0"
Expand All @@ -58,7 +59,7 @@ windows-registry = { version = ">=0.3, <0.7", optional = true }
[features]
default = []

# Shorthand to enable everything
# Shorthand to enable all standard features (excluding temporary opt-ins).
full = [
"client",
"client-legacy",
Expand Down Expand Up @@ -94,6 +95,9 @@ tokio = ["dep:tokio", "tokio/rt", "tokio/time"]

tracing = ["dep:tracing"]

# Temporary compatibility opt-in, deliberately excluded from `full`.
rt-tracing-exec-force = ["tokio", "tracing"]

# internal features used in CI
__internal_happy_eyeballs_tests = []

Expand Down
38 changes: 35 additions & 3 deletions src/rt/tokio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use std::{
use hyper::rt::{Executor, Sleep, Timer};
use pin_project_lite::pin_project;

#[cfg(feature = "tracing")]
#[cfg(feature = "rt-tracing-exec-force")]
use tracing::instrument::Instrument;

pub use self::{with_hyper_io::WithHyperIo, with_tokio_io::WithTokioIo};
Expand All @@ -69,6 +69,13 @@ mod with_hyper_io;
mod with_tokio_io;

/// Future executor that utilises `tokio` threads.
///
/// Spawned futures do not inherit the current tracing span, even when the
/// `tracing` feature is enabled.
///
/// The temporary `rt-tracing-exec-force` feature restores propagation of the
/// current span for libraries that do not allow customizing their executor.
/// It is excluded from `full` and may be removed in a future breaking release.
#[non_exhaustive]
#[derive(Default, Debug, Clone)]
pub struct TokioExecutor {}
Expand Down Expand Up @@ -107,10 +114,10 @@ where
Fut::Output: Send + 'static,
{
fn execute(&self, fut: Fut) {
#[cfg(feature = "tracing")]
#[cfg(feature = "rt-tracing-exec-force")]
tokio::spawn(fut.in_current_span());

#[cfg(not(feature = "tracing"))]
#[cfg(not(feature = "rt-tracing-exec-force"))]
tokio::spawn(fut);
}
}
Expand Down Expand Up @@ -338,4 +345,29 @@ mod tests {
});
rx.await.map_err(Into::into)
}

#[cfg(feature = "tracing")]
#[tokio::test]
async fn execute_tracing_span() {
// The current-thread runtime keeps the subscriber active while the
// spawned future is polled, after the caller has exited its span.
let _subscriber = tracing::subscriber::set_default(tracing_subscriber::registry());
let span = tracing::info_span!("caller");
assert!(span.id().is_some());
let (tx, rx) = oneshot::channel();

{
let _entered = span.enter();
TokioExecutor::new().execute(async move {
tx.send(tracing::Span::current().id()).unwrap();
});
}

let spawned_span = rx.await.unwrap();
if cfg!(feature = "rt-tracing-exec-force") {
assert_eq!(spawned_span, span.id());
} else {
assert_eq!(spawned_span, None);
}
}
}
Loading