From 2ae3ea0cfe1c1fe74e79d7c8ea31391307e10464 Mon Sep 17 00:00:00 2001 From: Kris Hicks Date: Fri, 31 Jul 2026 09:50:07 -0700 Subject: [PATCH] fix(server): isolate otel tracing test exporters Give each span-assertion test its own thread-scoped in-memory exporter so parallel tests cannot contaminate or reset captured spans. Keep a bare global tracing registry only to preserve callsite interest, and serialize scoped subscriber changes because tracing caches that interest process-wide. Remove the test-only OTLP collector, polling delivery barrier, transport-specific test, and direct opentelemetry-proto dependency. Seed the expected persistence conflict before tracing begins so its assertion window contains only the operation under test. Signed-off-by: Kris Hicks --- Cargo.lock | 1 - crates/openshell-server/Cargo.toml | 3 - crates/openshell-server/src/compute/mod.rs | 42 ++-- crates/openshell-server/src/grpc/sandbox.rs | 4 +- crates/openshell-server/src/multiplex.rs | 38 ++-- crates/openshell-server/src/otel_tracing.rs | 202 +++--------------- .../openshell-server/src/persistence/tests.rs | 58 ++--- .../openshell-server/src/provider_refresh.rs | 8 +- 8 files changed, 111 insertions(+), 245 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d16fb1f0f3..528309a970 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4201,7 +4201,6 @@ dependencies = [ "openshell-supervisor-middleware", "openshell-supervisor-middleware-builtins", "opentelemetry", - "opentelemetry-proto", "opentelemetry_sdk", "petname", "pin-project-lite", diff --git a/crates/openshell-server/Cargo.toml b/crates/openshell-server/Cargo.toml index 896817e07e..8f4dbeb859 100644 --- a/crates/openshell-server/Cargo.toml +++ b/crates/openshell-server/Cargo.toml @@ -128,8 +128,5 @@ wiremock = "0.6" # `testing` provides InMemorySpanExporter, so span assertions do not need a # collector, a network hop, or a flush barrier. opentelemetry_sdk = { workspace = true, features = ["testing"] } -# Supports asserting that the gateway sends spans over OTLP. -opentelemetry-proto = { version = "0.32", default-features = false, features = ["gen-tonic", "trace"] } - [lints] workspace = true diff --git a/crates/openshell-server/src/compute/mod.rs b/crates/openshell-server/src/compute/mod.rs index 8ff14f940d..25a2655a74 100644 --- a/crates/openshell-server/src/compute/mod.rs +++ b/crates/openshell-server/src/compute/mod.rs @@ -4222,12 +4222,12 @@ mod tests { async fn driver_calls_export_spans_with_parents() { use tracing::Instrument as _; - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let runtime = test_runtime(Arc::new(TestDriver::default())).await; let sandbox = sandbox_record("sb-trace", "sandbox-trace", SandboxPhase::Provisioning); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); async { runtime .create_sandbox(sandbox, None) @@ -4238,14 +4238,14 @@ mod tests { .await; let driver_span = traced.span_with("driver.create_sandbox", "sandbox.id", "sb-trace"); - test_collector::assert_has_parent(&driver_span); + test_exporter::assert_has_parent(&driver_span); assert_eq!( - test_collector::attribute(&driver_span, "driver.name").as_deref(), + test_exporter::attribute(&driver_span, "driver.name").as_deref(), Some("test-driver"), "the span names which driver was called" ); assert_eq!( - test_collector::attribute(&driver_span, "sandbox.id").as_deref(), + test_exporter::attribute(&driver_span, "sandbox.id").as_deref(), Some("sb-trace"), ); assert_eq!( @@ -4269,7 +4269,7 @@ mod tests { async fn failed_driver_calls_are_marked_on_the_span() { use tracing::Instrument as _; - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; /// A driver that behaves normally except that creates fail, so the /// test exercises only the failure attribute. @@ -4351,7 +4351,7 @@ mod tests { let runtime = test_runtime(Arc::new(FailingDriver::default())).await; let sandbox = sandbox_record("sb-fail", "sandbox-fail", SandboxPhase::Provisioning); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); async { runtime .create_sandbox(sandbox, None) @@ -4372,7 +4372,7 @@ mod tests { driver_span.status ); assert_eq!( - test_collector::attribute(&driver_span, "grpc.code").as_deref(), + test_exporter::attribute(&driver_span, "grpc.code").as_deref(), Some("14"), "the gRPC code names the cause without reading the message" ); @@ -6135,14 +6135,14 @@ mod tests { /// they trigger land outside the request that caused them. #[tokio::test] async fn driver_watch_events_are_roots_and_store_operations_have_parents() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let runtime = test_runtime(Arc::new(TestDriver::default())).await; let sandbox = sandbox_record("sb-1", "sandbox-a", SandboxPhase::Ready); runtime.store.put_message(&sandbox).await.unwrap(); runtime.sandbox_index.update_from_sandbox(&sandbox); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); runtime .apply_watch_event(deleted_watch_event("sb-1")) .await @@ -6159,9 +6159,9 @@ mod tests { ) }); - test_collector::assert_is_root(root); + test_exporter::assert_is_root(root); assert_eq!( - test_collector::attribute(root, "sandbox.id").as_deref(), + test_exporter::attribute(root, "sandbox.id").as_deref(), Some("sb-1"), "the span names which sandbox the driver reported on" ); @@ -6173,21 +6173,21 @@ mod tests { && span.span_context.trace_id() == root.span_context.trace_id() }) .expect("the event records its store operation"); - test_collector::assert_has_parent(store_span); + test_exporter::assert_has_parent(store_span); } /// The reconciler runs on a timer with no inbound request, so without a /// span of its own each store call becomes its own anonymous trace. #[tokio::test] async fn reconcile_sweeps_are_roots_and_operations_have_parents() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let runtime = test_runtime(Arc::new(TestDriver::default())).await; let sandbox = sandbox_record("sb-1", "sandbox-a", SandboxPhase::Provisioning); runtime.store.put_message(&sandbox).await.unwrap(); runtime.sandbox_index.update_from_sandbox(&sandbox); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); runtime .reconcile_store_with_backend(Duration::ZERO) .await @@ -6215,7 +6215,7 @@ mod tests { }) }) .expect("the sweep records its driver and store operations"); - test_collector::assert_is_root(root); + test_exporter::assert_is_root(root); let driver_span = spans .iter() @@ -6224,7 +6224,7 @@ mod tests { && span.span_context.trace_id() == root.span_context.trace_id() }) .expect("the sweep records its driver call"); - test_collector::assert_has_parent(driver_span); + test_exporter::assert_has_parent(driver_span); let store_span = spans .iter() .find(|span| { @@ -6232,7 +6232,7 @@ mod tests { && span.span_context.trace_id() == root.span_context.trace_id() }) .expect("the sweep records its store operation"); - test_collector::assert_has_parent(store_span); + test_exporter::assert_has_parent(store_span); } #[tokio::test] @@ -6644,10 +6644,10 @@ mod tests { #[tokio::test] async fn compute_driver_initialization_records_an_operation_span() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let store = Arc::new(Store::connect("sqlite::memory:").await.unwrap()); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); ComputeRuntime::from_driver( "test-driver".to_string(), Arc::new(TestDriver::default()), @@ -6664,7 +6664,7 @@ mod tests { .unwrap(); let initialization = traced.span_with("driver.initialize", "driver.name", "test-driver"); - test_collector::assert_is_root(&initialization); + test_exporter::assert_is_root(&initialization); } #[tokio::test] diff --git a/crates/openshell-server/src/grpc/sandbox.rs b/crates/openshell-server/src/grpc/sandbox.rs index 405932f037..8dc385e889 100644 --- a/crates/openshell-server/src/grpc/sandbox.rs +++ b/crates/openshell-server/src/grpc/sandbox.rs @@ -2570,7 +2570,7 @@ mod tests { #[tokio::test] async fn watch_producer_releases_request_span_when_client_disconnects() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; use tokio_stream::StreamExt as _; use tracing::Instrument as _; @@ -2578,7 +2578,7 @@ mod tests { let sandbox = test_sandbox("watched", Vec::new()); state.store.put_message(&sandbox).await.unwrap(); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); let request_span = tracing::info_span!("disconnected_watch_request"); let response = handle_watch_sandbox( &state, diff --git a/crates/openshell-server/src/multiplex.rs b/crates/openshell-server/src/multiplex.rs index ce3015f91f..bf06d2c537 100644 --- a/crates/openshell-server/src/multiplex.rs +++ b/crates/openshell-server/src/multiplex.rs @@ -2130,7 +2130,7 @@ mod tests { tracing_subscriber::registry().with(fmt_layer) }; { - let _traced = crate::otel_tracing::test_collector::install_scoped(subscriber); + let _traced = crate::otel_tracing::test_exporter::install_scoped(subscriber); let req = Request::builder() .uri("/test-path") @@ -2154,9 +2154,9 @@ mod tests { /// correlated with the gateway's logs. #[tokio::test] async fn request_span_exports_over_otlp_with_request_id() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); let req = Request::builder() .uri("/openshell.v1.OpenShell/CreateSandbox") .header("x-request-id", "otlp-req-id-9876") @@ -2177,11 +2177,11 @@ mod tests { ) }); assert_eq!( - test_collector::attribute(span, "request_id").as_deref(), + test_exporter::attribute(span, "request_id").as_deref(), Some("otlp-req-id-9876"), ); assert_eq!( - test_collector::attribute(span, "path").as_deref(), + test_exporter::attribute(span, "path").as_deref(), Some("/openshell.v1.OpenShell/CreateSandbox"), ); assert_eq!( @@ -2189,26 +2189,26 @@ mod tests { opentelemetry::trace::SpanKind::Server, "trace UIs lay this out as a served call, not an internal operation" ); - test_collector::assert_is_root(span); + test_exporter::assert_is_root(span); assert_eq!( - test_collector::attribute(span, "rpc.system").as_deref(), + test_exporter::attribute(span, "rpc.system").as_deref(), Some("grpc"), ); assert_eq!( - test_collector::attribute(span, "rpc.service").as_deref(), + test_exporter::attribute(span, "rpc.service").as_deref(), Some("openshell.v1.OpenShell"), ); assert_eq!( - test_collector::attribute(span, "rpc.method").as_deref(), + test_exporter::attribute(span, "rpc.method").as_deref(), Some("CreateSandbox"), ); } #[tokio::test] async fn request_span_continues_the_incoming_trace() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); let req = Request::builder() .uri("/openshell.v1.OpenShell/CreateSandbox") .header( @@ -2241,9 +2241,9 @@ mod tests { /// trace UI, which keys off span status rather than a logged field. #[tokio::test] async fn request_spans_record_the_response_outcome() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); for (path, status) in [ ("/openshell.v1.OpenShell/CreateSandbox", 500), ("/openshell.v1.OpenShell/ListSandboxes", 200), @@ -2274,7 +2274,7 @@ mod tests { .expect("successful request span recorded"); assert_eq!( - test_collector::attribute(failed, "http.response.status_code").as_deref(), + test_exporter::attribute(failed, "http.response.status_code").as_deref(), Some("500"), "the response status is an attribute, not only a log field" ); @@ -2292,9 +2292,9 @@ mod tests { #[tokio::test] async fn request_span_records_grpc_status_from_trailers() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); let req = Request::builder() .uri("/openshell.v1.OpenShell/CreateSandbox") .body(Empty::::new()) @@ -2311,7 +2311,7 @@ mod tests { "CreateSandbox", ); assert_eq!( - test_collector::attribute(&span, "rpc.grpc.status_code").as_deref(), + test_exporter::attribute(&span, "rpc.grpc.status_code").as_deref(), Some("13") ); assert!( @@ -2324,7 +2324,7 @@ mod tests { /// named for its RPC or HTTP method. #[tokio::test] async fn each_entrypoint_gets_its_own_root_span() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let paths = [ "/openshell.v1.OpenShell/CreateSandbox", @@ -2334,7 +2334,7 @@ mod tests { "/metrics", ]; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); for path in paths { let req = Request::builder() .uri(path) diff --git a/crates/openshell-server/src/otel_tracing.rs b/crates/openshell-server/src/otel_tracing.rs index dd143f22b4..58b4cdf804 100644 --- a/crates/openshell-server/src/otel_tracing.rs +++ b/crates/openshell-server/src/otel_tracing.rs @@ -105,66 +105,48 @@ pub fn mark_error(span: &tracing::Span) { span.record("otel.status_code", "ERROR"); } -/// In-process OTLP/gRPC trace collector, for tests that need to assert what -/// the gateway actually put on the wire. +/// Isolated in-memory span exporters for tracing tests. #[cfg(test)] -pub mod test_collector { - use std::net::SocketAddr; - use std::sync::{Arc, Mutex}; - - use opentelemetry_proto::tonic::collector::trace::v1::{ - ExportTraceServiceRequest, ExportTraceServiceResponse, - trace_service_server::{TraceService, TraceServiceServer}, - }; - use opentelemetry_proto::tonic::trace::v1::Span; - - /// Spans received by a running [`start`] collector. - pub type Received = Arc>>; - - /// The one exporter every traced test reads, installed for the whole test - /// binary and never swapped. +pub mod test_exporter { + /// Installs a process-wide registry before any scoped test subscriber is + /// used. /// - /// A per-test subscriber cannot work here: `tracing` caches callsite - /// interest process-wide, so a callsite first hit by an untraced test - /// stays dark for every later one. - static EXPORTER: std::sync::LazyLock = - std::sync::LazyLock::new(|| { - use tracing_subscriber::layer::SubscriberExt as _; - - let exporter = opentelemetry_sdk::trace::InMemorySpanExporterBuilder::new().build(); - let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() - .with_simple_exporter(exporter.clone()) - .build(); - let subscriber = tracing_subscriber::registry().with(super::layer(&provider)); - tracing::subscriber::set_global_default(subscriber) - .expect("test subscriber installs once"); - // Leaked so the provider outlives every span the binary records; - // dropping it would shut the exporter down mid-suite. - std::mem::forget(provider); - exporter - }); - - /// Captures spans until the returned guard is dropped. + /// `tracing` caches callsite interest process-wide. The registry keeps + /// callsites enabled without exporting spans from unrelated tests. + static INITIALIZED: std::sync::LazyLock<()> = std::sync::LazyLock::new(|| { + tracing::subscriber::set_global_default(tracing_subscriber::registry()) + .expect("test subscriber installs once"); + }); + + /// Captures spans from the current test thread until the guard is dropped. /// - /// Serialized on [`crate::TEST_TRACING_LOCK`] because the exporter it - /// clears is shared by the whole binary. + /// Subscriber changes remain serialized because `tracing` caches callsite + /// interest process-wide. The exporter itself is private to this guard, so + /// concurrent non-tracing tests cannot contaminate or reset its spans. #[must_use] pub fn install_traced() -> TracingTestGuard { + use tracing_subscriber::layer::SubscriberExt as _; + let lock = crate::TEST_TRACING_LOCK .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - EXPORTER.reset(); + std::sync::LazyLock::force(&INITIALIZED); + let exporter = opentelemetry_sdk::trace::InMemorySpanExporterBuilder::new().build(); + let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + let subscriber = tracing_subscriber::registry().with(super::layer(&provider)); + let dispatch = tracing::Dispatch::new(subscriber); TracingTestGuard { + _default: tracing::dispatcher::set_default(&dispatch), + _provider: provider, + exporter, _lock: lock, - exporter: &EXPORTER, } } impl TracingTestGuard { - /// Every span recorded since [`install_traced`], including any written - /// concurrently by other callers. - /// - /// Prefer [`Self::spans_named`] or [`Self::span_with`] to select spans. + /// Every span recorded by this test's in-memory exporter. pub fn finished_spans(&self) -> Vec { self.exporter.get_finished_spans().expect("in-memory spans") } @@ -226,7 +208,7 @@ pub mod test_collector { let lock = crate::TEST_TRACING_LOCK .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - std::sync::LazyLock::force(&EXPORTER); + std::sync::LazyLock::force(&INITIALIZED); ScopedTracingTestGuard { _default: tracing::dispatcher::set_default(&subscriber.into()), _lock: lock, @@ -240,72 +222,10 @@ pub mod test_collector { } pub struct TracingTestGuard { + _default: tracing::dispatcher::DefaultGuard, + _provider: opentelemetry_sdk::trace::SdkTracerProvider, + exporter: opentelemetry_sdk::trace::InMemorySpanExporter, _lock: std::sync::MutexGuard<'static, ()>, - exporter: &'static opentelemetry_sdk::trace::InMemorySpanExporter, - } - - #[derive(Clone)] - struct Collector { - spans: Received, - } - - #[tonic::async_trait] - impl TraceService for Collector { - async fn export( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - let mut spans = self.spans.lock().expect("collector lock"); - for resource_span in request.into_inner().resource_spans { - for scope_span in resource_span.scope_spans { - spans.extend(scope_span.spans); - } - } - Ok(tonic::Response::new(ExportTraceServiceResponse::default())) - } - } - - /// Start a collector on an ephemeral port. Returns its address and a - /// handle to the spans it receives. - pub async fn start() -> (SocketAddr, Received) { - let spans: Received = Arc::new(Mutex::new(Vec::new())); - let listener = tokio::net::TcpListener::bind("127.0.0.1:0") - .await - .expect("bind collector"); - let addr = listener.local_addr().expect("collector addr"); - - let service = Collector { - spans: Arc::clone(&spans), - }; - tokio::spawn(async move { - tonic::transport::Server::builder() - .add_service(TraceServiceServer::new(service)) - .serve_with_incoming(tokio_stream::wrappers::TcpListenerStream::new(listener)) - .await - .ok(); - }); - - (addr, spans) - } - - /// Wait for spans named `expected` to arrive, returning everything - /// received. - /// - /// `SdkTracerProvider::force_flush` is not a delivery barrier — it reports - /// `Ok` even when the collector is unreachable — so asserting on the - /// collector's contents immediately after it is a race. - pub async fn wait_for_spans(received: &Received, expected: &[&str]) -> Vec { - for _ in 0..200 { - let spans = received.lock().expect("collector lock").clone(); - if expected - .iter() - .all(|name| spans.iter().any(|s| s.name == *name)) - { - return spans; - } - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - } - received.lock().expect("collector lock").clone() } /// Value of `key` on an in-memory span, if present. @@ -315,21 +235,6 @@ pub mod test_collector { .find(|kv| kv.key.as_str() == key) .map(|kv| kv.value.to_string()) } - - /// Value of `key` on `span`, if present as a string attribute. - pub fn string_attribute(span: &Span, key: &str) -> Option { - use opentelemetry_proto::tonic::common::v1::any_value::Value; - - span.attributes - .iter() - .find(|kv| kv.key == key) - .and_then(|kv| kv.value.as_ref()) - .and_then(|v| v.value.as_ref()) - .map(|v| match v { - Value::StringValue(s) => s.clone(), - other => format!("{other:?}"), - }) - } } #[cfg(test)] @@ -530,7 +435,7 @@ mod tests { #[tokio::test] async fn tracing_events_are_not_exported() { - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); let span = tracing::info_span!("outer"); let entered = span.enter(); tracing::warn!(target: "opentelemetry-otlp", "export failed"); @@ -549,45 +454,4 @@ mod tests { "structured log events stay on the logging paths" ); } - - #[tokio::test(flavor = "multi_thread")] - async fn tracing_spans_reach_the_collector_over_otlp() { - let (addr, received) = test_collector::start().await; - - let cfg = OtlpConfig { - endpoint: format!("http://{addr}"), - service_name: None, - }; - let provider = build_provider(&cfg).expect("provider builds"); - - { - // Its own subscriber, not the shared in-memory one: this test - // asserts on what reaches a real collector over the wire. - use tracing_subscriber::layer::SubscriberExt as _; - let subscriber = tracing_subscriber::registry().with(layer(&provider)); - let _traced = test_collector::install_scoped(subscriber); - let span = tracing::info_span!("create_sandbox", sandbox_id = "sb-otlp"); - let _entered = span.enter(); - } - - provider.force_flush().expect("flush spans"); - - let spans = test_collector::wait_for_spans(&received, &["create_sandbox"]).await; - let span = spans - .iter() - .find(|s| s.name == "create_sandbox") - .unwrap_or_else(|| { - panic!( - "collector received the exported span, got {:?}", - spans.iter().map(|s| &s.name).collect::>() - ) - }); - assert_eq!( - test_collector::string_attribute(span, "sandbox_id").as_deref(), - Some("sb-otlp"), - "tracing fields are exported as span attributes" - ); - - provider.shutdown().ok(); - } } diff --git a/crates/openshell-server/src/persistence/tests.rs b/crates/openshell-server/src/persistence/tests.rs index 539dd2c6ff..ebf15b0d21 100644 --- a/crates/openshell-server/src/persistence/tests.rs +++ b/crates/openshell-server/src/persistence/tests.rs @@ -12,10 +12,10 @@ use std::collections::HashMap as StdHashMap; /// span that merely happened to return nothing. #[tokio::test] async fn failed_store_calls_are_marked_on_the_span() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let store = test_store().await; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); store.close_for_test().await; store .get("sandbox", "failed-store-call") @@ -36,26 +36,32 @@ async fn failed_store_calls_are_marked_on_the_span() { /// every gateway restart, exports as a failure. #[tokio::test] async fn expected_conflicts_leave_the_span_unmarked() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let store = test_store().await; - let traced = test_collector::install_traced(); - let put = async |id: &str| { - store - .put_if( - "workspace", - id, - "expected-conflict", - "", - b"payload", - None, - super::WriteCondition::MustCreate, - ) - .await - }; + store + .put( + "workspace", + "expected-conflict-first", + "expected-conflict", + "", + b"payload", + None, + ) + .await + .expect("seed conflicting record"); - put("expected-conflict-first").await.expect("first write"); - put("expected-conflict-second") + let traced = test_exporter::install_traced(); + store + .put_if( + "workspace", + "expected-conflict-second", + "expected-conflict", + "", + b"payload", + None, + super::WriteCondition::MustCreate, + ) .await .expect_err("the name is already taken"); @@ -73,7 +79,7 @@ async fn expected_conflicts_leave_the_span_unmarked() { /// each call touched is carried as attributes. #[tokio::test] async fn store_spans_record_what_they_touched_as_attributes() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let store = test_store().await; store @@ -81,7 +87,7 @@ async fn store_spans_record_what_they_touched_as_attributes() { .await .unwrap(); - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); store.get("sandbox", "abc").await.unwrap(); store .get_by_name("sandbox", "default", "my-sandbox") @@ -91,7 +97,7 @@ async fn store_spans_record_what_they_touched_as_attributes() { let by_name = traced.span_with("store.get_by_name", "object.name", "my-sandbox"); assert_eq!( - test_collector::attribute(&by_name, "object_type").as_deref(), + test_exporter::attribute(&by_name, "object_type").as_deref(), Some("sandbox"), "the span records which type it queried" ); @@ -2179,11 +2185,11 @@ async fn membership_selector_escapes_adversarial_label_key() { async fn store_operations_export_spans_with_parents() { use tracing::Instrument as _; - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let store = test_store().await; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); async { store .list("sandbox", "default", 10, 0) @@ -2211,9 +2217,9 @@ async fn store_operations_export_spans_with_parents() { ) }); - test_collector::assert_has_parent(child); + test_exporter::assert_has_parent(child); assert_eq!( - test_collector::attribute(child, "object_type").as_deref(), + test_exporter::attribute(child, "object_type").as_deref(), Some("sandbox"), "the store span records what it queried" ); diff --git a/crates/openshell-server/src/provider_refresh.rs b/crates/openshell-server/src/provider_refresh.rs index f70801221d..a03fdb0b17 100644 --- a/crates/openshell-server/src/provider_refresh.rs +++ b/crates/openshell-server/src/provider_refresh.rs @@ -1527,11 +1527,11 @@ mod tests { /// of its own its store reads export as anonymous single-span traces. #[tokio::test] async fn refresh_worker_ticks_are_roots_and_store_operations_have_parents() { - use crate::otel_tracing::test_collector; + use crate::otel_tracing::test_exporter; let store = test_store().await; - let traced = test_collector::install_traced(); + let traced = test_exporter::install_traced(); run_refresh_worker_tick(&store).await.unwrap(); let spans = traced.finished_spans(); @@ -1545,7 +1545,7 @@ mod tests { ) }); - test_collector::assert_is_root(root); + test_exporter::assert_is_root(root); let store_span = spans .iter() .find(|span| { @@ -1553,7 +1553,7 @@ mod tests { && span.span_context.trace_id() == root.span_context.trace_id() }) .expect("the tick records its store operation"); - test_collector::assert_has_parent(store_span); + test_exporter::assert_has_parent(store_span); } #[test]