From 17855be169024c7ac961e3916958c844bb695198 Mon Sep 17 00:00:00 2001 From: Takahiro Ebato Date: Tue, 31 Dec 2024 16:53:33 +0900 Subject: [PATCH] Retain empty tracer name as is instead of using default name (#2486) Co-authored-by: Cijo Thomas --- opentelemetry-sdk/CHANGELOG.md | 4 +++ opentelemetry-sdk/src/trace/mod.rs | 44 ++++++++++++++++++++++++- opentelemetry-sdk/src/trace/provider.rs | 14 +++----- 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index 937e3b0c6b..b7a3f2a0da 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -211,6 +211,10 @@ metadata, a feature introduced in version 0.1.40. [#2418](https://github.com/ope - Continue enabling one of the async runtime feature flags: `rt-tokio`, `rt-tokio-current-thread`, or `rt-async-std`. +- Bug fix: Empty Tracer names are retained as-is instead of replacing with + "rust.opentelemetry.io/sdk/tracer" + [#2486](https://github.com/open-telemetry/opentelemetry-rust/pull/2486) + ## 0.27.1 Released 2024-Nov-27 diff --git a/opentelemetry-sdk/src/trace/mod.rs b/opentelemetry-sdk/src/trace/mod.rs index 4acf809022..e714364a85 100644 --- a/opentelemetry-sdk/src/trace/mod.rs +++ b/opentelemetry-sdk/src/trace/mod.rs @@ -48,7 +48,7 @@ mod tests { use super::*; use crate::{ - testing::trace::InMemorySpanExporterBuilder, + testing::trace::{InMemorySpanExporter, InMemorySpanExporterBuilder}, trace::span_limit::{DEFAULT_MAX_EVENT_PER_SPAN, DEFAULT_MAX_LINKS_PER_SPAN}, }; use opentelemetry::trace::{ @@ -342,4 +342,46 @@ mod tests { .attributes() .eq(&[KeyValue::new("test_k", "test_v")])); } + + #[tokio::test(flavor = "multi_thread", worker_threads = 1)] + async fn empty_tracer_name_retained() { + async fn tracer_name_retained_helper( + tracer: super::Tracer, + provider: TracerProvider, + exporter: InMemorySpanExporter, + ) { + // Act + tracer.start("my_span").end(); + + // Force flush to ensure spans are exported + provider.force_flush().into_iter().for_each(|result| { + result.expect("failed to flush spans"); + }); + + // Assert + let finished_spans = exporter + .get_finished_spans() + .expect("spans are expected to be exported."); + assert_eq!(finished_spans.len(), 1, "There should be a single span"); + + let tracer_name = finished_spans[0].instrumentation_scope.name(); + assert_eq!(tracer_name, "", "The tracer name should be an empty string"); + + exporter.reset(); + } + + let exporter = InMemorySpanExporter::default(); + let span_processor = SimpleSpanProcessor::new(Box::new(exporter.clone())); + let tracer_provider = TracerProvider::builder() + .with_span_processor(span_processor) + .build(); + + // Test Tracer creation in 2 ways, both with empty string as tracer name + let tracer1 = tracer_provider.tracer(""); + tracer_name_retained_helper(tracer1, tracer_provider.clone(), exporter.clone()).await; + + let tracer_scope = InstrumentationScope::builder("").build(); + let tracer2 = tracer_provider.tracer_with_scope(tracer_scope); + tracer_name_retained_helper(tracer2, tracer_provider, exporter).await; + } } diff --git a/opentelemetry-sdk/src/trace/provider.rs b/opentelemetry-sdk/src/trace/provider.rs index 6d6f35fd94..447404cbb0 100644 --- a/opentelemetry-sdk/src/trace/provider.rs +++ b/opentelemetry-sdk/src/trace/provider.rs @@ -68,8 +68,8 @@ use crate::trace::{ use crate::Resource; use crate::{export::trace::SpanExporter, trace::SpanProcessor}; use opentelemetry::trace::TraceError; -use opentelemetry::InstrumentationScope; use opentelemetry::{otel_debug, trace::TraceResult}; +use opentelemetry::{otel_info, InstrumentationScope}; use std::borrow::Cow; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; @@ -252,20 +252,11 @@ impl TracerProvider { } } -/// Default tracer name if empty string is provided. -const DEFAULT_COMPONENT_NAME: &str = "rust.opentelemetry.io/sdk/tracer"; - impl opentelemetry::trace::TracerProvider for TracerProvider { /// This implementation of `TracerProvider` produces `Tracer` instances. type Tracer = Tracer; fn tracer(&self, name: impl Into>) -> Self::Tracer { - let mut name = name.into(); - - if name.is_empty() { - name = Cow::Borrowed(DEFAULT_COMPONENT_NAME) - }; - let scope = InstrumentationScope::builder(name).build(); self.tracer_with_scope(scope) } @@ -274,6 +265,9 @@ impl opentelemetry::trace::TracerProvider for TracerProvider { if self.inner.is_shutdown.load(Ordering::Relaxed) { return Tracer::new(scope, noop_tracer_provider().clone()); } + if scope.name().is_empty() { + otel_info!(name: "TracerNameEmpty", message = "Tracer name is empty; consider providing a meaningful name. Tracer will function normally and the provided name will be used as-is."); + }; Tracer::new(scope, self.clone()) } }