Panic with Zipkin

I am trying to get Zipkin tracing working in a simple example, but get this panic with the following code. What am I missing here?

Error
Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context.

Code

use axum::{routing::get, Json, Router};
use serde::Serialize;
use std::net::SocketAddr;
use tracing::{info, instrument};
use tracing_subscriber::{layer::SubscriberExt, Registry};

#[derive(Serialize)]
struct ApiResponse {
    message: String,
    status: u16,
}

#[tokio::main]
async fn main() {
    init_tracing();

    let app = Router::new()
        .route("/", get(root_handler))
        .route("/hello", get(hello_handler));

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    info!("Listening on http://{}", addr);

    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

#[instrument]
async fn root_handler() -> Json<ApiResponse> {
    Json(ApiResponse {
        message: "Welcome to the Rust API!".to_string(),
        status: 200,
    })
}

#[instrument]
async fn hello_handler() -> Json<ApiResponse> {
    Json(ApiResponse {
        message: "Hello, world!".to_string(),
        status: 200,
    })
}

fn init_tracing() {
    let tracer = opentelemetry_zipkin::new_pipeline()
        .with_service_name("rust-axum-service")
        .with_collector_endpoint("http://localhost:9411/api/v2/spans")
        .install_batch(opentelemetry_sdk::runtime::Tokio)
        .expect("Failed to initialize tracing pipeline");

    let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer);

    tracing::subscriber::set_global_default(Registry::default().with(otel_layer))
        .expect("setting default subscriber failed");
}

Cargo.toml

[dependencies]
axum = "0.6"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tracing = "0.1"
tracing-subscriber = "0.3"
tracing-opentelemetry = "0.28.0"
opentelemetry = { version = "0.27" }
opentelemetry-zipkin = {version = "0.27.0", features = ["reqwest-client"]}
opentelemetry_sdk = {version = "0.27.0", features = ["rt-tokio"]}
opentelemetry-http = "0.27.0"
reqwest = "0.12.9"

Stack Trace

thread 'main' panicked at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/blocking/shutdown.rs:51:21:
Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context.
stack backtrace:
   0: rust_begin_unwind
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:645:5
   1: core::panicking::panic_fmt
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:72:14
   2: tokio::runtime::blocking::shutdown::Receiver::wait
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/blocking/shutdown.rs:51:21
   3: tokio::runtime::blocking::pool::BlockingPool::shutdown
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/blocking/pool.rs:263:12
   4: <tokio::runtime::blocking::pool::BlockingPool as core::ops::drop::Drop>::drop
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/blocking/pool.rs:284:9
   5: core::ptr::drop_in_place<tokio::runtime::blocking::pool::BlockingPool>
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ptr/mod.rs:498:1
   6: core::ptr::drop_in_place<tokio::runtime::runtime::Runtime>
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ptr/mod.rs:498:1
   7: reqwest::blocking::wait::enter
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.12.9/src/blocking/wait.rs:76:21
   8: reqwest::blocking::wait::timeout
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.12.9/src/blocking/wait.rs:13:5
   9: reqwest::blocking::client::ClientHandle::new
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.12.9/src/blocking/client.rs:1208:15
  10: reqwest::blocking::client::ClientBuilder::build
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.12.9/src/blocking/client.rs:106:9
  11: <opentelemetry_zipkin::exporter::ZipkinPipelineBuilder as core::default::Default>::default
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/opentelemetry-zipkin-0.27.0/src/exporter/mod.rs:61:17
  12: opentelemetry_zipkin::exporter::new_pipeline
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/opentelemetry-zipkin-0.27.0/src/exporter/mod.rs:42:5
  13: web_server::init_tracing
             at ./src/main.rs:47:18
  14: web_server::main::{{closure}}
             at ./src/main.rs:15:5
  15: tokio::runtime::park::CachedParkThread::block_on::{{closure}}
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/park.rs:281:63
  16: tokio::runtime::coop::with_budget
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/coop.rs:107:5
  17: tokio::runtime::coop::budget
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/coop.rs:73:5
  18: tokio::runtime::park::CachedParkThread::block_on
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/park.rs:281:31
  19: tokio::runtime::context::blocking::BlockingRegionGuard::block_on
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/context/blocking.rs:66:9
  20: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::{{closure}}
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/multi_thread/mod.rs:87:13
  21: tokio::runtime::context::runtime::enter_runtime
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/context/runtime.rs:65:16
  22: tokio::runtime::scheduler::multi_thread::MultiThread::block_on
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/multi_thread/mod.rs:86:9
  23: tokio::runtime::runtime::Runtime::block_on_inner
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/runtime.rs:370:45
  24: tokio::runtime::runtime::Runtime::block_on
             at /Users/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/runtime.rs:342:13
  25: web_server::main
             at ./src/main.rs:24:5
  26: core::ops::function::FnOnce::call_once
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5

Judging from the stack trace, you are using reqwest's blocking API within an async context.

This did point me to the default-features = false setting in opentelemetry-zipkin which does resolve the issue.

Yeah, looks like reqwest-blocking-client is a default feature which overrides the (non-default) reqwest-client feature. (Probably they wish Cargo had exclusive features, but that still seems like an odd arrangement to me.)