From e99074da2f6525cd177f26b46b8d03fef2fe4f35 Mon Sep 17 00:00:00 2001 From: Alex Boten <223565+codeboten@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:38:49 -0700 Subject: [PATCH] [service] implement a noop tracer provider (#11026) This is to address some of the memory concerns around the SDK's noop tracer provider. Instead of using the published noop tracer provider, we implement our own to avoid the cost of context propagation, which has been proven to be high enough to cause issues for end users. Part of #10858 --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> --- .chloggen/codeboten_noop-providers.yaml | 28 +++++++++++++++++++++++++ service/telemetry/tracer.go | 21 ++++++++++++++++++- service/telemetry/tracer_test.go | 5 ++--- 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 .chloggen/codeboten_noop-providers.yaml diff --git a/.chloggen/codeboten_noop-providers.yaml b/.chloggen/codeboten_noop-providers.yaml new file mode 100644 index 00000000000..d3646634724 --- /dev/null +++ b/.chloggen/codeboten_noop-providers.yaml @@ -0,0 +1,28 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: service + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: implement a no-op tracer provider that doesn't propagate the context + +# One or more tracking issues or pull requests related to the change +issues: [11026] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: | + The no-op tracer provider supported by the SDK incurs a memory cost of propagating the context no matter + what. This is not needed if tracing is not enabled in the Collector. This implementation of the no-op tracer + provider removes the need to allocate memory when tracing is disabled. + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/service/telemetry/tracer.go b/service/telemetry/tracer.go index c5c242bcf85..11c735df625 100644 --- a/service/telemetry/tracer.go +++ b/service/telemetry/tracer.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/otel/propagation" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/embedded" "go.opentelemetry.io/otel/trace/noop" "go.opentelemetry.io/collector/config/configtelemetry" @@ -47,10 +48,28 @@ func attributes(set Settings, cfg Config) map[string]interface{} { return attrs } +type noopNoContextTracer struct { + embedded.Tracer +} + +var noopSpan = noop.Span{} + +func (n *noopNoContextTracer) Start(ctx context.Context, _ string, _ ...trace.SpanStartOption) (context.Context, trace.Span) { + return ctx, noopSpan +} + +type noopNoContextTracerProvider struct { + embedded.TracerProvider +} + +func (n *noopNoContextTracerProvider) Tracer(_ string, _ ...trace.TracerOption) trace.Tracer { + return &noopNoContextTracer{} +} + // New creates a new Telemetry from Config. func newTracerProvider(ctx context.Context, set Settings, cfg Config) (trace.TracerProvider, error) { if globalgates.NoopTracerProvider.IsEnabled() || cfg.Traces.Level == configtelemetry.LevelNone { - return noop.NewTracerProvider(), nil + return &noopNoContextTracerProvider{}, nil } sch := semconv.SchemaURL diff --git a/service/telemetry/tracer_test.go b/service/telemetry/tracer_test.go index b9503276e0c..80184dac2e0 100644 --- a/service/telemetry/tracer_test.go +++ b/service/telemetry/tracer_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" sdktrace "go.opentelemetry.io/otel/sdk/trace" - "go.opentelemetry.io/otel/trace/noop" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" @@ -76,13 +75,13 @@ func TestNewTracerProvider(t *testing.T) { Level: configtelemetry.LevelNone, }, }, - wantTracerProvider: noop.TracerProvider{}, + wantTracerProvider: &noopNoContextTracerProvider{}, }, { name: "noop tracer feature gate", cfg: Config{}, noopTracerGate: true, - wantTracerProvider: noop.TracerProvider{}, + wantTracerProvider: &noopNoContextTracerProvider{}, }, { name: "tracer provider",