Description
While testing #224, I came across an issue.
Steps to reproduce
- Checkout the PR (at the point of writing ffa96df).
- Open
examples/stdout.rs
and change:+ #[tokio::main] + async fn main() { - fn main() {
- Run
cargo run --example stdout
and observe the span being printed to the console. - Run
cargo run --example stdout --features tokio
and observe that nothing is printed. With the tokio feature enabled it used the BatchSpanProcessor setup by TraceProvider::with_exporter.
Analysis
I reproduced it on master as well and with a few print statements found that the BatchSpanProcessorWorker
is immediately dropped after calling with_exporter.
See my experiments here: 13fc775
The reason is that with_exporter uses either tokio::task::spawn_blocking
or async_std::task::spawn_blocking
(see sdk::TraceProvider). Both of those expect a blocking function, not a function returning a future. This means the BatchSpanProcessorWorker is never polled.
Possible solution
I assume the reason for using spawn_blocking
is that the exporters currently run blocking, so it's good to run on a special thread for blocking work. The solution for the problem then is most likely to execute the future using block_on:
let spawn = |future| {
tokio::task::spawn_blocking(|| {
futures::executor::block_on(future);
// or tokio::runtime::Handle::current().block_on(future)
// or async_std::task::block_on(future)
})
};
let batch = sdk::BatchSpanProcessor::builder(exporter, spawn, async_std::stream::interval);
If I do this, however, the program never exits. You can test this with the above linked example. The BatchSpanProcessorWorker just keeps running because it does never receive a shotdown message.
I'm not sure why, yet. I think the provider should be dropped and then notify all registered span processors. But that does not seem to happen.
If I manually call shutdown for all span processors, the worker stops properly, exports the remaining spans, and then the program exits.
I'm happy to work on a fix, but I would like to hear your thoughts first. What's the best way to proceed here?