-
Notifications
You must be signed in to change notification settings - Fork 437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug]: Shutdown doesn't flush when used with global subscriber #1961
Comments
That's expected behavior. The |
It's kind of misleading for
If current behavior (no shutdown if there are other references) is intentional and should remain, then I think it'd be helpful to change the documentation (explicitly state that it's not going to do anything if there's more references to the tracer provider, suggest calling
In previous |
|
Here's a test against #![cfg(feature = "rt-tokio")]
use futures_util::future::BoxFuture;
use opentelemetry::global as otel_global;
use opentelemetry::trace::{TracerProvider as _, Tracer as _};
use opentelemetry_sdk::{
export::trace::{ExportResult, SpanData, SpanExporter},
runtime,
trace::TracerProvider,
};
use tokio::runtime::Runtime;
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug, Default)]
struct TestExporter(Arc<Mutex<Vec<SpanData>>>);
impl SpanExporter for TestExporter {
fn export(&mut self, mut batch: Vec<SpanData>) -> BoxFuture<'static, ExportResult> {
let spans = self.0.clone();
Box::pin(async move {
if let Ok(mut inner) = spans.lock() {
inner.append(&mut batch);
}
Ok(())
})
}
}
fn test_tracer(runtime: &Runtime) -> (TracerProvider, TestExporter) {
let _guard = runtime.enter();
let exporter = TestExporter::default();
let provider = TracerProvider::builder()
.with_batch_exporter(exporter.clone(), runtime::Tokio)
.build();
(provider, exporter)
}
#[test]
fn shutdown_global() {
let rt = Runtime::new().unwrap();
let (provider, exporter) = test_tracer(&rt);
otel_global::set_tracer_provider(provider);
let tracer = otel_global::tracer("test");
for _ in 0..1000 {
tracer.start("test_span");
}
// drop(tracer);
// Should flush all batched telemetry spans
otel_global::shutdown_tracer_provider();
let spans = exporter.0.lock().unwrap();
assert_eq!(spans.len(), 1000);
} Dropping the tracer before the call to As currently implemented, the behavior of |
Here's a test to exercise this. However, it does produce an error printout when the tracer instance is kept alive past the shutdown. #[test]
fn shutdown_in_scope() {
let rt = Runtime::new().unwrap();
let (provider, exporter) = test_tracer(&rt);
let tracer = provider.tracer("test");
for _ in 0..1000 {
tracer.start("test_span");
}
// drop(tracer);
// Should flush all batched telemetry spans
provider.shutdown().unwrap();
let spans = exporter.0.lock().unwrap();
assert_eq!(spans.len(), 1000);
} There is also a case of a lockup in the
So it looks like we're not safe with the |
What happened?
As mentioned in #1625 -
Tracer
now holds strong reference toTracerProvider
.When opentelemetry used as a layer with global tracing subscriber it is now impossible to shutdown properly (it only decrements a reference, but doesn't execute Drop).
As a result some spans are missing, flattened, etc.
EDIT: Possible workaround is to flush manually:
API Version
0.24.0
SDK Version
0.24.1
What Exporter(s) are you seeing the problem on?
OTLP
Relevant log output
No response
The text was updated successfully, but these errors were encountered: