diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1809345405..35d202dd689 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,7 @@ jobs: - test-workspace-all-features - test-integration-tests-per-feature - test-parking_lot + - test-tracing-instrumentation - valgrind - test-unstable - miri @@ -213,6 +214,34 @@ jobs: - name: Check tests with all features enabled run: cargo check --workspace --all-features --tests + test-tracing-instrumentation: + # These tests use the as-yet unpublished `tracing-mock` crate to test the + # tracing instrumentation present in Tokio. As such they are placed in + # their own test crate outside of the workspace. + needs: basics + name: test tokio instrumentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install Rust ${{ env.rust_stable }} + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ env.rust_stable }} + - name: Install cargo-nextest + uses: taiki-e/install-action@v2 + with: + tool: cargo-nextest + + - uses: Swatinem/rust-cache@v2 + + - name: test tracing-instrumentation + run: | + set -euxo pipefail + cargo nextest run + working-directory: tokio/tests/tracing-instrumentation + env: + RUSTFLAGS: --cfg tokio_unstable -Dwarnings + valgrind: name: valgrind needs: basics diff --git a/tokio/tests/tracing-instrumentation/Cargo.toml b/tokio/tests/tracing-instrumentation/Cargo.toml new file mode 100644 index 00000000000..94c88dc2810 --- /dev/null +++ b/tokio/tests/tracing-instrumentation/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "tracing-instrumentation" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[dev-dependencies] +futures = { version = "0.3.0", features = ["async-await"] } +tokio = { version = "1.33.0", path = "../..", features = ["full", "tracing"] } +tracing = { version = "0.1.40", git = "https://github.com/tokio-rs/tracing.git", tag = "tracing-0.1.40" } +tracing-mock = { version = "0.1.0", git = "https://github.com/tokio-rs/tracing.git", tag = "tracing-0.1.40" } + +[patch.crates-io] +tracing = { git = "https://github.com/tokio-rs/tracing.git", tag = "tracing-0.1.40" } + +[workspace] diff --git a/tokio/tests/tracing-instrumentation/tests/task.rs b/tokio/tests/tracing-instrumentation/tests/task.rs new file mode 100644 index 00000000000..7bdb078e32c --- /dev/null +++ b/tokio/tests/tracing-instrumentation/tests/task.rs @@ -0,0 +1,107 @@ +//! Tests for task instrumentation. +//! +//! These tests ensure that the instrumentation for task spawning and task +//! lifecycles is correct. + +use tokio::task; +use tracing_mock::{expect, span::NewSpan, subscriber}; + +#[tokio::test] +async fn task_spawn_creates_span() { + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task"); + + let (subscriber, handle) = subscriber::mock() + .new_span(task_span.clone()) + .enter(task_span.clone()) + .exit(task_span.clone()) + // The task span is entered once more when it gets dropped + .enter(task_span.clone()) + .exit(task_span.clone()) + .drop_span(task_span) + .run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + tokio::spawn(futures::future::ready(())) + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); +} + +#[tokio::test] +async fn task_spawn_loc_file_recorded() { + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + .with_field(expect::field("loc.file").with_value(&file!())); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + + tokio::spawn(futures::future::ready(())) + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); +} + +#[tokio::test] +async fn task_builder_name_recorded() { + let task_span = expect_task_named("test-task"); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + task::Builder::new() + .name("test-task") + .spawn(futures::future::ready(())) + .unwrap() + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); +} + +#[tokio::test] +async fn task_builder_loc_file_recorded() { + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + .with_field(expect::field("loc.file").with_value(&file!())); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + + task::Builder::new() + .spawn(futures::future::ready(())) + .unwrap() + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); +} + +/// Expect a task with name +/// +/// This is a convenience function to create the expectation for a new task +/// with the `task.name` field set to the provided name. +fn expect_task_named(name: &str) -> NewSpan { + expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + .with_field( + expect::field("task.name").with_value(&tracing::field::debug(format_args!("{}", name))), + ) +}