use std::sync::{Arc, OnceLock};
use opentelemetry::global;
use opentelemetry_sdk::trace::{
InMemorySpanExporter, SdkTracerProvider, SimpleSpanProcessor, SpanData,
};
pub(crate) struct TestSpans {
provider: SdkTracerProvider,
exporter: Arc<InMemorySpanExporter>,
_guard: tokio::sync::OwnedMutexGuard<()>,
}
pub(crate) async fn test_spans() -> TestSpans {
static HARNESS: OnceLock<(SdkTracerProvider, Arc<InMemorySpanExporter>)> = OnceLock::new();
static LOCK: OnceLock<Arc<tokio::sync::Mutex<()>>> = OnceLock::new();
let (provider, exporter) = HARNESS.get_or_init(|| {
let exporter = Arc::new(InMemorySpanExporter::default());
let provider = SdkTracerProvider::builder()
.with_span_processor(SimpleSpanProcessor::new(exporter.as_ref().clone()))
.build();
global::set_tracer_provider(provider.clone());
(provider, exporter)
});
let guard = LOCK
.get_or_init(|| Arc::new(tokio::sync::Mutex::new(())))
.clone()
.lock_owned()
.await;
exporter.reset();
TestSpans {
provider: provider.clone(),
exporter: Arc::clone(exporter),
_guard: guard,
}
}
pub(crate) fn finish(spans: TestSpans) -> Vec<SpanData> {
spans.provider.force_flush().expect("flush exported spans"); spans
.exporter
.get_finished_spans()
.expect("read exported spans") }