From f6d31c0b62cef5b7316dda8c8e3d43dc406c03f1 Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Thu, 30 Jul 2026 22:59:15 +0900 Subject: [PATCH 01/17] Fix target_info metric name in PrometheusHttpServerBuilder javadoc (#8628) --- .../exporter/prometheus/PrometheusHttpServerBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java index 7b85bb027ac..156c721e449 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java @@ -97,7 +97,7 @@ public PrometheusHttpServerBuilder setOtelScopeLabelsEnabled(boolean otelScopeLa return this; } - /** Set if the {@code otel_target_info} metric is generated. Default is {@code true}. */ + /** Set if the {@code target_info} metric is generated. Default is {@code true}. */ public PrometheusHttpServerBuilder setTargetInfoMetricEnabled(boolean targetInfoMetricEnabled) { metricReaderBuilder.setTargetInfoMetricEnabled(targetInfoMetricEnabled); return this; From f224ff7042e1f448558cbeb76ae91add093225ed Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:01:02 +0900 Subject: [PATCH 02/17] Skip empty baggage key in OtTracePropagator extract (#8631) --- .../trace/propagation/OtTracePropagator.java | 3 ++- .../trace/propagation/OtTracePropagatorTest.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/OtTracePropagator.java b/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/OtTracePropagator.java index 10f3c8d8e8e..a8ebb8c7a6e 100644 --- a/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/OtTracePropagator.java +++ b/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/OtTracePropagator.java @@ -146,7 +146,8 @@ public Context extract(Context context, @Nullable C carrier, TextMapGetter carrier = new LinkedHashMap<>(); + carrier.put(OtTracePropagator.TRACE_ID_HEADER, TRACE_ID); + carrier.put(OtTracePropagator.SPAN_ID_HEADER, SPAN_ID); + carrier.put(OtTracePropagator.SAMPLED_HEADER, Common.TRUE_INT); + carrier.put(OtTracePropagator.PREFIX_BAGGAGE_HEADER, "value"); // Not really a valid key. + + Context context = propagator.extract(Context.current(), carrier, getter); + + assertThat(Baggage.fromContext(context)).isEqualTo(Baggage.empty()); + } + @Test void extract_Baggage_InvalidContext() { Map carrier = new LinkedHashMap<>(); From d9abf30670a61b2d10c312790a9074020709396a Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:02:39 +0900 Subject: [PATCH 03/17] Log the exception when a gRPC response frame is invalid (#8626) --- .../exporter/sender/okhttp/internal/OkHttpGrpcSender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java index d9c1e490051..878cca34781 100644 --- a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java +++ b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java @@ -188,7 +188,7 @@ private void handleResponse(Response response, Consumer onResponse compressed = body.source().readByte() != 0; body.source().skip(4); // message length — we bound reads by EOF instead } catch (IOException e) { - logger.log(Level.FINE, "Invalid gRPC response frame"); + logger.log(Level.FINE, "Invalid gRPC response frame", e); onResponse.accept( ImmutableGrpcResponse.create(grpcStatus(response), grpcMessage(response), new byte[0])); return; From 99a9d73d06971ebe9463c10649e8fbfecfb952e6 Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:09:42 +0900 Subject: [PATCH 04/17] Add links to OpenCensus spans after span start (#8635) --- CHANGELOG.md | 5 +++ opencensus-shim/README.md | 5 --- .../opencensusshim/OpenTelemetrySpanImpl.java | 20 +++++++-- .../OpenTelemetrySpanImplTest.java | 45 +++++++++++++++++++ 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf04a42f4d9..69e5107e410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ * Logging: Output event name in `SystemOutLogRecordExporter` ([#8609](https://github.com/open-telemetry/opentelemetry-java/pull/8609)) +### Shims + +* Add OpenCensus links to the OpenTelemetry span instead of logging a warning and dropping them + ([#8635](https://github.com/open-telemetry/opentelemetry-java/pull/8635)) + ## Version 1.64.0 (2026-07-10) ### API diff --git a/opencensus-shim/README.md b/opencensus-shim/README.md index 69c9f3319cd..b124e4d2c76 100644 --- a/opencensus-shim/README.md +++ b/opencensus-shim/README.md @@ -38,8 +38,3 @@ SdkMeterProvider.builder() .registerMetricReader(OpenCensusMetrics.attachTo(PeriodicMetricReader.create(metricExporter))) .build(); ``` - -## Known Problems - -* OpenCensus links added after an OpenCensus span is created will not be -exported, as OpenTelemetry only supports links added when a span is created. diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImpl.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImpl.java index 87c41b1ff07..5e4c76a386b 100644 --- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImpl.java +++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImpl.java @@ -39,6 +39,8 @@ import io.opencensus.trace.MessageEvent; import io.opencensus.trace.Span; import io.opencensus.trace.Status; +import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.Tracestate; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; @@ -46,13 +48,12 @@ import io.opentelemetry.api.trace.StatusCode; import java.util.EnumSet; import java.util.Map; -import java.util.logging.Logger; class OpenTelemetrySpanImpl extends Span implements io.opentelemetry.api.trace.Span, DelegatingSpan { - private static final Logger LOGGER = Logger.getLogger(OpenTelemetrySpanImpl.class.getName()); private static final EnumSet RECORD_EVENTS_SPAN_OPTIONS = EnumSet.of(Span.Options.RECORD_EVENTS); + private static final Tracestate OC_TRACESTATE_DEFAULT = Tracestate.builder().build(); private final io.opentelemetry.api.trace.Span otelSpan; @@ -104,7 +105,20 @@ public void addAnnotation(Annotation annotation) { @Override public void addLink(Link link) { - LOGGER.warning("OpenTelemetry does not support links added after a span is created."); + Preconditions.checkNotNull(link, "link"); + AttributesBuilder attributesBuilder = Attributes.builder(); + mapAttributes(link.getAttributes(), attributesBuilder); + // DelegatingSpan does not override addLink, so DelegatingSpan.super.addLink(..) would call the + // no-op default method of Span and drop the link. Call the delegate directly instead. + getDelegate() + .addLink( + mapSpanContext( + io.opencensus.trace.SpanContext.create( + link.getTraceId(), + link.getSpanId(), + TraceOptions.DEFAULT, + OC_TRACESTATE_DEFAULT)), + attributesBuilder.build()); } @Override diff --git a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImplTest.java b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImplTest.java index 448c032a3f8..e700d5b30f6 100644 --- a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImplTest.java +++ b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetrySpanImplTest.java @@ -5,16 +5,27 @@ package io.opentelemetry.opencensusshim; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Link; +import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.Tracestate; +import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import java.util.Collections; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -26,6 +37,9 @@ @MockitoSettings(strictness = Strictness.LENIENT) class OpenTelemetrySpanImplTest { + private static final String TRACE_ID = "0123456789abcdef0123456789abcdef"; + private static final String SPAN_ID = "fedcba9876543210"; + @Mock private Span otelSpan; private OpenTelemetrySpanImpl shimSpan() { @@ -47,4 +61,35 @@ void setStatus_withoutDescription_setsCodeOnly() { verify(otelSpan).setStatus(StatusCode.OK); verify(otelSpan, never()).setStatus(any(StatusCode.class), anyString()); } + + @Test + void addLink_delegatesToOtelSpan() { + shimSpan().addLink(Link.fromSpanContext(ocSpanContext(), Link.Type.CHILD_LINKED_SPAN)); + + verify(otelSpan).addLink(expectedOtelSpanContext(), Attributes.empty()); + } + + @Test + void addLink_mapsAttributes() { + shimSpan() + .addLink( + Link.fromSpanContext( + ocSpanContext(), + Link.Type.PARENT_LINKED_SPAN, + Collections.singletonMap("key", AttributeValue.stringAttributeValue("value")))); + + verify(otelSpan).addLink(expectedOtelSpanContext(), Attributes.of(stringKey("key"), "value")); + } + + private static io.opencensus.trace.SpanContext ocSpanContext() { + return io.opencensus.trace.SpanContext.create( + TraceId.fromLowerBase16(TRACE_ID), + SpanId.fromLowerBase16(SPAN_ID), + TraceOptions.DEFAULT, + Tracestate.builder().build()); + } + + private static SpanContext expectedOtelSpanContext() { + return SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault()); + } } From 3a12e2b5cb5b2695104d571ca342743361c3086b Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:59:01 +0900 Subject: [PATCH 05/17] Return extracted SpanContext when it is sampled but invalid (#8634) Co-authored-by: Jack Berg <34418638+jack-berg@users.noreply.github.com> --- CHANGELOG.md | 2 + .../opentracingshim/Propagation.java | 4 +- .../opentracingshim/TracerShimTest.java | 45 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69e5107e410..6252a43ec29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ ### Shims +* OpenTracing: Return the extracted `SpanContext` when it is sampled but invalid + ([#8634](https://github.com/open-telemetry/opentelemetry-java/pull/8634)) * Add OpenCensus links to the OpenTelemetry span instead of logging a warning and dropping them ([#8635](https://github.com/open-telemetry/opentelemetry-java/pull/8635)) diff --git a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java index 04f0407b4a8..e67bf4fa73d 100644 --- a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java +++ b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java @@ -46,7 +46,9 @@ SpanContextShim extractTextMap(Format format, TextMapExtract carrier) { Span span = Span.fromContext(context); Baggage baggage = Baggage.fromContext(context); - if (!span.getSpanContext().isValid() && baggage.isEmpty()) { + if (!span.getSpanContext().isValid() + && !span.getSpanContext().isSampled() + && baggage.isEmpty()) { return null; } diff --git a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java index f539e5e3bfa..199b6209e26 100644 --- a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java +++ b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java @@ -14,9 +14,15 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.baggage.Baggage; import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.trace.SpanId; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceId; +import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.context.propagation.TextMapSetter; import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; @@ -32,9 +38,11 @@ import io.opentracing.tag.StringTag; import io.opentracing.tag.Tag; import io.opentracing.tag.Tags; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import javax.annotation.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -350,6 +358,21 @@ void extract_onlyBaggage() { assertThat(spanContextShim.getBaggage()).isEqualTo(baggage); } + @Test + void extract_invalidButSampledSpanContext() { + tracerShim = + new TracerShim(provider, new InvalidButSampledPropagator(), TextMapPropagator.noop()); + + SpanContext spanContext = + tracerShim.extract(Format.Builtin.TEXT_MAP, new TextMapAdapter(new HashMap<>())); + + assertThat(spanContext).isNotNull(); + SpanContextShim spanContextShim = (SpanContextShim) spanContext; + assertThat(spanContextShim.getSpanContext().isValid()).isFalse(); + assertThat(spanContextShim.getSpanContext().isSampled()).isTrue(); + assertThat(spanContextShim.getBaggage().isEmpty()).isTrue(); + } + @Test void extract_emptyCarrier_withActiveSpan_returnsNull() { Span span = tracerShim.buildSpan("one").start(); @@ -467,4 +490,26 @@ void noopDoesNotCrash() { assertThat(((SpanShim) span).getSpan().isRecording()).isFalse(); } + + /** Extracts an invalid but sampled {@code SpanContext}, as {@code jaeger-debug-id} headers do. */ + private static class InvalidButSampledPropagator implements TextMapPropagator { + @Override + public Collection fields() { + return Collections.emptyList(); + } + + @Override + public void inject(Context context, @Nullable C carrier, TextMapSetter setter) {} + + @Override + public Context extract(Context context, @Nullable C carrier, TextMapGetter getter) { + return context.with( + io.opentelemetry.api.trace.Span.wrap( + io.opentelemetry.api.trace.SpanContext.create( + TraceId.getInvalid(), + SpanId.getInvalid(), + TraceFlags.getSampled(), + TraceState.getDefault()))); + } + } } From bc956bcf7d402104fe59af8ba31ff9b73849e9b7 Mon Sep 17 00:00:00 2001 From: Mohammed AbdessetarElyagoubi Date: Thu, 30 Jul 2026 20:15:18 +0100 Subject: [PATCH 06/17] Fix declarative Jaeger sampler interval configuration (#8668) --- .../trace/jaeger/sampler/JaegerRemoteSampler.java | 14 +++++++++++++- .../jaeger/sampler/JaegerRemoteSamplerBuilder.java | 3 ++- .../JaegerRemoteSamplerComponentProvider.java | 2 +- .../jaeger/sampler/JaegerRemoteSamplerTest.java | 14 ++++++++------ .../sampler/JaegerRemoteSamplerGrpcNettyTest.java | 13 +++++++------ 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java index 52a8b350e7c..96d196da719 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java @@ -18,6 +18,7 @@ import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingResult; import java.io.IOException; +import java.net.URI; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -45,14 +46,19 @@ public final class JaegerRemoteSampler implements Sampler { private final AtomicBoolean isShutdown = new AtomicBoolean(); private final GrpcSender grpcSender; + private final URI endpoint; + private final int pollingIntervalMs; JaegerRemoteSampler( GrpcSender grpcSender, + URI endpoint, @Nullable String serviceName, int pollingIntervalMs, Sampler initialSampler) { this.serviceName = serviceName != null ? serviceName : ""; this.grpcSender = grpcSender; + this.endpoint = endpoint; + this.pollingIntervalMs = pollingIntervalMs; this.sampler = initialSampler; pollExecutor = Executors.newScheduledThreadPool(1, new DaemonThreadFactory(WORKER_THREAD_NAME)); pollFuture = @@ -161,7 +167,13 @@ private static Sampler updateSampler(SamplingStrategyResponse response) throws I @Override public String getDescription() { - return String.format("JaegerRemoteSampler{%s}", this.sampler); + return "JaegerRemoteSampler{sampler=" + + this.sampler + + ", endpoint=" + + this.endpoint + + ", pollingIntervalMs=" + + this.pollingIntervalMs + + "}"; } @Override diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java index 2228956c47f..c6b2783e1a2 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java @@ -181,7 +181,8 @@ public JaegerRemoteSamplerBuilder setChannel(ManagedChannel channel) { */ public JaegerRemoteSampler build() { GrpcSender grpcSender = resolveGrpcSender(); - return new JaegerRemoteSampler(grpcSender, serviceName, pollingIntervalMillis, initialSampler); + return new JaegerRemoteSampler( + grpcSender, endpoint, serviceName, pollingIntervalMillis, initialSampler); } private GrpcSender resolveGrpcSender() { diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java index b6dd93b77c1..b983f6751ef 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java @@ -47,7 +47,7 @@ public Sampler create(DeclarativeConfigProperties config) { } builder.setInitialSampler(DeclarativeConfiguration.createSampler(initialSamplerModel)); - Long pollingIntervalMs = config.getLong("internal"); + Long pollingIntervalMs = config.getLong("interval"); if (pollingIntervalMs != null) { builder.setPollingInterval(Duration.ofMillis(pollingIntervalMs)); } diff --git a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java index 88047b9f92d..4ed67399f87 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java +++ b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java @@ -284,7 +284,8 @@ void description() { assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}") + .contains("endpoint=" + server.httpUri(), "pollingIntervalMs=1000"); // wait until the sampling strategy is retrieved before exiting test method await().untilAsserted(samplerIsType(sampler, RateLimitingSampler.class)); @@ -301,7 +302,8 @@ void initialSampler() { .build()) { assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); - assertThat(sampler.getDescription()).startsWith("JaegerRemoteSampler{AlwaysOnSampler}"); + assertThat(sampler.getDescription()) + .startsWith("JaegerRemoteSampler{sampler=AlwaysOnSampler"); } } @@ -400,7 +402,7 @@ void perOperationSampling() { () -> { assertThat(sampler.getDescription()) .startsWith( - "JaegerRemoteSampler{ParentBased{root:PerOperationSampler{default=TraceIdRatioBased{0.550000}, perOperation={foo=TraceIdRatioBased{0.900000}, bar=TraceIdRatioBased{0.700000}}}"); + "JaegerRemoteSampler{sampler=ParentBased{root:PerOperationSampler{default=TraceIdRatioBased{0.550000}, perOperation={foo=TraceIdRatioBased{0.900000}, bar=TraceIdRatioBased{0.700000}}}"); assertThat(sampler.getDescription()).contains("bar"); }); } @@ -419,7 +421,7 @@ void internal_error_server_response() { assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); await() .untilAsserted( @@ -444,7 +446,7 @@ void unavailable_error_server_response() { assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); await() .untilAsserted( @@ -468,7 +470,7 @@ void unimplemented_error_server_response() { assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); await() .untilAsserted( diff --git a/sdk-extensions/jaeger-remote-sampler/src/testGrpcNetty/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerGrpcNettyTest.java b/sdk-extensions/jaeger-remote-sampler/src/testGrpcNetty/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerGrpcNettyTest.java index c2ddc1987ad..7ef47608f9f 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/testGrpcNetty/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerGrpcNettyTest.java +++ b/sdk-extensions/jaeger-remote-sampler/src/testGrpcNetty/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerGrpcNettyTest.java @@ -159,7 +159,7 @@ void description() { assertThat(sampler).extracting("grpcSender").isInstanceOf(UpstreamGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); // wait until the sampling strategy is retrieved before exiting test method await().untilAsserted(samplerIsType(sampler, RateLimitingSampler.class)); @@ -178,7 +178,8 @@ void initialSampler() { .build()) { assertThat(sampler).extracting("grpcSender").isInstanceOf(UpstreamGrpcSender.class); - assertThat(sampler.getDescription()).startsWith("JaegerRemoteSampler{AlwaysOnSampler}"); + assertThat(sampler.getDescription()) + .startsWith("JaegerRemoteSampler{sampler=AlwaysOnSampler"); } } @@ -277,7 +278,7 @@ void perOperationSampling() { () -> { assertThat(sampler.getDescription()) .startsWith( - "JaegerRemoteSampler{ParentBased{root:PerOperationSampler{default=TraceIdRatioBased{0.550000}, perOperation={foo=TraceIdRatioBased{0.900000}, bar=TraceIdRatioBased{0.700000}}}"); + "JaegerRemoteSampler{sampler=ParentBased{root:PerOperationSampler{default=TraceIdRatioBased{0.550000}, perOperation={foo=TraceIdRatioBased{0.900000}, bar=TraceIdRatioBased{0.700000}}}"); assertThat(sampler.getDescription()).contains("bar"); }); } @@ -297,7 +298,7 @@ void internal_error_server_response() { assertThat(sampler).extracting("grpcSender").isInstanceOf(UpstreamGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); await() .untilAsserted( @@ -323,7 +324,7 @@ void unavailable_error_server_response() { assertThat(sampler).extracting("grpcSender").isInstanceOf(UpstreamGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); await() .untilAsserted( @@ -348,7 +349,7 @@ void unimplemented_error_server_response() { assertThat(sampler).extracting("grpcSender").isInstanceOf(UpstreamGrpcSender.class); assertThat(sampler.getDescription()) - .startsWith("JaegerRemoteSampler{ParentBased{root:TraceIdRatioBased{0.001000}"); + .startsWith("JaegerRemoteSampler{sampler=ParentBased{root:TraceIdRatioBased{0.001000}"); await() .untilAsserted( From f8bd413df10411d7ecc76add7371c73eb8c333e7 Mon Sep 17 00:00:00 2001 From: Jack Berg <34418638+jack-berg@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:22:51 -0500 Subject: [PATCH 07/17] Restore java 25 lts to test matrix, collect coverage on java 25 (#8678) --- .github/workflows/build.yml | 3 ++- .../sdk/metrics/internal/state/TestInstrumentType.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aef1339eef9..ca3d8fab774 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,11 +31,12 @@ jobs: - 11 - 17 - 21 + - 25 - 26 # renovate(java-version) # Collect coverage on latest LTS include: - os: ubuntu-latest - test-java-version: 21 + test-java-version: 25 coverage: true jmh-based-tests: true steps: diff --git a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java index 5a462fd94c8..9877d02a945 100644 --- a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java +++ b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java @@ -31,7 +31,7 @@ public enum TestInstrumentType { DOUBLE_SUM( DoubleSumTester::new, /* dataAllocRateReductionPercentage= */ 97.3f, - /* allowedPercentOffset= */ 2.0f), + /* allowedPercentOffset= */ 4.0f), LONG_LAST_VALUE( LongLastValueTester::new, /* dataAllocRateReductionPercentage= */ 97.3f, From 19d95abe44e18a7941767a59f9c5523000539ee2 Mon Sep 17 00:00:00 2001 From: Jack Berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:52:26 -0500 Subject: [PATCH 08/17] Delete opentelemetry-exporter-zipkin (#8677) --- README.md | 1 - dependencyManagement/build.gradle.kts | 7 +- .../opentelemetry-exporter-zipkin.txt | 2 - exporters/zipkin/README.md | 7 - exporters/zipkin/build.gradle.kts | 30 - .../exporter/zipkin/BytesEncoderAdapter.java | 58 -- .../zipkin/EventDataToAnnotation.java | 76 --- .../zipkin/LocalInetAddressSupplier.java | 58 -- .../zipkin/OtelToZipkinSpanTransformer.java | 243 --------- .../exporter/zipkin/ZipkinSpanExporter.java | 149 ----- .../zipkin/ZipkinSpanExporterBuilder.java | 256 --------- .../exporter/zipkin/internal/ComponentId.java | 67 --- .../internal/ExporterInstrumentation.java | 116 ---- .../zipkin/internal/ExporterMetrics.java | 61 --- .../internal/LegacyExporterMetrics.java | 136 ----- .../zipkin/internal/NoopExporterMetrics.java | 29 - .../exporter/zipkin/internal/RateLimiter.java | 68 --- .../zipkin/internal/SemConvAttributes.java | 34 -- .../internal/SemConvExporterMetrics.java | 187 ------- .../exporter/zipkin/internal/Signal.java | 32 -- .../zipkin/internal/StandardComponentId.java | 54 -- .../zipkin/internal/ThrottlingLogger.java | 110 ---- .../internal/ZipkinSpanExporterProvider.java | 45 -- .../exporter/zipkin/package-info.java | 9 - ...pi.traces.ConfigurableSpanExporterProvider | 1 - .../zipkin/BytesEncoderAdapterTest.java | 70 --- .../zipkin/EventDataToAnnotationTest.java | 56 -- .../OtelToZipkinSpanTransformerTest.java | 515 ------------------ .../ZipkinSpanExporterEndToEndHttpTest.java | 289 ---------- .../zipkin/ZipkinSpanExporterTest.java | 328 ----------- .../exporter/zipkin/ZipkinTestUtil.java | 82 --- .../ZipkinSpanExporterProviderTest.java | 67 --- sdk-extensions/autoconfigure/build.gradle.kts | 1 - .../SpanExporterConfiguration.java | 1 - .../SpanExporterConfigurationTest.java | 5 - .../ConfigurableSpanExporterTest.java | 22 +- .../SpanExporterConfigurationTest.java | 3 - .../sdk/common/internal/ComponentIdTest.java | 3 - settings.gradle.kts | 1 - 39 files changed, 8 insertions(+), 3271 deletions(-) delete mode 100644 docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt delete mode 100644 exporters/zipkin/README.md delete mode 100644 exporters/zipkin/build.gradle.kts delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotation.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformer.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ComponentId.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterInstrumentation.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterMetrics.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/LegacyExporterMetrics.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/NoopExporterMetrics.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/RateLimiter.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvAttributes.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvExporterMetrics.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/Signal.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/StandardComponentId.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ThrottlingLogger.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProvider.java delete mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/package-info.java delete mode 100644 exporters/zipkin/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotationTest.java delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformerTest.java delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinTestUtil.java delete mode 100644 exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProviderTest.java diff --git a/README.md b/README.md index 311bfd7a294..4e5f3829852 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,6 @@ SDK exporters for shipping traces, metrics, and logs out of process. | [OTLP Logging Exporters](./exporters/logging-otlp) | Logging exporters in OTLP JSON encoding, including traces, metrics, and logs | `opentelemetry-exporter-logging-otlp` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-logging-otlp.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging-otlp) | | [OTLP Common](./exporters/otlp/common) | Shared OTLP components (internal) | `opentelemetry-exporter-otlp-common` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-otlp-common.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp-common) | | [Logging Exporter](./exporters/logging) | Logging exporters, including metrics, traces, and logs | `opentelemetry-exporter-logging` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-logging.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging) | -| [Zipkin Exporter](./exporters/zipkin) | **DEPRECATED** Zipkin trace exporter | `opentelemetry-exporter-zipkin` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-zipkin.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-zipkin) | | [Prometheus Exporter](./exporters/prometheus) | Prometheus metric exporter | `opentelemetry-exporter-prometheus` | 1.64.0-alpha | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-prometheus.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-prometheus) | | [Exporter Common](./exporters/common) | Shared exporter components (internal) | `opentelemetry-exporter-common` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-common.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-common) | | [OkHttp Sender](./exporters/sender/okhttp) | OkHttp implementation of HttpSender (internal) | `opentelemetry-exporter-sender-okhttp` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-sender-okhttp.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-okhttp) | diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 092909c5743..a4978f2c1c7 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -34,8 +34,6 @@ val DEPENDENCY_BOMS = listOf( "com.squareup.okio:okio-bom:3.18.0", // applies to transitive dependencies of okhttp "io.grpc:grpc-bom:1.83.0", "io.netty:netty-bom:4.2.16.Final", - "io.zipkin.brave:brave-bom:6.3.1", - "io.zipkin.reporter2:zipkin-reporter-bom:3.5.3", "org.assertj:assertj-bom:3.27.7", "org.osgi:org.osgi.test.bom:1.3.0", "org.testcontainers:testcontainers-bom:2.0.5", @@ -92,10 +90,7 @@ val DEPENDENCIES = listOf( "io.opentelemetry.proto:opentelemetry-proto:1.11.0-alpha", "io.opentracing:opentracing-api:0.33.0", "io.opentracing:opentracing-noop:0.33.0", - // zipkin-reporter-bom depends on zipkin v2.x for java 6 compatibility - // we only need java 8 compatibility. upgrade to 3.x to avoid problematic shaded gson dependency version - // See: https://github.com/open-telemetry/opentelemetry-java/issues/8427 - "io.zipkin.zipkin2:zipkin:3.6.1", + "io.zipkin.brave:brave:6.3.1", "junit:junit:4.13.2", "nl.jqno.equalsverifier:equalsverifier:3.19.4", "org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.7", diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt deleted file mode 100644 index 11551cefc22..00000000000 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt +++ /dev/null @@ -1,2 +0,0 @@ -Comparing source compatibility of opentelemetry-exporter-zipkin-1.65.0-SNAPSHOT.jar against opentelemetry-exporter-zipkin-1.64.0.jar -No changes. \ No newline at end of file diff --git a/exporters/zipkin/README.md b/exporters/zipkin/README.md deleted file mode 100644 index 9fb38662a12..00000000000 --- a/exporters/zipkin/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# OpenTelemetry - Zipkin Span Exporter - -## Attribution - -The code in this module is based on the [OpenCensus Zipkin exporter][oc-origin] code. - -[oc-origin]: https://github.com/census-instrumentation/opencensus-java/ diff --git a/exporters/zipkin/build.gradle.kts b/exporters/zipkin/build.gradle.kts deleted file mode 100644 index c46c0d15dfd..00000000000 --- a/exporters/zipkin/build.gradle.kts +++ /dev/null @@ -1,30 +0,0 @@ -plugins { - id("otel.java-conventions") - id("otel.publish-conventions") - - id("otel.animalsniffer-conventions") -} - -description = "OpenTelemetry - Zipkin Exporter" -otelJava.moduleName.set("io.opentelemetry.exporter.zipkin") -otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.sdk.autoconfigure.spi")) -otelJava.osgiServiceLoaderProvides.set(listOf( - "io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider", -)) - -dependencies { - api(project(":sdk:all")) - - api("io.zipkin.reporter2:zipkin-reporter") - - compileOnly(project(":sdk-extensions:autoconfigure-spi")) - compileOnly(project(":api:incubator")) - - implementation("io.zipkin.reporter2:zipkin-sender-okhttp3") - - testImplementation(project(":sdk:testing")) - testImplementation(project(":sdk-extensions:autoconfigure-spi")) - - testImplementation("com.linecorp.armeria:armeria") - testImplementation("org.testcontainers:testcontainers-junit-jupiter") -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java deleted file mode 100644 index 8605eacd936..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import zipkin2.Span; -import zipkin2.reporter.BytesEncoder; -import zipkin2.reporter.Encoding; - -/** - * This supports the deprecated method {@link - * ZipkinSpanExporterBuilder#setEncoder(zipkin2.codec.BytesEncoder)}. - */ -final class BytesEncoderAdapter implements BytesEncoder { - private final zipkin2.codec.BytesEncoder delegate; - private final Encoding encoding; - - @SuppressWarnings("deprecation") // we have to use the deprecated thrift encoding to return it - BytesEncoderAdapter(zipkin2.codec.BytesEncoder delegate) { - this.delegate = delegate; - switch (delegate.encoding()) { - case JSON: - this.encoding = Encoding.JSON; - break; - case PROTO3: - this.encoding = Encoding.PROTO3; - break; - case THRIFT: - this.encoding = Encoding.THRIFT; - break; - default: - // Only possible if zipkin2 adds an encoding besides above, which is very unlikely. - throw new UnsupportedOperationException("unsupported encoding " + delegate.encoding()); - } - } - - @Override - public Encoding encoding() { - return encoding; - } - - @Override - public int sizeInBytes(Span span) { - return delegate.sizeInBytes(span); - } - - @Override - public byte[] encode(Span span) { - return delegate.encode(span); - } - - @Override - public String toString() { - return delegate.toString(); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotation.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotation.java deleted file mode 100644 index 855488a8b52..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotation.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static java.util.stream.Collectors.joining; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.Value; -import io.opentelemetry.api.common.ValueType; -import io.opentelemetry.sdk.trace.data.EventData; -import java.util.List; - -/** - * Converts an EventData instance to a String representation of that data, with attributes converted - * to JSON. - * - *

See the - * zipkin exporter spec for details. - */ -final class EventDataToAnnotation { - - private EventDataToAnnotation() {} - - static String apply(EventData eventData) { - String name = eventData.getName(); - String value = toJson(eventData.getAttributes()); - return "\"" + name + "\":" + value; - } - - private static String toJson(Attributes attributes) { - return attributes.asMap().entrySet().stream() - .map(entry -> "\"" + entry.getKey() + "\":" + toValue(entry.getValue())) - .collect(joining(",", "{", "}")); - } - - private static String toValue(Object o) { - if (o instanceof String) { - return "\"" + o + "\""; - } - if (o instanceof List) { - return ((List) o) - .stream().map(EventDataToAnnotation::toValue).collect(joining(",", "[", "]")); - } - if (o instanceof Value) { - return toJsonValue((Value) o); - } - return String.valueOf(o); - } - - // note: simple types (STRING, BOOLEAN, LONG, DOUBLE) won't actually come here - // but handling here for completeness - private static String toJsonValue(Value value) { - ValueType type = value.getType(); - switch (type) { - case STRING: - case BYTES: - // For JSON encoding, strings and bytes need to be quoted - return "\"" + value.asString() + "\""; - case EMPTY: - // For JSON encoding, empty values should be null - return "null"; - case ARRAY: - case KEY_VALUE_LIST: - case BOOLEAN: - case LONG: - case DOUBLE: - // Arrays, maps, and primitives are already valid JSON from asString() - return value.asString(); - } - throw new IllegalStateException("Unknown value type: " + type); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java deleted file mode 100644 index a5376eb88a9..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Enumeration; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; - -class LocalInetAddressSupplier implements Supplier { - - private static final Logger logger = Logger.getLogger(LocalInetAddressSupplier.class.getName()); - private static final LocalInetAddressSupplier INSTANCE = - new LocalInetAddressSupplier(findLocalIp()); - @Nullable private final InetAddress inetAddress; - - private LocalInetAddressSupplier(@Nullable InetAddress inetAddress) { - this.inetAddress = inetAddress; - } - - @Nullable - @Override - public InetAddress get() { - return inetAddress; - } - - /** Logic borrowed from brave.internal.Platform.produceLocalEndpoint. */ - @Nullable - private static InetAddress findLocalIp() { - try { - Enumeration nics = NetworkInterface.getNetworkInterfaces(); - while (nics.hasMoreElements()) { - NetworkInterface nic = nics.nextElement(); - Enumeration addresses = nic.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress address = addresses.nextElement(); - if (address.isSiteLocalAddress()) { - return address; - } - } - } - } catch (Exception e) { - // don't crash the caller if there was a problem reading nics. - logger.log(Level.FINE, "error reading nics", e); - } - return null; - } - - static LocalInetAddressSupplier getInstance() { - return INSTANCE; - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformer.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformer.java deleted file mode 100644 index 57d12ec5864..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformer.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.api.common.AttributeKey.longKey; -import static io.opentelemetry.api.common.AttributeKey.stringKey; -import static java.util.concurrent.TimeUnit.NANOSECONDS; - -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.AttributeType; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.Value; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.sdk.common.InstrumentationScopeInfo; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.data.EventData; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.data.StatusData; -import java.net.InetAddress; -import java.util.List; -import java.util.function.Supplier; -import javax.annotation.Nullable; -import zipkin2.Endpoint; -import zipkin2.Span; - -/** - * This class is responsible for transforming an OpenTelemetry SpanData instance into an instance of - * a Zipkin Span. It is based, in part, on code from - * https://github.com/census-instrumentation/opencensus-java/tree/c960b19889de5e4a7b25f90919d28b066590d4f0/exporters/trace/zipkin - */ -final class OtelToZipkinSpanTransformer { - - private static final AttributeKey SERVICE_NAME = AttributeKey.stringKey("service.name"); - private static final AttributeKey PEER_SERVICE = stringKey("peer.service"); - private static final AttributeKey SERVER_SOCKET_ADDRESS = - stringKey("server.socket.address"); - private static final AttributeKey SERVER_SOCKET_PORT = longKey("server.socket.port"); - - static final String KEY_INSTRUMENTATION_SCOPE_NAME = "otel.scope.name"; - static final String KEY_INSTRUMENTATION_SCOPE_VERSION = "otel.scope.version"; - static final String KEY_INSTRUMENTATION_LIBRARY_NAME = "otel.library.name"; - static final String KEY_INSTRUMENTATION_LIBRARY_VERSION = "otel.library.version"; - static final String OTEL_DROPPED_ATTRIBUTES_COUNT = "otel.dropped_attributes_count"; - static final String OTEL_DROPPED_EVENTS_COUNT = "otel.dropped_events_count"; - static final String OTEL_STATUS_CODE = "otel.status_code"; - static final AttributeKey STATUS_ERROR = stringKey("error"); - private final Supplier ipAddressSupplier; - - /** - * Creates an instance of an OtelToZipkinSpanTransformer with the given Supplier that can produce - * an InetAddress, which may be null. This value from this Supplier will be used when creating the - * local zipkin Endpoint for each Span. The default implementation uses - * LocalInetAddressSupplier.getInstance(). - * - * @param ipAddressSupplier - A Supplier of an InetAddress. - */ - static OtelToZipkinSpanTransformer create(Supplier ipAddressSupplier) { - return new OtelToZipkinSpanTransformer(ipAddressSupplier); - } - - /** - * Creates an instance of an OtelToZipkinSpanTransformer with the given Supplier that can produce - * an InetAddress. Supplier may return null. This value from this Supplier will be used when - * creating the local zipkin Endpoint for each Span. - * - * @param ipAddressSupplier - A Supplier of an InetAddress, which can be null - */ - private OtelToZipkinSpanTransformer(Supplier ipAddressSupplier) { - this.ipAddressSupplier = ipAddressSupplier; - } - - /** - * Creates an instance of a Zipkin Span from an OpenTelemetry SpanData instance. - * - * @param spanData an OpenTelemetry spanData instance - * @return a new Zipkin Span - */ - Span generateSpan(SpanData spanData) { - long startTimestamp = toEpochMicros(spanData.getStartEpochNanos()); - long endTimestamp = toEpochMicros(spanData.getEndEpochNanos()); - - Span.Builder spanBuilder = - Span.newBuilder() - .traceId(spanData.getTraceId()) - .id(spanData.getSpanId()) - .kind(toSpanKind(spanData)) - .name(spanData.getName()) - .timestamp(toEpochMicros(spanData.getStartEpochNanos())) - .duration(Math.max(1, endTimestamp - startTimestamp)) - .localEndpoint(getLocalEndpoint(spanData)) - .remoteEndpoint(getRemoteEndpoint(spanData)); - - if (spanData.getParentSpanContext().isValid()) { - spanBuilder.parentId(spanData.getParentSpanId()); - } - - Attributes spanAttributes = spanData.getAttributes(); - spanAttributes.forEach( - (key, value) -> spanBuilder.putTag(key.getKey(), valueToString(key, value))); - int droppedAttributes = spanData.getTotalAttributeCount() - spanAttributes.size(); - if (droppedAttributes > 0) { - spanBuilder.putTag(OTEL_DROPPED_ATTRIBUTES_COUNT, String.valueOf(droppedAttributes)); - } - - StatusData status = spanData.getStatus(); - - // include status code & error. - if (status.getStatusCode() != StatusCode.UNSET) { - spanBuilder.putTag(OTEL_STATUS_CODE, status.getStatusCode().toString()); - - // add the error tag, if it isn't already in the source span. - if (status.getStatusCode() == StatusCode.ERROR && spanAttributes.get(STATUS_ERROR) == null) { - spanBuilder.putTag(STATUS_ERROR.getKey(), nullToEmpty(status.getDescription())); - } - } - - InstrumentationScopeInfo instrumentationScopeInfo = spanData.getInstrumentationScopeInfo(); - - if (!instrumentationScopeInfo.getName().isEmpty()) { - spanBuilder.putTag(KEY_INSTRUMENTATION_SCOPE_NAME, instrumentationScopeInfo.getName()); - // Include instrumentation library name for backwards compatibility - spanBuilder.putTag(KEY_INSTRUMENTATION_LIBRARY_NAME, instrumentationScopeInfo.getName()); - } - if (instrumentationScopeInfo.getVersion() != null) { - spanBuilder.putTag(KEY_INSTRUMENTATION_SCOPE_VERSION, instrumentationScopeInfo.getVersion()); - // Include instrumentation library name for backwards compatibility - spanBuilder.putTag( - KEY_INSTRUMENTATION_LIBRARY_VERSION, instrumentationScopeInfo.getVersion()); - } - - for (EventData eventData : spanData.getEvents()) { - String annotation = EventDataToAnnotation.apply(eventData); - spanBuilder.addAnnotation(toEpochMicros(eventData.getEpochNanos()), annotation); - } - int droppedEvents = spanData.getTotalRecordedEvents() - spanData.getEvents().size(); - if (droppedEvents > 0) { - spanBuilder.putTag(OTEL_DROPPED_EVENTS_COUNT, String.valueOf(droppedEvents)); - } - - return spanBuilder.build(); - } - - private static String nullToEmpty(@Nullable String value) { - return value != null ? value : ""; - } - - private Endpoint getLocalEndpoint(SpanData spanData) { - Attributes resourceAttributes = spanData.getResource().getAttributes(); - - Endpoint.Builder endpoint = Endpoint.newBuilder(); - endpoint.ip(ipAddressSupplier.get()); - - // use the service.name from the Resource, if it's been set. - String serviceNameValue = resourceAttributes.get(SERVICE_NAME); - if (serviceNameValue == null) { - serviceNameValue = Resource.getDefault().getAttribute(SERVICE_NAME); - } - // In practice should never be null unless the default Resource spec is changed. - if (serviceNameValue != null) { - endpoint.serviceName(serviceNameValue); - } - return endpoint.build(); - } - - @Nullable - private static Endpoint getRemoteEndpoint(SpanData spanData) { - if (spanData.getKind() == SpanKind.CLIENT || spanData.getKind() == SpanKind.PRODUCER) { - // TODO: Implement fallback mechanism: - // https://opentelemetry.io/docs/reference/specification/trace/sdk_exporters/zipkin/#otlp---zipkin - Attributes attributes = spanData.getAttributes(); - String serviceName = attributes.get(PEER_SERVICE); - - if (serviceName != null) { - Endpoint.Builder endpoint = Endpoint.newBuilder(); - endpoint.serviceName(serviceName); - endpoint.ip(attributes.get(SERVER_SOCKET_ADDRESS)); - Long port = attributes.get(SERVER_SOCKET_PORT); - if (port != null) { - endpoint.port(port.intValue()); - } - - return endpoint.build(); - } - } - - return null; - } - - @Nullable - private static Span.Kind toSpanKind(SpanData spanData) { - switch (spanData.getKind()) { - case SERVER: - return Span.Kind.SERVER; - case CLIENT: - return Span.Kind.CLIENT; - case PRODUCER: - return Span.Kind.PRODUCER; - case CONSUMER: - return Span.Kind.CONSUMER; - case INTERNAL: - return null; - } - return null; - } - - private static long toEpochMicros(long epochNanos) { - return NANOSECONDS.toMicros(epochNanos); - } - - private static String valueToString(AttributeKey key, Object attributeValue) { - AttributeType type = key.getType(); - switch (type) { - case STRING: - case BOOLEAN: - case LONG: - case DOUBLE: - return String.valueOf(attributeValue); - case STRING_ARRAY: - case BOOLEAN_ARRAY: - case LONG_ARRAY: - case DOUBLE_ARRAY: - return commaSeparated((List) attributeValue); - case VALUE: - return ((Value) attributeValue).asString(); - } - throw new IllegalStateException("Unknown attribute type: " + type); - } - - private static String commaSeparated(List values) { - StringBuilder builder = new StringBuilder(); - for (Object value : values) { - if (builder.length() != 0) { - builder.append(','); - } - builder.append(value); - } - return builder.toString(); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java deleted file mode 100644 index d726a5d5655..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import io.opentelemetry.api.impl.InstrumentationUtil; -import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.exporter.zipkin.internal.ComponentId; -import io.opentelemetry.exporter.zipkin.internal.ExporterInstrumentation; -import io.opentelemetry.exporter.zipkin.internal.StandardComponentId; -import io.opentelemetry.exporter.zipkin.internal.ThrottlingLogger; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.common.InternalTelemetryVersion; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.logging.Logger; -import zipkin2.Span; -import zipkin2.reporter.BytesEncoder; -import zipkin2.reporter.BytesMessageSender; -import zipkin2.reporter.Encoding; - -/** - * This class was based on the OpenCensus - * zipkin exporter code. - * - * @deprecated Zipkin exporter is deprecated in the OpenTelemetry specification (see #4715). - * Expect this artifact to no longer be published in approximately 6 months (mid 2026). - */ -@Deprecated -public final class ZipkinSpanExporter implements SpanExporter { - - public static final Logger baseLogger = Logger.getLogger(ZipkinSpanExporter.class.getName()); - - public static final String DEFAULT_ENDPOINT = "http://localhost:9411/api/v2/spans"; - - private final ThrottlingLogger logger = new ThrottlingLogger(baseLogger); - private final AtomicBoolean isShutdown = new AtomicBoolean(); - private final ZipkinSpanExporterBuilder builder; - private final BytesEncoder encoder; - private final BytesMessageSender sender; - private final ExporterInstrumentation exporterMetrics; - - private final OtelToZipkinSpanTransformer transformer; - - ZipkinSpanExporter( - ZipkinSpanExporterBuilder builder, - BytesEncoder encoder, - BytesMessageSender sender, - Supplier meterProviderSupplier, - InternalTelemetryVersion internalTelemetryVersion, - String endpoint, - OtelToZipkinSpanTransformer transformer) { - this.builder = builder; - this.encoder = encoder; - this.sender = sender; - this.transformer = transformer; - - StandardComponentId.ExporterType exporterType; - if (sender.encoding() == Encoding.JSON) { - exporterType = StandardComponentId.ExporterType.ZIPKIN_HTTP_JSON_SPAN_EXPORTER; - } else { - exporterType = StandardComponentId.ExporterType.ZIPKIN_HTTP_SPAN_EXPORTER; - } - this.exporterMetrics = - new ExporterInstrumentation( - internalTelemetryVersion, - meterProviderSupplier, - ComponentId.generateLazy(exporterType), - URI.create(endpoint)); - } - - @Override - public CompletableResultCode export(Collection spanDataList) { - if (isShutdown.get()) { - return CompletableResultCode.ofFailure(); - } - - int numItems = spanDataList.size(); - ExporterInstrumentation.Recording metricRecording = - exporterMetrics.startRecordingExport(numItems); - - List encodedSpans = new ArrayList<>(numItems); - for (SpanData spanData : spanDataList) { - Span zipkinSpan = transformer.generateSpan(spanData); - encodedSpans.add(encoder.encode(zipkinSpan)); - } - - CompletableResultCode resultCode = new CompletableResultCode(); - InstrumentationUtil.suppressInstrumentation( - () -> { - try { - sender.send(encodedSpans); - metricRecording.finishSuccessful(); - resultCode.succeed(); - } catch (IOException | RuntimeException e) { - metricRecording.finishFailed(e); - logger.log(Level.WARNING, "Failed to export spans", e); - resultCode.fail(); - } - }); - return resultCode; - } - - @Override - public CompletableResultCode flush() { - // nothing required here - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode shutdown() { - if (!isShutdown.compareAndSet(false, true)) { - logger.log(Level.INFO, "Calling shutdown() multiple times."); - return CompletableResultCode.ofSuccess(); - } - try { - sender.close(); - } catch (IOException e) { - logger.log(Level.WARNING, "Exception while closing the Zipkin Sender instance", e); - } - return CompletableResultCode.ofSuccess(); - } - - @Override - public String toString() { - return "ZipkinSpanExporter{" + builder.toString(false) + "}"; - } - - /** - * Returns a new Builder for {@link ZipkinSpanExporter}. - * - * @return a new {@link ZipkinSpanExporter}. - */ - public static ZipkinSpanExporterBuilder builder() { - return new ZipkinSpanExporterBuilder(); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java deleted file mode 100644 index 98dc68bbc66..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static java.util.Objects.requireNonNull; - -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.sdk.common.InternalTelemetryVersion; -import java.net.InetAddress; -import java.time.Duration; -import java.util.StringJoiner; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; -import javax.annotation.Nullable; -import zipkin2.Span; -import zipkin2.reporter.BytesEncoder; -import zipkin2.reporter.BytesMessageSender; -import zipkin2.reporter.Sender; -import zipkin2.reporter.SpanBytesEncoder; -import zipkin2.reporter.okhttp3.OkHttpSender; - -/** - * Builder class for {@link ZipkinSpanExporter}. - * - * @deprecated Zipkin exporter is deprecated in OpenTelemetry spec (see the PR). - * Expect this artifact to no longer be published in approximately 6 months (mid 2026). - */ -@Deprecated -public final class ZipkinSpanExporterBuilder { - private BytesEncoder encoder = SpanBytesEncoder.JSON_V2; - private Supplier localIpAddressSupplier = LocalInetAddressSupplier.getInstance(); - @Nullable private BytesMessageSender sender; - private String endpoint = ZipkinSpanExporter.DEFAULT_ENDPOINT; - // compression is enabled by default, because this is the default of OkHttpSender, - // which is created when no custom sender is set (see OkHttpSender.Builder) - private boolean compressionEnabled = true; - private int readTimeoutMillis = (int) TimeUnit.SECONDS.toMillis(10); - private Supplier meterProviderSupplier = - () -> GlobalOpenTelemetry.getOrNoop().getMeterProvider(); - private InternalTelemetryVersion internalTelemetryVersion = InternalTelemetryVersion.LEGACY; - - /** - * Sets the Zipkin sender. Implements the client side of the span transport. An {@link - * OkHttpSender} is a good default. - * - *

The {@link BytesMessageSender#close()} method will be called when the exporter is shut down. - * - * @param sender the Zipkin sender implementation. - * @return this. - * @deprecated Use {@link #setSender(BytesMessageSender)} insteead. - */ - @Deprecated - public ZipkinSpanExporterBuilder setSender(Sender sender) { - return setSender((BytesMessageSender) sender); - } - - /** - * Sets the Zipkin sender. Implements the client side of the span transport. An {@link - * OkHttpSender} is a good default. - * - *

The {@link BytesMessageSender#close()} method will be called when the exporter is shut down. - * - * @param sender the Zipkin sender implementation. - * @return this. - * @since 1.35.0 - */ - public ZipkinSpanExporterBuilder setSender(BytesMessageSender sender) { - requireNonNull(sender, "sender"); - this.sender = sender; - return this; - } - - /** - * Sets the {@link zipkin2.codec.BytesEncoder}, which controls the format used by the {@link - * BytesMessageSender}. Defaults to the {@link zipkin2.codec.SpanBytesEncoder#JSON_V2}. - * - * @param encoder the {@code BytesEncoder} to use. - * @return this. - * @see zipkin2.codec.SpanBytesEncoder - * @deprecated Use {@link #setEncoder(BytesEncoder)} instead. - */ - @Deprecated - public ZipkinSpanExporterBuilder setEncoder(zipkin2.codec.BytesEncoder encoder) { - requireNonNull(encoder, "encoder"); - return setEncoder(new BytesEncoderAdapter(encoder)); - } - - /** - * Sets the {@link BytesEncoder}, which controls the format used by the {@link - * BytesMessageSender}. Defaults to the {@link SpanBytesEncoder#JSON_V2}. - * - * @param encoder the {@code BytesEncoder} to use. - * @return this. - * @see SpanBytesEncoder - * @since 1.35.0 - */ - public ZipkinSpanExporterBuilder setEncoder(BytesEncoder encoder) { - requireNonNull(encoder, "encoder"); - this.encoder = encoder; - return this; - } - - /** - * Sets the Supplier of InetAddress. This Supplier will be used by the {@link - * OtelToZipkinSpanTransformer} when creating the Zipkin local endpoint. The default - * implementation uses a Supplier that returns a single unchanging IP address that is captured at - * creation time. - * - * @param localIpAddressSupplier - A supplier that returns an InetAddress that may be null. - * @return this - * @since 1.18.0 - */ - public ZipkinSpanExporterBuilder setLocalIpAddressSupplier( - Supplier localIpAddressSupplier) { - requireNonNull(localIpAddressSupplier, "localIpAddressSupplier"); - this.localIpAddressSupplier = localIpAddressSupplier; - return this; - } - - /** - * Sets the zipkin endpoint. This will use the endpoint to assign an {@link OkHttpSender} instance - * to this builder. - * - * @param endpoint The Zipkin endpoint URL, ex. "http://zipkinhost:9411/api/v2/spans". - * @return this. - * @see OkHttpSender - */ - public ZipkinSpanExporterBuilder setEndpoint(String endpoint) { - requireNonNull(endpoint, "endpoint"); - this.endpoint = endpoint; - return this; - } - - /** - * Sets the method used to compress payloads. If unset, gzip compression is enabled. Currently - * supported compression methods include "gzip" and "none". - * - *

The compression method is ignored when a custom Zipkin sender is set via {@link - * #setSender(BytesMessageSender)}. - * - * @param compressionMethod The compression method, ex. "gzip". - * @return this. - * @see OkHttpSender - * @since 1.20.0 - */ - public ZipkinSpanExporterBuilder setCompression(String compressionMethod) { - requireNonNull(compressionMethod, "compressionMethod"); - if (!compressionMethod.equals("gzip") && !compressionMethod.equals("none")) { - throw new IllegalArgumentException( - "Unsupported compression method. Supported compression methods include: gzip, none."); - } - this.compressionEnabled = compressionMethod.equals("gzip"); - return this; - } - - /** - * Sets the maximum time to wait for the export of a batch of spans. If unset, defaults to 10s. - * - * @return this. - * @since 1.2.0 - */ - public ZipkinSpanExporterBuilder setReadTimeout(long timeout, TimeUnit unit) { - requireNonNull(unit, "unit"); - if (timeout < 0) { - throw new IllegalArgumentException("timeout must be non-negative"); - } - long timeoutMillis = timeout == 0 ? Long.MAX_VALUE : unit.toMillis(timeout); - this.readTimeoutMillis = (int) Math.min(timeoutMillis, Integer.MAX_VALUE); - return this; - } - - /** - * Sets the maximum time to wait for the export of a batch of spans. If unset, defaults to 10s. - * - * @return this. - * @since 1.2.0 - */ - public ZipkinSpanExporterBuilder setReadTimeout(Duration timeout) { - requireNonNull(timeout, "timeout"); - setReadTimeout(timeout.toMillis(), TimeUnit.MILLISECONDS); - return this; - } - - /** - * Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses - * {@link GlobalOpenTelemetry#getMeterProvider()}. - * - * @return this. - * @since 1.17.0 - */ - public ZipkinSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) { - requireNonNull(meterProvider, "meterProvider"); - this.meterProviderSupplier = () -> meterProvider; - return this; - } - - /** - * Sets the {@link InternalTelemetryVersion} defining which self-monitoring metrics this exporter - * collects. - * - * @since 1.51.0 - */ - public ZipkinSpanExporterBuilder setInternalTelemetryVersion(InternalTelemetryVersion level) { - requireNonNull(level, "level"); - this.internalTelemetryVersion = level; - return this; - } - - String toString(boolean includePrefixAndSuffix) { - StringJoiner joiner = - includePrefixAndSuffix - ? new StringJoiner(", ", "ZipkinSpanExporterBuilder{", "}") - : new StringJoiner(", "); - joiner.add("endpoint=" + endpoint); - joiner.add("compressionEnabled=" + compressionEnabled); - joiner.add("readTimeoutMillis=" + readTimeoutMillis); - joiner.add("internalTelemetrySchemaVersion=" + internalTelemetryVersion); - // Note: omit sender because we can't log the configuration in any readable way - // Note: omit encoder because we can't log the configuration in any readable way - // Note: omit localIpAddressSupplier because we can't log the configuration in any readable way - // Note: omit meterProviderSupplier because we can't log the configuration in any readable way - return joiner.toString(); - } - - /** - * Builds a {@link ZipkinSpanExporter}. - * - * @return a {@code ZipkinSpanExporter}. - */ - public ZipkinSpanExporter build() { - BytesMessageSender sender = this.sender; - if (sender == null) { - sender = - OkHttpSender.newBuilder() - .endpoint(endpoint) - .compressionEnabled(compressionEnabled) - .readTimeout(readTimeoutMillis) - .build(); - } - OtelToZipkinSpanTransformer transformer = - OtelToZipkinSpanTransformer.create(localIpAddressSupplier); - return new ZipkinSpanExporter( - this, - encoder, - sender, - meterProviderSupplier, - internalTelemetryVersion, - endpoint, - transformer); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ComponentId.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ComponentId.java deleted file mode 100644 index 15d735df0cf..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ComponentId.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import javax.annotation.Nullable; - -/** - * The component id used for SDK health metrics. This corresponds to the otel.component.name and - * otel.component.id semconv attributes. - * - *

Copied from {@code io.opentelemetry.sdk.common.internal.ComponentId} to avoid shared internal - * code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public abstract class ComponentId { - - private ComponentId() {} - - public abstract String getTypeName(); - - public abstract String getComponentName(); - - static class Lazy extends ComponentId { - - private static final Map nextIdCounters = new ConcurrentHashMap<>(); - - private final String componentType; - @Nullable private volatile String componentName = null; - - Lazy(String componentType) { - this.componentType = componentType; - } - - @Override - public String getTypeName() { - return componentType; - } - - @Override - public String getComponentName() { - if (componentName == null) { - synchronized (this) { - if (componentName == null) { - int id = - nextIdCounters - .computeIfAbsent(componentType, k -> new AtomicInteger(0)) - .getAndIncrement(); - componentName = componentType + "/" + id; - } - } - } - return componentName; - } - } - - public static StandardComponentId generateLazy(StandardComponentId.ExporterType exporterType) { - return new StandardComponentId(exporterType); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterInstrumentation.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterInstrumentation.java deleted file mode 100644 index fc2f2fb8919..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterInstrumentation.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.AttributesBuilder; -import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.sdk.common.InternalTelemetryVersion; -import java.net.URI; -import java.util.function.Supplier; - -/** - * Copied from {@code io.opentelemetry.exporter.internal.ExporterInstrumentation} to avoid shared - * internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class ExporterInstrumentation { - - private final ExporterMetrics implementation; - - public ExporterInstrumentation( - InternalTelemetryVersion schema, - Supplier meterProviderSupplier, - StandardComponentId componentId, - URI endpoint) { - - Signal signal = componentId.getStandardType().signal(); - switch (schema) { - case LEGACY: - implementation = - LegacyExporterMetrics.isSupportedType() - ? new LegacyExporterMetrics(meterProviderSupplier, componentId.getStandardType()) - : NoopExporterMetrics.INSTANCE; - break; - case LATEST: - implementation = - new SemConvExporterMetrics( - meterProviderSupplier, signal, componentId, extractServerAttributes(endpoint)); - break; - default: - throw new IllegalStateException("Unhandled case: " + schema); - } - } - - // visible for testing - static Attributes extractServerAttributes(URI httpEndpoint) { - AttributesBuilder builder = Attributes.builder(); - String host = httpEndpoint.getHost(); - if (host != null) { - builder.put(SemConvAttributes.SERVER_ADDRESS, host); - } - int port = httpEndpoint.getPort(); - if (port == -1) { - String scheme = httpEndpoint.getScheme(); - if ("https".equals(scheme)) { - port = 443; - } else if ("http".equals(scheme)) { - port = 80; - } - } - if (port != -1) { - builder.put(SemConvAttributes.SERVER_PORT, port); - } - return builder.build(); - } - - public Recording startRecordingExport(int itemCount) { - return new Recording(implementation.startRecordingExport(itemCount)); - } - - /** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ - public static class Recording { - - private final ExporterMetrics.Recording delegate; - - private Recording(ExporterMetrics.Recording delegate) { - this.delegate = delegate; - } - - /** Callback to notify that the export was successful. */ - public void finishSuccessful() { - delegate.finishSuccessful(buildRequestAttributes()); - } - - /** - * Callback to notify that the export has failed with the given {@link Throwable} as failure - * cause. - * - * @param failureCause the cause of the failure - */ - public void finishFailed(Throwable failureCause) { - finishFailed(failureCause.getClass().getName()); - } - - /** - * Callback to notify that the export has failed. - * - * @param errorType a failure reason suitable for the error.type attribute - */ - public void finishFailed(String errorType) { - delegate.finishFailed(errorType, buildRequestAttributes()); - } - - private static Attributes buildRequestAttributes() { - return Attributes.empty(); - } - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterMetrics.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterMetrics.java deleted file mode 100644 index 7ef471fe126..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterMetrics.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.api.common.Attributes; -import javax.annotation.Nullable; - -/** - * Copied from {@code io.opentelemetry.exporter.internal.ExporterMetrics} to avoid shared internal - * code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public interface ExporterMetrics { - - Recording startRecordingExport(int itemCount); - - /** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ - abstract class Recording { - - private boolean alreadyEnded = false; - - protected Recording() {} - - public final void finishSuccessful(Attributes requestAttributes) { - ensureEndedOnce(); - doFinish(null, requestAttributes); - } - - public final void finishFailed(String errorType, Attributes requestAttributes) { - ensureEndedOnce(); - if (errorType == null || errorType.isEmpty()) { - throw new IllegalArgumentException("The export failed but no failure reason was provided"); - } - doFinish(errorType, requestAttributes); - } - - private void ensureEndedOnce() { - if (alreadyEnded) { - throw new IllegalStateException("Recording already ended"); - } - alreadyEnded = true; - } - - /** - * Invoked when the export has finished, either successfully or failed. - * - * @param errorType null if the export was successful, otherwise a failure reason suitable for - * the error.type attribute - * @param requestAttributes additional attributes to add to request metrics - */ - protected abstract void doFinish(@Nullable String errorType, Attributes requestAttributes); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/LegacyExporterMetrics.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/LegacyExporterMetrics.java deleted file mode 100644 index 9eae9e1f843..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/LegacyExporterMetrics.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import static io.opentelemetry.api.common.AttributeKey.booleanKey; -import static io.opentelemetry.api.common.AttributeKey.stringKey; - -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.metrics.LongCounter; -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.api.metrics.MeterProvider; -import java.util.function.Supplier; -import javax.annotation.Nullable; - -/** - * Implements health metrics for exporters which were defined prior to the standardization in - * semantic conventions. - * - *

Copied from {@code io.opentelemetry.exporter.internal.LegacyExporterMetrics} to avoid shared - * internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class LegacyExporterMetrics implements ExporterMetrics { - - private static final AttributeKey ATTRIBUTE_KEY_TYPE = stringKey("type"); - private static final AttributeKey ATTRIBUTE_KEY_SUCCESS = booleanKey("success"); - - private final Supplier meterProviderSupplier; - private final String exporterName; - private final String transportName; - private final Attributes seenAttrs; - private final Attributes successAttrs; - private final Attributes failedAttrs; - - /** Access via {@link #seen()}. */ - @Nullable private volatile LongCounter seen; - - /** Access via {@link #exported()} . */ - @Nullable private volatile LongCounter exported; - - LegacyExporterMetrics( - Supplier meterProviderSupplier, - StandardComponentId.ExporterType exporterType) { - this.meterProviderSupplier = meterProviderSupplier; - this.exporterName = "zipkin"; - this.transportName = getTransportName(exporterType); - this.seenAttrs = Attributes.builder().put(ATTRIBUTE_KEY_TYPE, "span").build(); - this.successAttrs = this.seenAttrs.toBuilder().put(ATTRIBUTE_KEY_SUCCESS, true).build(); - this.failedAttrs = this.seenAttrs.toBuilder().put(ATTRIBUTE_KEY_SUCCESS, false).build(); - } - - public static boolean isSupportedType() { - return true; - } - - private static String getTransportName(StandardComponentId.ExporterType exporterType) { - switch (exporterType) { - case ZIPKIN_HTTP_SPAN_EXPORTER: - return "http"; - case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: - return "http-json"; - } - throw new IllegalArgumentException("Not a supported exporter type: " + exporterType); - } - - /** Record number of records seen. */ - private void addSeen(long value) { - seen().add(value, seenAttrs); - } - - /** Record number of records which successfully exported. */ - private void addSuccess(long value) { - exported().add(value, successAttrs); - } - - /** Record number of records which failed to export. */ - private void addFailed(long value) { - exported().add(value, failedAttrs); - } - - private LongCounter seen() { - LongCounter seen = this.seen; - if (seen == null || SemConvExporterMetrics.isNoop(seen)) { - seen = meter().counterBuilder(exporterName + ".exporter.seen").build(); - this.seen = seen; - } - return seen; - } - - private LongCounter exported() { - LongCounter exported = this.exported; - if (exported == null || SemConvExporterMetrics.isNoop(exported)) { - exported = meter().counterBuilder(exporterName + ".exporter.exported").build(); - this.exported = exported; - } - return exported; - } - - private Meter meter() { - MeterProvider meterProvider = meterProviderSupplier.get(); - if (meterProvider == null) { - meterProvider = MeterProvider.noop(); - } - return meterProvider.get("io.opentelemetry.exporters." + exporterName + "-" + transportName); - } - - @Override - public ExporterMetrics.Recording startRecordingExport(int itemCount) { - return new Recording(itemCount); - } - - private class Recording extends ExporterMetrics.Recording { - - private final int itemCount; - - private Recording(int itemCount) { - this.itemCount = itemCount; - addSeen(itemCount); - } - - @Override - protected void doFinish(@Nullable String errorType, Attributes requestAttributes) { - if (errorType != null) { - addFailed(itemCount); - } else { - addSuccess(itemCount); - } - } - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/NoopExporterMetrics.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/NoopExporterMetrics.java deleted file mode 100644 index abea8c9c45a..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/NoopExporterMetrics.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.api.common.Attributes; -import javax.annotation.Nullable; - -/** - * Copied from {@code io.opentelemetry.exporter.internal.NoopExporterMetrics} to avoid shared - * internal code. - */ -class NoopExporterMetrics implements ExporterMetrics { - - static final NoopExporterMetrics INSTANCE = new NoopExporterMetrics(); - - @Override - public Recording startRecordingExport(int itemCount) { - return new NoopRecording(); - } - - private static class NoopRecording extends Recording { - - @Override - protected void doFinish(@Nullable String errorType, Attributes requestAttributes) {} - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/RateLimiter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/RateLimiter.java deleted file mode 100644 index 03230f9ede2..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/RateLimiter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.sdk.common.Clock; -import java.util.concurrent.atomic.AtomicLong; - -/** - * This class was taken from Jaeger java client. - * https://github.com/jaegertracing/jaeger-client-java/blob/master/jaeger-core/src/main/java/io/jaegertracing/internal/samplers/RateLimitingSampler.java - * - *

Variables have been renamed for clarity. - * - *

Copied from {@code io.opentelemetry.sdk.common.internal.RateLimiter} to avoid shared internal - * code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class RateLimiter { - private final Clock clock; - private final double creditsPerNanosecond; - private final long maxBalance; // max balance in nano ticks - private final AtomicLong currentBalance; // last op nano time less remaining balance - - /** - * Create a new RateLimiter with the provided parameters. - * - * @param creditsPerSecond How many credits to accrue per second. - * @param maxBalance The maximum balance that the limiter can hold, which corresponds to the rate - * that is being limited to. - * @param clock An implementation of the {@link Clock} interface. - */ - public RateLimiter(double creditsPerSecond, double maxBalance, Clock clock) { - this.clock = clock; - this.creditsPerNanosecond = creditsPerSecond / 1.0e9; - this.maxBalance = (long) (maxBalance / creditsPerNanosecond); - this.currentBalance = new AtomicLong(clock.nanoTime() - this.maxBalance); - } - - /** - * Check to see if the provided cost can be spent within the current limits. Will deduct the cost - * from the current balance if it can be spent. - */ - public boolean trySpend(double itemCost) { - long cost = (long) (itemCost / creditsPerNanosecond); - long currentNanos; - long currentBalanceNanos; - long availableBalanceAfterWithdrawal; - do { - currentBalanceNanos = this.currentBalance.get(); - currentNanos = clock.nanoTime(); - long currentAvailableBalance = currentNanos - currentBalanceNanos; - if (currentAvailableBalance > maxBalance) { - currentAvailableBalance = maxBalance; - } - availableBalanceAfterWithdrawal = currentAvailableBalance - cost; - if (availableBalanceAfterWithdrawal < 0) { - return false; - } - } while (!this.currentBalance.compareAndSet( - currentBalanceNanos, currentNanos - availableBalanceAfterWithdrawal)); - return true; - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvAttributes.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvAttributes.java deleted file mode 100644 index 14a39c7c0a7..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvAttributes.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.api.common.AttributeKey; - -/** - * Provides access to semantic convention attributes used within the SDK implementation. This avoids - * having to pull in semantic conventions as a dependency, which would easily collide and conflict - * with user-provided dependencies. - * - *

Copied from {@code io.opentelemetry.sdk.common.internal.SemConvAttributes} to avoid shared - * internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class SemConvAttributes { - - private SemConvAttributes() {} - - public static final AttributeKey OTEL_COMPONENT_TYPE = - AttributeKey.stringKey("otel.component.type"); - public static final AttributeKey OTEL_COMPONENT_NAME = - AttributeKey.stringKey("otel.component.name"); - public static final AttributeKey ERROR_TYPE = AttributeKey.stringKey("error.type"); - - public static final AttributeKey SERVER_ADDRESS = - AttributeKey.stringKey("server.address"); - public static final AttributeKey SERVER_PORT = AttributeKey.longKey("server.port"); -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvExporterMetrics.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvExporterMetrics.java deleted file mode 100644 index 18254fd21ec..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvExporterMetrics.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.AttributesBuilder; -import io.opentelemetry.api.metrics.DoubleHistogram; -import io.opentelemetry.api.metrics.LongCounter; -import io.opentelemetry.api.metrics.LongUpDownCounter; -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.sdk.common.Clock; -import java.util.Collections; -import java.util.function.Supplier; -import javax.annotation.Nullable; - -/** - * Copied from {@code io.opentelemetry.exporter.internal.SemConvExporterMetrics} to avoid shared - * internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class SemConvExporterMetrics implements ExporterMetrics { - - private static final Clock CLOCK = Clock.getDefault(); - - private final Supplier meterProviderSupplier; - private final Signal signal; - private final ComponentId componentId; - private final Attributes additionalAttributes; - - @Nullable private volatile LongUpDownCounter inflight = null; - @Nullable private volatile LongCounter exported = null; - @Nullable private volatile DoubleHistogram duration = null; - @Nullable private volatile Attributes allAttributes = null; - - public SemConvExporterMetrics( - Supplier meterProviderSupplier, - Signal signal, - ComponentId componentId, - Attributes additionalAttributes) { - this.meterProviderSupplier = meterProviderSupplier; - this.componentId = componentId; - this.signal = signal; - this.additionalAttributes = additionalAttributes; - } - - @Override - public ExporterMetrics.Recording startRecordingExport(int itemCount) { - return new Recording(itemCount); - } - - private Meter meter() { - MeterProvider meterProvider = meterProviderSupplier.get(); - if (meterProvider == null) { - meterProvider = MeterProvider.noop(); - } - return meterProvider.get("io.opentelemetry.exporters." + componentId.getTypeName()); - } - - private Attributes allAttributes() { - // attributes are initialized lazily to trigger lazy initialization of the componentId - Attributes allAttributes = this.allAttributes; - if (allAttributes == null) { - AttributesBuilder builder = Attributes.builder(); - builder.put(SemConvAttributes.OTEL_COMPONENT_TYPE, componentId.getTypeName()); - builder.put(SemConvAttributes.OTEL_COMPONENT_NAME, componentId.getComponentName()); - builder.putAll(additionalAttributes); - allAttributes = builder.build(); - this.allAttributes = allAttributes; - } - return allAttributes; - } - - private LongUpDownCounter inflight() { - LongUpDownCounter inflight = this.inflight; - if (inflight == null || isNoop(inflight)) { - String unit = signal.getMetricUnit(); - inflight = - meter() - .upDownCounterBuilder(signal.getExporterMetricNamespace() + ".inflight") - .setUnit("{" + unit + "}") - .setDescription( - "The number of " - + unit - + "s which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)") - .build(); - this.inflight = inflight; - } - return inflight; - } - - private LongCounter exported() { - LongCounter exported = this.exported; - if (exported == null || isNoop(exported)) { - String unit = signal.getMetricUnit(); - exported = - meter() - .counterBuilder(signal.getExporterMetricNamespace() + ".exported") - .setUnit("{" + unit + "}") - .setDescription( - "The number of " - + unit - + "s for which the export has finished, either successful or failed") - .build(); - this.exported = exported; - } - return exported; - } - - private DoubleHistogram duration() { - DoubleHistogram duration = this.duration; - if (duration == null || isNoop(duration)) { - duration = - meter() - .histogramBuilder("otel.sdk.exporter.operation.duration") - .setUnit("s") - .setDescription("The duration of exporting a batch of telemetry records") - .setExplicitBucketBoundariesAdvice(Collections.emptyList()) - .build(); - this.duration = duration; - } - return duration; - } - - private void incrementInflight(long count) { - inflight().add(count, allAttributes()); - } - - private void decrementInflight(long count) { - inflight().add(-count, allAttributes()); - } - - private void incrementExported(long count, @Nullable String errorType) { - exported().add(count, getAttributesWithPotentialError(errorType, Attributes.empty())); - } - - static boolean isNoop(Object instrument) { - // This is a poor way to identify a Noop implementation, but the API doesn't provide a better - // way. Perhaps we could add a common "Noop" interface to allow for an instanceof check? - return instrument.getClass().getSimpleName().startsWith("Noop"); - } - - private Attributes getAttributesWithPotentialError( - @Nullable String errorType, Attributes additionalAttributes) { - Attributes attributes = allAttributes(); - boolean errorPresent = errorType != null && !errorType.isEmpty(); - if (errorPresent || !additionalAttributes.isEmpty()) { - AttributesBuilder builder = attributes.toBuilder(); - if (errorPresent) { - builder.put(SemConvAttributes.ERROR_TYPE, errorType); - } - attributes = builder.putAll(additionalAttributes).build(); - } - return attributes; - } - - private void recordDuration( - double seconds, @Nullable String errorType, Attributes requestAttributes) { - duration().record(seconds, getAttributesWithPotentialError(errorType, requestAttributes)); - } - - private class Recording extends ExporterMetrics.Recording { - - private final int itemCount; - - private final long startNanoTime; - - private Recording(int itemCount) { - this.itemCount = itemCount; - startNanoTime = CLOCK.nanoTime(); - incrementInflight(itemCount); - } - - @Override - protected void doFinish(@Nullable String errorType, Attributes requestAttributes) { - decrementInflight(itemCount); - incrementExported(itemCount, errorType); - long durationNanos = CLOCK.nanoTime() - startNanoTime; - recordDuration(durationNanos / 1_000_000_000.0, errorType, requestAttributes); - } - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/Signal.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/Signal.java deleted file mode 100644 index 30736dead3d..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/Signal.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -/** - * Copied from {@code io.opentelemetry.sdk.common.internal.Signal} to avoid shared internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public enum Signal { - SPAN("otel.sdk.exporter.span", "span"); - - private final String exporterMetricNamespace; - private final String metricUnit; - - Signal(String exporterMetricNamespace, String metricUnit) { - this.exporterMetricNamespace = exporterMetricNamespace; - this.metricUnit = metricUnit; - } - - public String getExporterMetricNamespace() { - return exporterMetricNamespace; - } - - public String getMetricUnit() { - return metricUnit; - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/StandardComponentId.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/StandardComponentId.java deleted file mode 100644 index 608a361e9b7..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/StandardComponentId.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -/** - * A {@link ComponentId} where the component type is one of {@link ExporterType}. - * - *

Copied from {@code io.opentelemetry.sdk.common.internal.StandardComponentId} to avoid shared - * internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class StandardComponentId extends ComponentId.Lazy { - - /** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ - public enum ExporterType { - ZIPKIN_HTTP_SPAN_EXPORTER("zipkin_http_span_exporter", Signal.SPAN), - /** - * Has the same semconv attribute value as ZIPKIN_HTTP_SPAN_EXPORTER, but we still use a - * different enum value for now because they produce separate legacy metrics. - */ - ZIPKIN_HTTP_JSON_SPAN_EXPORTER("zipkin_http_span_exporter", Signal.SPAN); - - final String value; - private final Signal signal; - - ExporterType(String value, Signal signal) { - this.value = value; - this.signal = signal; - } - - public Signal signal() { - return signal; - } - } - - private final ExporterType standardType; - - StandardComponentId(ExporterType standardType) { - super(standardType.value); - this.standardType = standardType; - } - - public ExporterType getStandardType() { - return standardType; - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ThrottlingLogger.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ThrottlingLogger.java deleted file mode 100644 index b5d8c808bc5..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ThrottlingLogger.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import static java.util.concurrent.TimeUnit.MINUTES; - -import io.opentelemetry.sdk.common.Clock; -import java.util.Locale; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; - -/** - * Will limit the number of log messages emitted, so as not to spam when problems are happening. - * - *

Copied from {@code io.opentelemetry.sdk.common.internal.ThrottlingLogger} to avoid shared - * internal code. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public class ThrottlingLogger { - private static final double DEFAULT_RATE_LIMIT = 5; - private static final double DEFAULT_THROTTLED_RATE_LIMIT = 1; - private static final TimeUnit DEFAULT_RATE_TIME_UNIT = MINUTES; - - private final Logger delegate; - private final AtomicBoolean throttled = new AtomicBoolean(false); - private final RateLimiter fastRateLimiter; - private final RateLimiter throttledRateLimiter; - - private final double rateLimit; - private final double throttledRateLimit; - private final TimeUnit rateTimeUnit; - - /** Create a new logger which will enforce a max number of messages per minute. */ - public ThrottlingLogger(Logger delegate) { - Clock clock = Clock.getDefault(); - this.delegate = delegate; - this.rateLimit = DEFAULT_RATE_LIMIT; - this.throttledRateLimit = DEFAULT_THROTTLED_RATE_LIMIT; - this.rateTimeUnit = DEFAULT_RATE_TIME_UNIT; - this.fastRateLimiter = - new RateLimiter(this.rateLimit / this.rateTimeUnit.toSeconds(1), this.rateLimit, clock); - this.throttledRateLimiter = - new RateLimiter( - this.throttledRateLimit / this.rateTimeUnit.toSeconds(1), - this.throttledRateLimit, - clock); - } - - /** Log a message at the given level. */ - public void log(Level level, String message) { - log(level, message, null); - } - - /** Log a message at the given level with a throwable. */ - public void log(Level level, String message, @Nullable Throwable throwable) { - if (!isLoggable(level)) { - return; - } - if (throttled.get()) { - if (throttledRateLimiter.trySpend(1.0)) { - doLog(level, message, throwable); - } - return; - } - - if (fastRateLimiter.trySpend(1.0)) { - doLog(level, message, throwable); - return; - } - - if (throttled.compareAndSet(false, true)) { - // spend the balance in the throttled one, so that it starts at zero. - throttledRateLimiter.trySpend(throttledRateLimit); - String timeUnitString = rateTimeUnit.toString().toLowerCase(Locale.ROOT); - String throttleMessage = - String.format( - Locale.ROOT, - "Too many log messages detected. Will only log %.0f time(s) per %s from now on.", - throttledRateLimit, - timeUnitString.substring(0, timeUnitString.length() - 1)); - delegate.log(level, throttleMessage); - doLog(level, message, throwable); - } - } - - private void doLog(Level level, String message, @Nullable Throwable throwable) { - if (throwable != null) { - delegate.log(level, message, throwable); - } else { - delegate.log(level, message); - } - } - - /** - * Returns whether the current wrapped logger is set to log at the given level. - * - * @return true if the logger set to log at the requested level. - */ - public boolean isLoggable(Level level) { - return delegate.isLoggable(level); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProvider.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProvider.java deleted file mode 100644 index fc5e0ab64a2..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; -import io.opentelemetry.exporter.zipkin.ZipkinSpanExporterBuilder; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.time.Duration; - -/** - * {@link SpanExporter} SPI implementation for {@link - * io.opentelemetry.exporter.zipkin.ZipkinSpanExporter}. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -@SuppressWarnings("deprecation") -public class ZipkinSpanExporterProvider implements ConfigurableSpanExporterProvider { - @Override - public String getName() { - return "zipkin"; - } - - @Override - public SpanExporter createExporter(ConfigProperties config) { - ZipkinSpanExporterBuilder builder = ZipkinSpanExporter.builder(); - - String endpoint = config.getString("otel.exporter.zipkin.endpoint"); - if (endpoint != null) { - builder.setEndpoint(endpoint); - } - - Duration timeout = config.getDuration("otel.exporter.zipkin.timeout"); - if (timeout != null) { - builder.setReadTimeout(timeout); - } - - return builder.build(); - } -} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/package-info.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/package-info.java deleted file mode 100644 index 8e03649dd64..00000000000 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/package-info.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -@ParametersAreNonnullByDefault -package io.opentelemetry.exporter.zipkin; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/exporters/zipkin/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider b/exporters/zipkin/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider deleted file mode 100644 index 8a45b6fab18..00000000000 --- a/exporters/zipkin/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.exporter.zipkin.internal.ZipkinSpanExporterProvider diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java deleted file mode 100644 index 24b16eb3a06..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.PARENT_SPAN_ID; -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.SPAN_ID; -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.TRACE_ID; -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; -import zipkin2.Endpoint; -import zipkin2.Span; -import zipkin2.reporter.Encoding; -import zipkin2.reporter.SpanBytesEncoder; - -class BytesEncoderAdapterTest { - - /** Contains {@link Span#localEndpoint()} to ensure would be encoded differently. */ - private final Span testSpan = - Span.newBuilder() - .traceId(TRACE_ID) - .parentId(PARENT_SPAN_ID) - .id(SPAN_ID) - .localEndpoint(Endpoint.newBuilder().serviceName("test").build()) - .build(); - - @Test - void testJsonV2() { - BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.JSON_V2); - assertThat(adapter.encoding()).isEqualTo(Encoding.JSON); - assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.JSON_V2.encode(testSpan)); - assertThat(adapter.sizeInBytes(testSpan)) - .isEqualTo(SpanBytesEncoder.JSON_V2.sizeInBytes(testSpan)); - assertThat(adapter).hasToString(SpanBytesEncoder.JSON_V2.toString()); - } - - @Test - void testProtobuf() { - BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.PROTO3); - assertThat(adapter.encoding()).isEqualTo(Encoding.PROTO3); - assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.PROTO3.encode(testSpan)); - assertThat(adapter.sizeInBytes(testSpan)) - .isEqualTo(SpanBytesEncoder.PROTO3.sizeInBytes(testSpan)); - assertThat(adapter).hasToString(SpanBytesEncoder.PROTO3.toString()); - } - - @Test - @SuppressWarnings("deprecation") // we have to use the deprecated thrift encoding to test it - void testThrift() { - BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.THRIFT); - assertThat(adapter.encoding()).isEqualTo(Encoding.THRIFT); - assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.THRIFT.encode(testSpan)); - assertThat(adapter.sizeInBytes(testSpan)) - .isEqualTo(SpanBytesEncoder.THRIFT.sizeInBytes(testSpan)); - assertThat(adapter).hasToString(SpanBytesEncoder.THRIFT.toString()); - } - - @Test - void testJsonV1() { - BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.JSON_V1); - assertThat(adapter.encoding()).isEqualTo(Encoding.JSON); - assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.JSON_V1.encode(testSpan)); - assertThat(adapter.sizeInBytes(testSpan)) - .isEqualTo(SpanBytesEncoder.JSON_V1.sizeInBytes(testSpan)); - assertThat(adapter).hasToString(SpanBytesEncoder.JSON_V1.toString()); - } -} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotationTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotationTest.java deleted file mode 100644 index 429ccd06bf1..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/EventDataToAnnotationTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.api.common.AttributeKey.valueKey; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.KeyValue; -import io.opentelemetry.api.common.Value; -import io.opentelemetry.sdk.trace.data.EventData; -import org.junit.jupiter.api.Test; - -class EventDataToAnnotationTest { - - @Test - void basicConversion() { - - Attributes attrs = - Attributes.builder() - .put("v01", "v1") - .put("v02", 12L) - .put("v03", 123.45) - .put("v04", false) - .put("v05", "foo", "bar", "baz") - .put("v06", 1, 2, 3) - .put("v07", 1.23, 3.45) - .put("v08", true, false, true) - .put(valueKey("v09"), Value.of(new byte[] {1, 2, 3})) - .put(valueKey("v10"), Value.of(KeyValue.of("nested", Value.of("value")))) - .put(valueKey("v11"), Value.of(Value.of("string"), Value.of(123L))) - .put(valueKey("v12"), Value.empty()) - .build(); - String expected = - "\"cat\":{\"v01\":\"v1\",\"v02\":12,\"v03\":123.45,\"v04\":false,\"v05\":[\"foo\",\"bar\",\"baz\"],\"v06\":[1,2,3],\"v07\":[1.23,3.45],\"v08\":[true,false,true],\"v09\":\"AQID\",\"v10\":{\"nested\":\"value\"},\"v11\":[\"string\",123],\"v12\":null}"; - EventData eventData = EventData.create(0, "cat", attrs); - - String result = EventDataToAnnotation.apply(eventData); - - assertThat(result).isEqualTo(expected); - } - - @Test - void empty() { - Attributes attrs = Attributes.empty(); - String expected = "\"dog\":{}"; - EventData eventData = EventData.create(0, "dog", attrs); - - String result = EventDataToAnnotation.apply(eventData); - - assertThat(result).isEqualTo(expected); - } -} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformerTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformerTest.java deleted file mode 100644 index e81e3a3c0e1..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/OtelToZipkinSpanTransformerTest.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.api.common.AttributeKey.booleanArrayKey; -import static io.opentelemetry.api.common.AttributeKey.booleanKey; -import static io.opentelemetry.api.common.AttributeKey.doubleArrayKey; -import static io.opentelemetry.api.common.AttributeKey.doubleKey; -import static io.opentelemetry.api.common.AttributeKey.longArrayKey; -import static io.opentelemetry.api.common.AttributeKey.longKey; -import static io.opentelemetry.api.common.AttributeKey.stringArrayKey; -import static io.opentelemetry.api.common.AttributeKey.stringKey; -import static io.opentelemetry.api.common.AttributeKey.valueKey; -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.spanBuilder; -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.zipkinSpan; -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.zipkinSpanBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.KeyValue; -import io.opentelemetry.api.common.Value; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.sdk.common.InstrumentationScopeInfo; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.data.StatusData; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collections; -import javax.annotation.Nullable; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import zipkin2.Endpoint; -import zipkin2.Span; - -class OtelToZipkinSpanTransformerTest { - - private OtelToZipkinSpanTransformer transformer; - private InetAddress localIp; - - @BeforeEach - void setup() { - localIp = mock(InetAddress.class); - transformer = OtelToZipkinSpanTransformer.create(() -> localIp); - } - - @Test - void generateSpan_remoteParent() { - SpanData data = spanBuilder().build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpanBuilder(Span.Kind.SERVER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_subMicroDurations() { - SpanData data = - spanBuilder() - .setStartEpochNanos(1505855794_194009601L) - .setEndEpochNanos(1505855794_194009999L) - .build(); - - Span expected = - zipkinSpanBuilder(Span.Kind.SERVER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .duration(1) - .build(); - assertThat(transformer.generateSpan(data)).isEqualTo(expected); - } - - @Test - void generateSpan_ServerKind() { - SpanData data = spanBuilder().setKind(SpanKind.SERVER).build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpanBuilder(Span.Kind.SERVER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_ClientKind() { - SpanData data = spanBuilder().setKind(SpanKind.CLIENT).build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpanBuilder(Span.Kind.CLIENT, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_InternalKind() { - SpanData data = spanBuilder().setKind(SpanKind.INTERNAL).build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpanBuilder(null, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_ConsumeKind() { - SpanData data = spanBuilder().setKind(SpanKind.CONSUMER).build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpanBuilder(Span.Kind.CONSUMER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_ProducerKind() { - SpanData data = spanBuilder().setKind(SpanKind.PRODUCER).build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpanBuilder(Span.Kind.PRODUCER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_ResourceServiceNameMapping() { - Resource resource = - Resource.create(Attributes.of(stringKey("service.name"), "super-zipkin-service")); - SpanData data = spanBuilder().setResource(resource).build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder().serviceName("super-zipkin-service").ip(localIp).build(); - Span expectedZipkinSpan = - zipkinSpan(Span.Kind.SERVER, localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - assertThat(transformer.generateSpan(data)).isEqualTo(expectedZipkinSpan); - } - - @Test - void generateSpan_defaultResourceServiceName() { - SpanData data = spanBuilder().setResource(Resource.empty()).build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder() - .serviceName(Resource.getDefault().getAttribute(stringKey("service.name"))) - .ip(localIp) - .build(); - Span expectedZipkinSpan = - zipkinSpan(Span.Kind.SERVER, localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - assertThat(transformer.generateSpan(data)).isEqualTo(expectedZipkinSpan); - } - - @ParameterizedTest - @EnumSource( - value = SpanKind.class, - names = {"CLIENT", "PRODUCER"}) - void generateSpan_RemoteEndpointMapping(SpanKind spanKind) { - Attributes attributes = - Attributes.builder() - .put(stringKey("peer.service"), "remote-test-service") - .put(stringKey("server.socket.address"), "8.8.8.8") - .put(longKey("server.socket.port"), 42L) - .build(); - - SpanData spanData = - spanBuilder() - .setKind(spanKind) - .setResource(Resource.empty()) - .setAttributes(attributes) - .build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder() - .serviceName(Resource.getDefault().getAttribute(stringKey("service.name"))) - .ip(localIp) - .build(); - - Endpoint expectedRemoteEndpoint = - Endpoint.newBuilder().serviceName("remote-test-service").ip("8.8.8.8").port(42).build(); - - Span expectedSpan = - zipkinSpan(toZipkinSpanKind(spanKind), localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .remoteEndpoint(expectedRemoteEndpoint) - .putTag("peer.service", "remote-test-service") - .putTag("server.socket.address", "8.8.8.8") - .putTag("server.socket.port", "42") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - - assertThat(transformer.generateSpan(spanData)).isEqualTo(expectedSpan); - } - - @ParameterizedTest - @EnumSource( - value = SpanKind.class, - names = {"SERVER", "CONSUMER", "INTERNAL"}) - void generateSpan_RemoteEndpointMappingWhenKindIsNotClientOrProducer(SpanKind spanKind) { - Attributes attributes = - Attributes.builder() - .put("peer.service", "remote-test-service") - .put("server.socket.address", "8.8.8.8") - .put("server.socket.port", 42L) - .build(); - - SpanData spanData = - spanBuilder() - .setKind(spanKind) - .setResource(Resource.empty()) - .setAttributes(attributes) - .build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder() - .serviceName(Resource.getDefault().getAttribute(stringKey("service.name"))) - .ip(localIp) - .build(); - - Span expectedSpan = - zipkinSpan(toZipkinSpanKind(spanKind), localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .remoteEndpoint(null) - .putTag("peer.service", "remote-test-service") - .putTag("server.socket.address", "8.8.8.8") - .putTag("server.socket.port", "42") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - - assertThat(transformer.generateSpan(spanData)).isEqualTo(expectedSpan); - } - - @ParameterizedTest - @EnumSource( - value = SpanKind.class, - names = {"CLIENT", "PRODUCER"}) - void generateSpan_RemoteEndpointMappingWhenServiceNameIsMissing(SpanKind spanKind) { - Attributes attributes = - Attributes.builder() - .put("server.socket.address", "8.8.8.8") - .put("server.socket.port", 42L) - .build(); - - SpanData spanData = - spanBuilder() - .setKind(spanKind) - .setResource(Resource.empty()) - .setAttributes(attributes) - .build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder() - .serviceName(Resource.getDefault().getAttribute(stringKey("service.name"))) - .ip(localIp) - .build(); - - Span expectedSpan = - zipkinSpan(toZipkinSpanKind(spanKind), localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .remoteEndpoint(null) - .putTag("server.socket.address", "8.8.8.8") - .putTag("server.socket.port", "42") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - - assertThat(transformer.generateSpan(spanData)).isEqualTo(expectedSpan); - } - - @ParameterizedTest - @EnumSource( - value = SpanKind.class, - names = {"CLIENT", "PRODUCER"}) - void generateSpan_RemoteEndpointMappingWhenPortIsMissing(SpanKind spanKind) { - Attributes attributes = - Attributes.builder() - .put("peer.service", "remote-test-service") - .put("server.socket.address", "8.8.8.8") - .build(); - - SpanData spanData = - spanBuilder() - .setKind(spanKind) - .setResource(Resource.empty()) - .setAttributes(attributes) - .build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder() - .serviceName(Resource.getDefault().getAttribute(stringKey("service.name"))) - .ip(localIp) - .build(); - - Endpoint expectedRemoteEndpoint = - Endpoint.newBuilder().serviceName("remote-test-service").ip("8.8.8.8").build(); - - Span expectedSpan = - zipkinSpan(toZipkinSpanKind(spanKind), localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .remoteEndpoint(expectedRemoteEndpoint) - .putTag("peer.service", "remote-test-service") - .putTag("server.socket.address", "8.8.8.8") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - - assertThat(transformer.generateSpan(spanData)).isEqualTo(expectedSpan); - } - - @ParameterizedTest - @EnumSource( - value = SpanKind.class, - names = {"CLIENT", "PRODUCER"}) - void generateSpan_RemoteEndpointMappingWhenIpAndPortAreMissing(SpanKind spanKind) { - Attributes attributes = Attributes.builder().put("peer.service", "remote-test-service").build(); - - SpanData spanData = - spanBuilder() - .setKind(spanKind) - .setResource(Resource.empty()) - .setAttributes(attributes) - .build(); - - Endpoint expectedLocalEndpoint = - Endpoint.newBuilder() - .serviceName(Resource.getDefault().getAttribute(stringKey("service.name"))) - .ip(localIp) - .build(); - - Endpoint expectedRemoteEndpoint = - Endpoint.newBuilder().serviceName("remote-test-service").build(); - - Span expectedSpan = - zipkinSpan(toZipkinSpanKind(spanKind), localIp).toBuilder() - .localEndpoint(expectedLocalEndpoint) - .remoteEndpoint(expectedRemoteEndpoint) - .putTag("peer.service", "remote-test-service") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - - assertThat(transformer.generateSpan(spanData)).isEqualTo(expectedSpan); - } - - @Test - void generateSpan_WithAttributes() { - Attributes attributes = - Attributes.builder() - .put(stringKey("string"), "string value") - .put(booleanKey("boolean"), false) - .put(longKey("long"), 9999L) - .put(doubleKey("double"), 222.333d) - .put(booleanArrayKey("booleanArray"), Arrays.asList(true, false)) - .put(stringArrayKey("stringArray"), Collections.singletonList("Hello")) - .put(doubleArrayKey("doubleArray"), Arrays.asList(32.33d, -98.3d)) - .put(longArrayKey("longArray"), Arrays.asList(33L, 999L)) - .put(valueKey("bytes"), Value.of(new byte[] {1, 2, 3})) - .put(valueKey("map"), Value.of(KeyValue.of("nested", Value.of("value")))) - .put(valueKey("heterogeneousArray"), Value.of(Value.of("string"), Value.of(123L))) - .put(valueKey("empty"), Value.empty()) - .build(); - SpanData data = - spanBuilder() - .setAttributes(attributes) - .setTotalAttributeCount(32) - .setTotalRecordedEvents(3) - .setKind(SpanKind.CLIENT) - .build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpan(Span.Kind.CLIENT, localIp).toBuilder() - .putTag("string", "string value") - .putTag("boolean", "false") - .putTag("long", "9999") - .putTag("double", "222.333") - .putTag("booleanArray", "true,false") - .putTag("stringArray", "Hello") - .putTag("doubleArray", "32.33,-98.3") - .putTag("longArray", "33,999") - .putTag("bytes", "AQID") - .putTag("map", "{\"nested\":\"value\"}") - .putTag("heterogeneousArray", "[\"string\",123]") - .putTag("empty", "") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .putTag(OtelToZipkinSpanTransformer.OTEL_DROPPED_ATTRIBUTES_COUNT, "20") - .putTag(OtelToZipkinSpanTransformer.OTEL_DROPPED_EVENTS_COUNT, "1") - .build()); - } - - @Test - void generateSpan_WithInstrumentationLibraryInfo() { - SpanData data = - spanBuilder() - .setInstrumentationScopeInfo( - InstrumentationScopeInfo.builder("io.opentelemetry.auto") - .setVersion("1.0.0") - .build()) - .setKind(SpanKind.CLIENT) - .build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpan(Span.Kind.CLIENT, localIp).toBuilder() - .putTag("otel.scope.name", "io.opentelemetry.auto") - .putTag("otel.scope.version", "1.0.0") - .putTag("otel.library.name", "io.opentelemetry.auto") - .putTag("otel.library.version", "1.0.0") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build()); - } - - @Test - void generateSpan_AlreadyHasHttpStatusInfo() { - Attributes attributes = - Attributes.of( - longKey("http.response.status.code"), - 404L, - stringKey("error"), - "A user provided error"); - SpanData data = - spanBuilder() - .setAttributes(attributes) - .setKind(SpanKind.CLIENT) - .setStatus(StatusData.error()) - .setTotalAttributeCount(2) - .build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpan(Span.Kind.CLIENT, localIp).toBuilder() - .clearTags() - .putTag("http.response.status.code", "404") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "ERROR") - .putTag("error", "A user provided error") - .build()); - } - - @Test - void generateSpan_WithRpcTimeoutErrorStatus_WithTimeoutErrorDescription() { - Attributes attributes = Attributes.of(stringKey("rpc.service"), "my service name"); - - String errorMessage = "timeout"; - - SpanData data = - spanBuilder() - .setStatus(StatusData.create(StatusCode.ERROR, errorMessage)) - .setAttributes(attributes) - .setTotalAttributeCount(1) - .build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpan(Span.Kind.SERVER, localIp).toBuilder() - .putTag("rpc.service", "my service name") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "ERROR") - .putTag(OtelToZipkinSpanTransformer.STATUS_ERROR.getKey(), errorMessage) - .build()); - } - - @Test - void generateSpan_WithRpcErrorStatus_WithEmptyErrorDescription() { - Attributes attributes = Attributes.of(stringKey("rpc.service"), "my service name"); - - SpanData data = - spanBuilder() - .setStatus(StatusData.create(StatusCode.ERROR, "")) - .setAttributes(attributes) - .setTotalAttributeCount(1) - .build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpan(Span.Kind.SERVER, localIp).toBuilder() - .putTag("rpc.service", "my service name") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "ERROR") - .putTag(OtelToZipkinSpanTransformer.STATUS_ERROR.getKey(), "") - .build()); - } - - @Test - void generateSpan_WithRpcUnsetStatus() { - Attributes attributes = Attributes.of(stringKey("rpc.service"), "my service name"); - - SpanData data = - spanBuilder() - .setStatus(StatusData.create(StatusCode.UNSET, "")) - .setAttributes(attributes) - .setTotalAttributeCount(1) - .build(); - - assertThat(transformer.generateSpan(data)) - .isEqualTo( - zipkinSpan(Span.Kind.SERVER, localIp).toBuilder() - .putTag("rpc.service", "my service name") - .build()); - } - - @Nullable - private static Span.Kind toZipkinSpanKind(SpanKind spanKind) { - return spanKind != SpanKind.INTERNAL ? Span.Kind.valueOf(spanKind.name()) : null; - } -} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java deleted file mode 100644 index 38fb9ee078e..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.api.common.AttributeKey.stringKey; -import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; -import static org.mockito.Mockito.mock; - -import com.linecorp.armeria.client.WebClient; -import com.linecorp.armeria.common.AggregatedHttpResponse; -import com.linecorp.armeria.common.HttpData; -import com.linecorp.armeria.common.HttpStatus; -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.TraceFlags; -import io.opentelemetry.api.trace.TraceState; -import io.opentelemetry.internal.testing.slf4j.SuppressLogger; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.common.InstrumentationScopeInfo; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; -import io.opentelemetry.sdk.testing.trace.TestSpanData; -import io.opentelemetry.sdk.trace.IdGenerator; -import io.opentelemetry.sdk.trace.data.EventData; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.data.StatusData; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import zipkin2.Endpoint; -import zipkin2.Span; -import zipkin2.codec.SpanBytesDecoder; -import zipkin2.reporter.BytesMessageSender; -import zipkin2.reporter.Encoding; -import zipkin2.reporter.SpanBytesEncoder; -import zipkin2.reporter.okhttp3.OkHttpSender; - -@SuppressWarnings("deprecation") // testing deprecated code -@Testcontainers(disabledWithoutDocker = true) -class ZipkinSpanExporterEndToEndHttpTest { - private static final WebClient client = WebClient.of(); - - private static final int ZIPKIN_API_PORT = 9411; - - private static final String SPAN_ID = "9cc1e3049173be09"; - private static final String PARENT_SPAN_ID = "8b03ab423da481c5"; - private static final String SPAN_NAME = "Recv.helloworld.Greeter.SayHello"; - private static final long START_EPOCH_NANOS = 1505855794_194009601L; - private static final long END_EPOCH_NANOS = 1505855799_465726528L; - private static final long RECEIVED_TIMESTAMP_NANOS = 1505855799_433901068L; - private static final long SENT_TIMESTAMP_NANOS = 1505855799_459486280L; - private static final Attributes attributes = Attributes.empty(); - private static final List annotations = - Collections.unmodifiableList( - Arrays.asList( - EventData.create(RECEIVED_TIMESTAMP_NANOS, "RECEIVED", Attributes.empty()), - EventData.create(SENT_TIMESTAMP_NANOS, "SENT", Attributes.empty()))); - - private static final String ENDPOINT_V1_SPANS = "/api/v1/spans"; - private static final String ENDPOINT_V2_SPANS = "/api/v2/spans"; - private static final String SERVICE_NAME = "myService"; - - private static final Attributes SEEN_ATTRIBUTES = - Attributes.of(AttributeKey.stringKey("type"), "span"); - private static final Attributes EXPORTED_SUCCESS_ATTRIBUTES = - SEEN_ATTRIBUTES.toBuilder().put(AttributeKey.booleanKey("success"), true).build(); - private static final Attributes EXPORTED_FAILED_ATTRIBUTES = - SEEN_ATTRIBUTES.toBuilder().put(AttributeKey.booleanKey("success"), false).build(); - - @Container - public static final GenericContainer zipkinContainer = - new GenericContainer<>("ghcr.io/openzipkin/zipkin:2.27") - .withExposedPorts(ZIPKIN_API_PORT) - .waitingFor(Wait.forHttp("/health").forPort(ZIPKIN_API_PORT)); - - private final InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); - private final SdkMeterProvider sdkMeterProvider = - SdkMeterProvider.builder().registerMetricReader(sdkMeterReader).build(); - - private static final InetAddress localIp = mock(InetAddress.class); - - @AfterEach - void tearDown() { - sdkMeterProvider.close(); - } - - @Test - void testExportWithDefaultEncoding() { - ZipkinSpanExporter exporter = - ZipkinSpanExporter.builder() - .setEndpoint(zipkinUrl(ENDPOINT_V2_SPANS)) - .setMeterProvider(sdkMeterProvider) - .setLocalIpAddressSupplier(() -> localIp) - .build(); - exportAndVerify(exporter); - - exporter.close(); - verifyMetrics(sdkMeterReader, "http-json", EXPORTED_SUCCESS_ATTRIBUTES); - } - - @Test - void testExportAsProtobuf() { - ZipkinSpanExporter exporter = - buildZipkinExporter( - zipkinUrl(ENDPOINT_V2_SPANS), - Encoding.PROTO3, - SpanBytesEncoder.PROTO3, - sdkMeterProvider); - exportAndVerify(exporter); - - exporter.close(); - verifyMetrics(sdkMeterReader, "http", EXPORTED_SUCCESS_ATTRIBUTES); - } - - @Test - void testExportAsThrift() { - @SuppressWarnings("deprecation") // we have to use the deprecated thrift encoding to test it - ZipkinSpanExporter exporter = - buildZipkinExporter( - zipkinUrl(ENDPOINT_V1_SPANS), - Encoding.THRIFT, - SpanBytesEncoder.THRIFT, - sdkMeterProvider); - exportAndVerify(exporter); - - exporter.close(); - verifyMetrics(sdkMeterReader, "http", EXPORTED_SUCCESS_ATTRIBUTES); - } - - @Test - void testExportAsJsonV1() { - ZipkinSpanExporter exporter = - buildZipkinExporter( - zipkinUrl(ENDPOINT_V1_SPANS), - Encoding.JSON, - SpanBytesEncoder.JSON_V1, - sdkMeterProvider); - exportAndVerify(exporter); - - exporter.close(); - verifyMetrics(sdkMeterReader, "http-json", EXPORTED_SUCCESS_ATTRIBUTES); - } - - @Test - @SuppressLogger(ZipkinSpanExporter.class) - void testExportFailedAsWrongEncoderUsed() { - ZipkinSpanExporter exporter = - buildZipkinExporter( - zipkinUrl(ENDPOINT_V2_SPANS), Encoding.JSON, SpanBytesEncoder.PROTO3, sdkMeterProvider); - - String traceId = IdGenerator.random().generateTraceId(); - SpanData spanData = buildStandardSpan(traceId).build(); - CompletableResultCode resultCode = exporter.export(Collections.singleton(spanData)); - - assertThat(resultCode.isSuccess()).isFalse(); - List zipkinSpans = getTrace(traceId); - assertThat(zipkinSpans).isEmpty(); - - exporter.close(); - verifyMetrics(sdkMeterReader, "http-json", EXPORTED_FAILED_ATTRIBUTES); - } - - private static ZipkinSpanExporter buildZipkinExporter( - String endpoint, Encoding encoding, SpanBytesEncoder encoder, MeterProvider meterProvider) { - BytesMessageSender sender = - OkHttpSender.newBuilder().endpoint(endpoint).encoding(encoding).build(); - return ZipkinSpanExporter.builder() - .setSender(sender) - .setEncoder(encoder) - .setMeterProvider(meterProvider) - .setLocalIpAddressSupplier(() -> localIp) - .build(); - } - - /** - * Exports a span, verify that it was received by Zipkin, and check that the span stored by Zipkin - * matches what was sent. - */ - private static void exportAndVerify(ZipkinSpanExporter zipkinSpanExporter) { - String traceId = IdGenerator.random().generateTraceId(); - SpanData spanData = buildStandardSpan(traceId).build(); - CompletableResultCode resultCode = zipkinSpanExporter.export(Collections.singleton(spanData)); - resultCode.join(10, TimeUnit.SECONDS); - - assertThat(resultCode.isSuccess()).isTrue(); - List zipkinSpans = getTrace(traceId); - - assertThat(zipkinSpans).isNotNull(); - assertThat(zipkinSpans.size()).isEqualTo(1); - assertThat(zipkinSpans.get(0)).isEqualTo(buildZipkinSpan(localIp, traceId)); - } - - private static TestSpanData.Builder buildStandardSpan(String traceId) { - return TestSpanData.builder() - .setSpanContext( - SpanContext.create(traceId, SPAN_ID, TraceFlags.getSampled(), TraceState.getDefault())) - .setParentSpanContext( - SpanContext.create( - traceId, PARENT_SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault())) - .setStatus(StatusData.ok()) - .setKind(SpanKind.SERVER) - .setName(SPAN_NAME) - .setStartEpochNanos(START_EPOCH_NANOS) - .setAttributes(attributes) - .setTotalAttributeCount(attributes.size()) - .setTotalRecordedEvents(annotations.size()) - .setEvents(annotations) - .setLinks(Collections.emptyList()) - .setEndEpochNanos(END_EPOCH_NANOS) - .setHasEnded(true) - .setResource(Resource.create(Attributes.of(stringKey("service.name"), SERVICE_NAME))); - } - - private static Span buildZipkinSpan(InetAddress localAddress, String traceId) { - return Span.newBuilder() - .traceId(traceId) - .parentId(PARENT_SPAN_ID) - .id(SPAN_ID) - .kind(Span.Kind.SERVER) - .name(SPAN_NAME) - .timestamp(START_EPOCH_NANOS / 1000) - .duration((END_EPOCH_NANOS / 1000) - (START_EPOCH_NANOS / 1000)) - .localEndpoint(Endpoint.newBuilder().serviceName(SERVICE_NAME).ip(localAddress).build()) - .addAnnotation(RECEIVED_TIMESTAMP_NANOS / 1000, "\"RECEIVED\":{}") - .addAnnotation(SENT_TIMESTAMP_NANOS / 1000, "\"SENT\":{}") - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - } - - private static List getTrace(String traceId) { - AggregatedHttpResponse response = - client.get(zipkinUrl("/api/v2/trace/" + traceId)).aggregate().join(); - if (response.status().equals(HttpStatus.NOT_FOUND)) { - return Collections.emptyList(); - } - try (HttpData content = response.content()) { - return SpanBytesDecoder.JSON_V2.decodeList(content.array()); - } - } - - private static String zipkinUrl(String endpoint) { - return "http://localhost:" + zipkinContainer.getMappedPort(ZIPKIN_API_PORT) + endpoint; - } - - private static void verifyMetrics( - InMemoryMetricReader sdkMeterReader, String transportName, Attributes exportedAttributes) { - assertThat(sdkMeterReader.collectAllMetrics()) - .allSatisfy( - metric -> - assertThat(metric) - .hasInstrumentationScope( - InstrumentationScopeInfo.create( - "io.opentelemetry.exporters.zipkin-" + transportName))) - .satisfiesExactlyInAnyOrder( - metric -> - assertThat(metric) - .hasName("zipkin.exporter.seen") - .hasLongSumSatisfying( - sum -> - sum.isMonotonic() - .isCumulative() - .hasPointsSatisfying( - point -> point.hasAttributes(SEEN_ATTRIBUTES).hasValue(1))), - metric -> - assertThat(metric) - .hasName("zipkin.exporter.exported") - .hasLongSumSatisfying( - sum -> - sum.isMonotonic() - .isCumulative() - .hasPointsSatisfying( - point -> point.hasAttributes(exportedAttributes).hasValue(1)))); - } -} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java deleted file mode 100644 index 2227c8ff76a..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.spanBuilder; -import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.zipkinSpanBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.github.netmikey.logunit.api.LogCapturer; -import io.opentelemetry.api.impl.InstrumentationUtil; -import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.context.Context; -import io.opentelemetry.internal.testing.slf4j.SuppressLogger; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.common.InternalTelemetryVersion; -import io.opentelemetry.sdk.testing.trace.TestSpanData; -import java.io.IOException; -import java.net.InetAddress; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import zipkin2.Span; -import zipkin2.reporter.BytesEncoder; -import zipkin2.reporter.BytesMessageSender; -import zipkin2.reporter.Encoding; -import zipkin2.reporter.SpanBytesEncoder; - -@ExtendWith(MockitoExtension.class) -@SuppressWarnings("deprecation") // testing deprecated code -class ZipkinSpanExporterTest { - - @Mock private BytesMessageSender mockSender; - @Mock private SpanBytesEncoder mockEncoder; - @Mock private OtelToZipkinSpanTransformer mockTransformer; - @Mock private InetAddress localIp; - - @RegisterExtension - LogCapturer logs = LogCapturer.create().captureForType(ZipkinSpanExporter.class); - - @Test - void testExport() throws IOException { - TestSpanData testSpanData = spanBuilder().build(); - - ZipkinSpanExporter zipkinSpanExporter = - new ZipkinSpanExporter( - new ZipkinSpanExporterBuilder(), - mockEncoder, - mockSender, - MeterProvider::noop, - InternalTelemetryVersion.LATEST, - "http://testing:1234", - mockTransformer); - - byte[] someBytes = new byte[0]; - Span zipkinSpan = - zipkinSpanBuilder(Span.Kind.SERVER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - when(mockTransformer.generateSpan(testSpanData)).thenReturn(zipkinSpan); - when(mockEncoder.encode(zipkinSpan)).thenReturn(someBytes); - - CompletableResultCode resultCode = - zipkinSpanExporter.export(Collections.singleton(testSpanData)); - - assertThat(resultCode.isSuccess()).isTrue(); - - verify(mockSender).send(Collections.singletonList(someBytes)); - } - - @Test - @SuppressLogger(ZipkinSpanExporter.class) - void testExport_failed() throws IOException { - TestSpanData testSpanData = spanBuilder().build(); - - ZipkinSpanExporter zipkinSpanExporter = - new ZipkinSpanExporter( - new ZipkinSpanExporterBuilder(), - mockEncoder, - mockSender, - MeterProvider::noop, - InternalTelemetryVersion.LATEST, - "http://testing:1234", - mockTransformer); - - byte[] someBytes = new byte[0]; - Span zipkinSpan = - zipkinSpanBuilder(Span.Kind.SERVER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - when(mockTransformer.generateSpan(testSpanData)).thenReturn(zipkinSpan); - when(mockEncoder.encode(zipkinSpan)).thenReturn(someBytes); - doThrow(new IOException()).when(mockSender).send(Collections.singletonList(someBytes)); - - CompletableResultCode resultCode = - zipkinSpanExporter.export(Collections.singleton(testSpanData)); - - assertThat(resultCode.isSuccess()).isFalse(); - - verify(mockSender).send(Collections.singletonList(someBytes)); - } - - @Test - void testCreate() { - ZipkinSpanExporter exporter = ZipkinSpanExporter.builder().setSender(mockSender).build(); - - assertThat(exporter).isNotNull(); - } - - @Test - @SuppressLogger(ZipkinSpanExporter.class) - void testShutdown() throws IOException { - ZipkinSpanExporter exporter = ZipkinSpanExporter.builder().setSender(mockSender).build(); - - assertThat(exporter.shutdown().isSuccess()).isTrue(); - verify(mockSender).close(); - assertThat(logs.getEvents()).isEmpty(); - assertThat( - exporter - .export(Collections.singletonList(spanBuilder().build())) - .join(10, TimeUnit.SECONDS) - .isSuccess()) - .isFalse(); - assertThat(exporter.shutdown().isSuccess()).isTrue(); - logs.assertContains("Calling shutdown() multiple times."); - } - - @Test - @SuppressWarnings({"PreferJavaTimeOverload", "deprecation"}) - // we have to use the deprecated setEncoder overload to test it - void invalidConfig() { - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setReadTimeout(-1, TimeUnit.MILLISECONDS)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("timeout must be non-negative"); - - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setReadTimeout(1, null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("unit"); - - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setReadTimeout(null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("timeout"); - - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setEndpoint(null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("endpoint"); - - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setCompression(null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("compressionMethod"); - - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setSender(null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("sender"); - - assertThatThrownBy( - () -> ZipkinSpanExporter.builder().setEncoder((zipkin2.codec.BytesEncoder) null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("encoder"); - - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setEncoder((BytesEncoder) null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("encoder"); - } - - @Test - void encoderProtobuf() { - @SuppressWarnings("deprecation") // we have to use the deprecated setEncoderto test it - ZipkinSpanExporter exporter = - ZipkinSpanExporter.builder().setEncoder(zipkin2.codec.SpanBytesEncoder.PROTO3).build(); - try { - assertThat(exporter).extracting("encoder.encoding").isEqualTo(Encoding.PROTO3); - } finally { - exporter.shutdown(); - } - - exporter = ZipkinSpanExporter.builder().setEncoder(SpanBytesEncoder.PROTO3).build(); - try { - assertThat(exporter).extracting("encoder").isEqualTo(SpanBytesEncoder.PROTO3); - } finally { - exporter.shutdown(); - } - } - - @Test - void compressionDefault() { - ZipkinSpanExporter exporter = ZipkinSpanExporter.builder().build(); - try { - assertThat(exporter).extracting("sender.delegate.compressionEnabled").isEqualTo(true); - } finally { - exporter.shutdown(); - } - } - - @Test - void compressionNone() { - ZipkinSpanExporter exporter = ZipkinSpanExporter.builder().setCompression("none").build(); - try { - assertThat(exporter).extracting("sender.delegate.compressionEnabled").isEqualTo(false); - } finally { - exporter.shutdown(); - } - } - - @Test - void compressionGzip() { - ZipkinSpanExporter exporter = ZipkinSpanExporter.builder().setCompression("gzip").build(); - try { - assertThat(exporter).extracting("sender.delegate.compressionEnabled").isEqualTo(true); - } finally { - exporter.shutdown(); - } - } - - @Test - void compressionEnabledAndDisabled() { - ZipkinSpanExporter exporter = - ZipkinSpanExporter.builder().setCompression("gzip").setCompression("none").build(); - try { - assertThat(exporter).extracting("sender.delegate.compressionEnabled").isEqualTo(false); - } finally { - exporter.shutdown(); - } - } - - @Test - @SuppressWarnings("PreferJavaTimeOverload") - void readTimeout_Zero() { - ZipkinSpanExporter exporter = - ZipkinSpanExporter.builder().setReadTimeout(0, TimeUnit.SECONDS).build(); - - try { - assertThat(exporter) - .extracting("sender.delegate.client.readTimeoutMillis") - .isEqualTo(Integer.MAX_VALUE); - } finally { - exporter.shutdown(); - } - } - - @Test - void stringRepresentation() { - try (ZipkinSpanExporter exporter = ZipkinSpanExporter.builder().build()) { - assertThat(exporter.toString()) - .isEqualTo( - "ZipkinSpanExporter{endpoint=http://localhost:9411/api/v2/spans, compressionEnabled=true, readTimeoutMillis=10000, internalTelemetrySchemaVersion=LEGACY}"); - } - try (ZipkinSpanExporter exporter = - ZipkinSpanExporter.builder() - .setEndpoint("http://zipkin:9411/api/v2/spans") - .setReadTimeout(Duration.ofSeconds(15)) - .setCompression("none") - .build()) { - assertThat(exporter.toString()) - .isEqualTo( - "ZipkinSpanExporter{endpoint=http://zipkin:9411/api/v2/spans, compressionEnabled=false, readTimeoutMillis=15000, internalTelemetrySchemaVersion=LEGACY}"); - } - } - - @Test - void suppressInstrumentation() { - TestSpanData testSpanData = spanBuilder().build(); - - SuppressCatchingSender suppressCatchingSender = new SuppressCatchingSender(Encoding.JSON); - ZipkinSpanExporter zipkinSpanExporter = - new ZipkinSpanExporter( - new ZipkinSpanExporterBuilder(), - mockEncoder, - suppressCatchingSender, - MeterProvider::noop, - InternalTelemetryVersion.LATEST, - "http://testing:1234", - mockTransformer); - - byte[] someBytes = new byte[0]; - Span zipkinSpan = - zipkinSpanBuilder(Span.Kind.SERVER, localIp) - .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK") - .build(); - when(mockTransformer.generateSpan(testSpanData)).thenReturn(zipkinSpan); - when(mockEncoder.encode(zipkinSpan)).thenReturn(someBytes); - - zipkinSpanExporter.export(Collections.singleton(testSpanData)); - - // Instrumentation should be suppressed on send, to avoid incidental spans related to span - // export. - assertTrue(suppressCatchingSender.sent.get()); - assertTrue(suppressCatchingSender.suppressed.get()); - } - - static class SuppressCatchingSender extends BytesMessageSender.Base { - - final AtomicBoolean sent = new AtomicBoolean(); - final AtomicBoolean suppressed = new AtomicBoolean(); - - protected SuppressCatchingSender(Encoding encoding) { - super(encoding); - } - - @Override - public int messageMaxBytes() { - return 1024; - } - - @Override - public void send(List list) throws IOException { - sent.set(true); - suppressed.set(InstrumentationUtil.shouldSuppressInstrumentation(Context.current())); - } - - @Override - public void close() throws IOException {} - } -} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinTestUtil.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinTestUtil.java deleted file mode 100644 index e964be3c85e..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinTestUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin; - -import static io.opentelemetry.api.common.AttributeKey.stringKey; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.TraceFlags; -import io.opentelemetry.api.trace.TraceState; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.testing.trace.TestSpanData; -import io.opentelemetry.sdk.trace.data.EventData; -import io.opentelemetry.sdk.trace.data.StatusData; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import zipkin2.Endpoint; -import zipkin2.Span; - -class ZipkinTestUtil { - - static final String TRACE_ID = "d239036e7d5cec116b562147388b35bf"; - static final String SPAN_ID = "9cc1e3049173be09"; - static final String PARENT_SPAN_ID = "8b03ab423da481c5"; - - private static final Attributes attributes = Attributes.empty(); - private static final List annotations = - Collections.unmodifiableList( - Arrays.asList( - EventData.create(1505855799_433901068L, "RECEIVED", Attributes.empty()), - EventData.create(1505855799_459486280L, "SENT", Attributes.empty()))); - - private ZipkinTestUtil() {} - - static TestSpanData.Builder spanBuilder() { - return TestSpanData.builder() - .setSpanContext( - SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getSampled(), TraceState.getDefault())) - .setParentSpanContext( - SpanContext.create( - TRACE_ID, PARENT_SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault())) - .setResource( - Resource.create( - Attributes.builder().put(stringKey("service.name"), "tweetiebird").build())) - .setStatus(StatusData.ok()) - .setKind(SpanKind.SERVER) - .setName("Recv.helloworld.Greeter.SayHello") - .setStartEpochNanos(1505855794_194009601L) - .setEndEpochNanos(1505855799_465726528L) - .setAttributes(attributes) - .setTotalAttributeCount(attributes.size()) - .setTotalRecordedEvents(annotations.size()) - .setEvents(annotations) - .setLinks(Collections.emptyList()) - .setHasEnded(true); - } - - static Span zipkinSpan(@Nullable Span.Kind kind, InetAddress localIp) { - return zipkinSpanBuilder(kind, localIp).build(); - } - - static Span.Builder zipkinSpanBuilder(@Nullable Span.Kind kind, InetAddress localIp) { - return Span.newBuilder() - .traceId(TRACE_ID) - .parentId(PARENT_SPAN_ID) - .id(SPAN_ID) - .kind(kind) - .name("Recv.helloworld.Greeter.SayHello") - .timestamp(1505855794000000L + 194009601L / 1000) - .duration((1505855799000000L + 465726528L / 1000) - (1505855794000000L + 194009601L / 1000)) - .localEndpoint(Endpoint.newBuilder().ip(localIp).serviceName("tweetiebird").build()) - .addAnnotation(1505855799000000L + 433901068L / 1000, "\"RECEIVED\":{}") - .addAnnotation(1505855799000000L + 459486280L / 1000, "\"SENT\":{}"); - } -} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProviderTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProviderTest.java deleted file mode 100644 index e21b2a7d6f1..00000000000 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProviderTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.zipkin.internal; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; -import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; - -@SuppressWarnings("deprecation") // testing deprecated code -class ZipkinSpanExporterProviderTest { - - private static final ZipkinSpanExporterProvider provider = new ZipkinSpanExporterProvider(); - - @Test - void getName() { - assertThat(provider.getName()).isEqualTo("zipkin"); - } - - @Test - void createExporter_Default() { - try (SpanExporter spanExporter = - provider.createExporter(DefaultConfigProperties.createFromMap(Collections.emptyMap()))) { - assertThat(spanExporter).isInstanceOf(ZipkinSpanExporter.class); - assertThat(spanExporter) - .extracting("sender") - .extracting("delegate") - .extracting("client") - .extracting("readTimeoutMillis") - .isEqualTo(10_000); - assertThat(spanExporter) - .extracting("sender") - .extracting("endpoint") - .isEqualTo("http://localhost:9411/api/v2/spans"); - } - } - - @Test - void createExporter_WithConfiguration() { - Map config = new HashMap<>(); - config.put("otel.exporter.zipkin.endpoint", "http://localhost:8080/spans"); - config.put("otel.exporter.zipkin.timeout", "1s"); - - try (SpanExporter spanExporter = - provider.createExporter(DefaultConfigProperties.createFromMap(config))) { - assertThat(spanExporter).isInstanceOf(ZipkinSpanExporter.class); - assertThat(spanExporter) - .extracting("sender") - .extracting("delegate") - .extracting("client") - .extracting("readTimeoutMillis") - .isEqualTo(1000); - assertThat(spanExporter) - .extracting("sender") - .extracting("endpoint") - .isEqualTo("http://localhost:8080/spans"); - } - } -} diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index 288fff4be41..987b0f903cf 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -76,7 +76,6 @@ testing { implementation("io.prometheus:prometheus-metrics-exporter-httpserver") { exclude(group = "io.prometheus", module = "prometheus-metrics-exposition-formats") } - implementation(project(":exporters:zipkin")) implementation(project(":sdk:testing")) implementation(project(":sdk:trace-shaded-deps")) implementation(project(":sdk-extensions:jaeger-remote-sampler")) diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java index 1cb0f84181c..f98fe404330 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java @@ -32,7 +32,6 @@ final class SpanExporterConfiguration { EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); EXPORTER_ARTIFACT_ID_BY_NAME.put("logging-otlp", "opentelemetry-exporter-logging-otlp"); EXPORTER_ARTIFACT_ID_BY_NAME.put("otlp", "opentelemetry-exporter-otlp"); - EXPORTER_ARTIFACT_ID_BY_NAME.put("zipkin", "opentelemetry-exporter-zipkin"); } // Visible for testing diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java index 3ac7ce6c269..79c848db2d7 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java @@ -45,11 +45,6 @@ void configureExporter_KnownSpiExportersNotOnClasspath() { .hasMessage( "otel.traces.exporter set to \"otlp\" but opentelemetry-exporter-otlp" + " not found on classpath. Make sure to add it as a dependency."); - assertThatThrownBy(() -> configureExporter("zipkin", spiExportersManager)) - .isInstanceOf(ConfigurationException.class) - .hasMessage( - "otel.traces.exporter set to \"zipkin\" but opentelemetry-exporter-zipkin" - + " not found on classpath. Make sure to add it as a dependency."); // Unrecognized exporter assertThatThrownBy(() -> configureExporter("foo", spiExportersManager)) diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java index d09dd4ce0d5..aeea76a4d87 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableSpanExporterTest.java @@ -13,7 +13,6 @@ import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.otlp.internal.OtlpSpanExporterProvider; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; import io.opentelemetry.internal.testing.CleanupExtension; import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; @@ -164,14 +163,14 @@ void configureSpanProcessors_simpleSpanProcessor() { @Test void configureSpanProcessors_batchSpanProcessor() { - String exporterName = "zipkin"; + String exporterName = "noop"; List closeables = new ArrayList<>(); List spanProcessors = TracerProviderConfiguration.configureSpanProcessors( DefaultConfigProperties.createFromMap( Collections.singletonMap("otel.traces.exporter", exporterName)), - ImmutableMap.of(exporterName, ZipkinSpanExporter.builder().build()), + ImmutableMap.of(exporterName, SpanExporter.noop()), InternalTelemetryVersion.LEGACY, MeterProvider.noop(), closeables); @@ -188,12 +187,9 @@ void configureSpanProcessors_multipleExporters() { List spanProcessors = TracerProviderConfiguration.configureSpanProcessors( DefaultConfigProperties.createFromMap( - Collections.singletonMap("otel.traces.exporter", "otlp,zipkin")), + Collections.singletonMap("otel.traces.exporter", "otlp,noop")), ImmutableMap.of( - "otlp", - OtlpGrpcSpanExporter.builder().build(), - "zipkin", - ZipkinSpanExporter.builder().build()), + "otlp", OtlpGrpcSpanExporter.builder().build(), "noop", SpanExporter.noop()), InternalTelemetryVersion.LEGACY, MeterProvider.noop(), closeables); @@ -217,7 +213,7 @@ void configureSpanProcessors_multipleExporters() { spanExporters -> { assertThat(spanExporters.length).isEqualTo(2); assertThat(spanExporters) - .hasAtLeastOneElementOfType(ZipkinSpanExporter.class) + .hasAtLeastOneElementOfType(SpanExporter.noop().getClass()) .hasAtLeastOneElementOfType(OtlpGrpcSpanExporter.class); }); }); @@ -231,12 +227,8 @@ void configureSpanProcessors_multipleExportersWithLogging() { List spanProcessors = TracerProviderConfiguration.configureSpanProcessors( DefaultConfigProperties.createFromMap( - Collections.singletonMap("otel.traces.exporter", "logging,zipkin")), - ImmutableMap.of( - "logging", - LoggingSpanExporter.create(), - "zipkin", - ZipkinSpanExporter.builder().build()), + Collections.singletonMap("otel.traces.exporter", "logging,noop")), + ImmutableMap.of("logging", LoggingSpanExporter.create(), "noop", SpanExporter.noop()), InternalTelemetryVersion.LEGACY, MeterProvider.noop(), closeables); diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java index 95d014f615c..a31280c4177 100644 --- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfigurationTest.java @@ -12,7 +12,6 @@ import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -42,8 +41,6 @@ void configureExporter_KnownSpiExportersOnClasspath() { .isInstanceOf(OtlpJsonLoggingSpanExporter.class); assertThat(SpanExporterConfiguration.configureExporter("otlp", spiExportersManager)) .isInstanceOf(OtlpGrpcSpanExporter.class); - assertThat(SpanExporterConfiguration.configureExporter("zipkin", spiExportersManager)) - .isInstanceOf(ZipkinSpanExporter.class); } @Test diff --git a/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/ComponentIdTest.java b/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/ComponentIdTest.java index 4d3e23c2b2b..241587a97da 100644 --- a/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/ComponentIdTest.java +++ b/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/ComponentIdTest.java @@ -43,8 +43,5 @@ void testStandardTypesUpToDate() { // assertThat(ComponentId.StandardType.OTLP_HTTP_JSON_METRIC_EXPORTER.value) // // .isEqualTo(OtelIncubatingAttributes.OtelComponentTypeIncubatingValues.OTLP_HTTP_JSON_METRIC_EXPORTER); - // assertThat(ComponentId.StandardType.ZIPKIN_HTTP_SPAN_EXPORTER.value) - // - // .isEqualTo(OtelIncubatingAttributes.OtelComponentTypeIncubatingValues.ZIPKIN_HTTP_SPAN_EXPORTER); } } diff --git a/settings.gradle.kts b/settings.gradle.kts index d6120e3b32b..40d84299d41 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -47,7 +47,6 @@ include(":exporters:otlp:common") include(":exporters:otlp:profiles") include(":exporters:otlp:testing-internal") include(":exporters:prometheus") -include(":exporters:zipkin") include(":integration-tests") include(":integration-tests:otlp") include(":integration-tests:tracecontext") From 0843e020448354c614da9267dfa2bbc53293d505 Mon Sep 17 00:00:00 2001 From: Rajkaran Date: Tue, 4 Aug 2026 21:43:33 +0530 Subject: [PATCH 09/17] docs: document legacy metrics (#8683) --- .../logging/otlp/OtlpJsonLoggingLogRecordExporter.java | 3 +++ .../exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java | 3 +++ .../exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java | 3 +++ 3 files changed, 9 insertions(+) diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java index 0c00cca908e..f45ccc0f62c 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java @@ -17,6 +17,9 @@ * A {@link LogRecordExporter} which writes {@linkplain LogRecordData logs} to a {@link Logger} in * OTLP JSON format. Each log line will include a single {@code ResourceLogs}. * + *

Note: This class is superseded by {@link OtlpStdoutLogRecordExporter}, which allows + * configuring a custom logger or output stream. + * * @since 1.19.0 */ public final class OtlpJsonLoggingLogRecordExporter implements LogRecordExporter { diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java index 520b047f5f8..23a5579d0c5 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java @@ -18,6 +18,9 @@ /** * A {@link MetricExporter} which writes {@linkplain MetricData metrics} to a {@link Logger} in OTLP * JSON format. Each log line will include a single {@code ResourceMetrics}. + * + *

Note: This class is superseded by {@link OtlpStdoutMetricExporter}, which allows configuring a + * custom logger or output stream. */ public final class OtlpJsonLoggingMetricExporter implements MetricExporter { diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java index 63901351326..a2500935cc2 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java @@ -16,6 +16,9 @@ /** * A {@link SpanExporter} which writes {@linkplain SpanData spans} to a {@link Logger} in OTLP JSON * format. Each log line will include a single {@code ResourceSpans}. + * + *

Note: This class is superseded by {@link OtlpStdoutSpanExporter}, which allows configuring a + * custom logger or output stream. */ public final class OtlpJsonLoggingSpanExporter implements SpanExporter { From 95b2866b3527a5ac004e4a6e3b3ae8397ee99bed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 09:26:18 -0700 Subject: [PATCH 10/17] Update all patch and minor versions (#8686) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 8 ++++---- settings.gradle.kts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index a4978f2c1c7..bf414902e86 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -31,8 +31,8 @@ val DEPENDENCY_BOMS = listOf( "com.google.guava:guava-bom:33.6.0-jre", "com.google.protobuf:protobuf-bom:4.35.1", "com.squareup.okhttp3:okhttp-bom:$okhttpVersion", - "com.squareup.okio:okio-bom:3.18.0", // applies to transitive dependencies of okhttp - "io.grpc:grpc-bom:1.83.0", + "com.squareup.okio:okio-bom:3.18.1", // applies to transitive dependencies of okhttp + "io.grpc:grpc-bom:1.83.1", "io.netty:netty-bom:4.2.16.Final", "org.assertj:assertj-bom:3.27.7", "org.osgi:org.osgi.test.bom:1.3.0", @@ -72,12 +72,12 @@ val DEPENDENCIES = listOf( "io.prometheus:prometheus-metrics-exposition-formats-no-protobuf:${prometheusServerVersion}", "javax.annotation:javax.annotation-api:1.3.2", "com.github.stefanbirkner:system-rules:1.19.0", - "com.google.api.grpc:proto-google-common-protos:2.73.0", + "com.google.api.grpc:proto-google-common-protos:2.74.0", "com.google.code.findbugs:jsr305:3.0.2", "com.google.guava:guava-beta-checker:1.0", "com.sun.net.httpserver:http:20070405", "com.squareup.okhttp3:okhttp:$okhttpVersion", - "com.tngtech.archunit:archunit-junit5:1.4.2", + "com.tngtech.archunit:archunit-junit5:1.5.0", "com.uber.nullaway:nullaway:0.13.8", "edu.berkeley.cs.jqf:jqf-fuzz:1.7", // jqf-fuzz version 1.8+ requires Java 11+ "eu.rekawek.toxiproxy:toxiproxy-java:2.1.11", diff --git a/settings.gradle.kts b/settings.gradle.kts index 40d84299d41..593d6e29cb4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,7 +4,7 @@ pluginManagement { id("com.gradle.develocity") version "4.5.0" id("de.undercouch.download") version "5.7.0" id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id("org.graalvm.buildtools.native") version "1.1.6" + id("org.graalvm.buildtools.native") version "1.1.7" id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } } From dd811c4c3187d207626397b02e6f1e86757434a8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 15:16:17 -0500 Subject: [PATCH 11/17] Update weekly update (#8687) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/benchmark-tags.yml | 6 +++--- .github/workflows/benchmark.yml | 6 +++--- .github/workflows/build-daily.yml | 4 ++-- .github/workflows/build-tracecontext-testsuite.yml | 2 +- .github/workflows/build.yml | 6 +++--- .github/workflows/codeql.yml | 8 ++++---- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/javadoc-crawler.yml | 4 ++-- .github/workflows/ossf-scorecard.yml | 2 +- .github/workflows/release.yml | 8 ++++---- .github/workflows/reusable-link-check.yml | 2 +- .../workflows/sonatype-guide-dependency-audit-daily.yml | 4 ++-- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/benchmark-tags.yml b/.github/workflows/benchmark-tags.yml index f43fda3bef3..124651823fb 100644 --- a/.github/workflows/benchmark-tags.yml +++ b/.github/workflows/benchmark-tags.yml @@ -13,7 +13,7 @@ jobs: name: Benchmark SDK runs-on: oracle-bare-metal-64cpu-1024gb-x86-64-ubuntu-24 container: - image: ubuntu:26.04@sha256:3131b4cc82a783df6c9df078f86e01819a13594b865c2cad47bd1bca2b7063bb + image: ubuntu:26.04@sha256:678c6550cc43645e08669028bc177f50be4e7c5b8cca677067b1914d4afc7a03 timeout-minutes: 20 # since there is only a single bare metal runner across all repos strategy: fail-fast: false @@ -28,13 +28,13 @@ jobs: - id: setup-java name: Set up Java for build - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Run jmh run: ./gradlew jmhJar env: diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 258a22c2f9d..89ff69f63d9 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -16,7 +16,7 @@ jobs: name: Benchmark SDK runs-on: oracle-bare-metal-64cpu-1024gb-x86-64-ubuntu-24 container: - image: ubuntu:26.04@sha256:3131b4cc82a783df6c9df078f86e01819a13594b865c2cad47bd1bca2b7063bb + image: ubuntu:26.04@sha256:678c6550cc43645e08669028bc177f50be4e7c5b8cca677067b1914d4afc7a03 timeout-minutes: 120 # since there is only a single bare metal runner across all repos steps: - name: Install Git @@ -31,13 +31,13 @@ jobs: - id: setup-java name: Set up Java for build - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Run jmh run: ./gradlew jmhJar env: diff --git a/.github/workflows/build-daily.yml b/.github/workflows/build-daily.yml index 15f3f8c03f1..0b0b97c9d55 100644 --- a/.github/workflows/build-daily.yml +++ b/.github/workflows/build-daily.yml @@ -22,13 +22,13 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Java - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Publish to Sonatype run: ./gradlew assemble publishToSonatype diff --git a/.github/workflows/build-tracecontext-testsuite.yml b/.github/workflows/build-tracecontext-testsuite.yml index de7586806a6..aefa81a86bd 100644 --- a/.github/workflows/build-tracecontext-testsuite.yml +++ b/.github/workflows/build-tracecontext-testsuite.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Login to GitHub package registry - uses: docker/login-action@371161bbe7024a29a25c5e19bfcbc0804fe9ad2c # v4.5.2 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca3d8fab774..25acff015e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: - id: setup-java-test name: Set up Java ${{ matrix.test-java-version }} for tests - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: # using zulu for 26 because new releases get published quickly distribution: zulu @@ -52,13 +52,13 @@ jobs: - id: setup-java name: Set up Java for build - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Build run: > ./gradlew build diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c59bd531bef..4f74db1b12b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -35,17 +35,17 @@ jobs: - name: Set up Java 21 if: matrix.language == 'java' - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle if: matrix.language == 'java' - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Initialize CodeQL - uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 with: languages: ${{ matrix.language }} # using "linked" helps to keep up with the latest Kotlin support @@ -62,7 +62,7 @@ jobs: DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 5eb702bacbf..c1ec5b7ea7e 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -14,4 +14,4 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # this needs to be in its own workflow in order to make OSSF scorecard happy - - uses: gradle/actions/wrapper-validation@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + - uses: gradle/actions/wrapper-validation@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 diff --git a/.github/workflows/javadoc-crawler.yml b/.github/workflows/javadoc-crawler.yml index 886cc7cee3f..a4ef63579e7 100644 --- a/.github/workflows/javadoc-crawler.yml +++ b/.github/workflows/javadoc-crawler.yml @@ -15,13 +15,13 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + - uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Run crawler run: ./gradlew :javadoc-crawler:crawl diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index c36df2a374b..f38713eb78d 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -44,7 +44,7 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 with: sarif_file: results.sarif diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f1de71af56..4ae73d35c52 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,13 +23,13 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + - uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Build and publish artifacts run: ./gradlew assemble publishToSonatype closeAndReleaseSonatypeStagingRepository @@ -182,13 +182,13 @@ jobs: done - name: Set up JDK for running Gradle - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up Gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 - name: Update apidiff baseline env: diff --git a/.github/workflows/reusable-link-check.yml b/.github/workflows/reusable-link-check.yml index 09f9b4bd61d..61e297a7343 100644 --- a/.github/workflows/reusable-link-check.yml +++ b/.github/workflows/reusable-link-check.yml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 # needed for merge-base used in modified-files mode - - uses: jdx/mise-action@9e7f7633ff6f6d6048a9418a68d48f288f50eb14 # v4.2.3 + - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 - name: Link check for pull requests if: github.event_name == 'pull_request' diff --git a/.github/workflows/sonatype-guide-dependency-audit-daily.yml b/.github/workflows/sonatype-guide-dependency-audit-daily.yml index 2f0334bff80..0c5c2448c5f 100644 --- a/.github/workflows/sonatype-guide-dependency-audit-daily.yml +++ b/.github/workflows/sonatype-guide-dependency-audit-daily.yml @@ -18,13 +18,13 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 + - uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: temurin java-version: 21 - name: Set up gradle - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 # --no-parallel is needed to avoid OverlappingFileLockException on the shared OSS Index cache - run: ./gradlew ossIndexAudit --no-configuration-cache --no-parallel --info From 65ea2757342f1ca6d8a2a4f567fc1cbaccd69161 Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:25:54 +0900 Subject: [PATCH 12/17] Fix broken spec data model link in ImmutableSummaryData javadoc (#8640) --- .../sdk/metrics/internal/data/ImmutableSummaryData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/data/ImmutableSummaryData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/data/ImmutableSummaryData.java index 0c1f4db1bd6..bf5cc390727 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/data/ImmutableSummaryData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/data/ImmutableSummaryData.java @@ -16,7 +16,7 @@ * A summary metric point. * *

See: - * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#summary + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#summary * *

Note: This is called "DoubleSummary" to reflect which primitives are used to record it, * however "Summary" is the equivalent OTLP type. From 3d1cce87bd4a78432cca4214a96586046a6e4590 Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:26:39 +0900 Subject: [PATCH 13/17] Fix ObfuscatedLoggerProvider Javadoc copy-paste example (#8639) --- .../src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java b/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java index 667f5abe14c..5600a676da3 100644 --- a/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java +++ b/sdk/all/src/main/java/io/opentelemetry/sdk/OpenTelemetrySdk.java @@ -202,7 +202,7 @@ public SdkMeterProvider unobfuscate() { * *

Static global providers are obfuscated when they are returned from the API to prevent users * from casting them to their SDK specific implementation. For example, we do not want users to - * use patterns like {@code (SdkMeterProvider) openTelemetry.getMeterProvider()}. + * use patterns like {@code (SdkLoggerProvider) openTelemetry.getLogsBridge()}. */ @ThreadSafe // Visible for testing From 0e033e2ca8128ca470abd33f3ef1f2f684bcf610 Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:27:14 +0900 Subject: [PATCH 14/17] Remove stray token from addLogRecordProcessorCustomizer Javadoc (#8641) --- .../AutoConfiguredOpenTelemetrySdkBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java index 37dbe4262fd..fd5a985ca55 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java @@ -367,9 +367,9 @@ public AutoConfiguredOpenTelemetrySdkBuilder addLogRecordExporterCustomizer( * Adds a {@link BiFunction} to invoke for all autoconfigured {@link * io.opentelemetry.sdk.logs.LogRecordProcessor}s. The return value of the {@link BiFunction} will * replace the passed-in argument. In contrast to {@link - * #addLogRecordExporterCustomizer(BiFunction)} (BiFunction)} this allows modifications to happen - * before batching occurs. As a result, it is possible to efficiently filter logs, add artificial - * logs or delay logs for enhancing them with external, delayed data. + * #addLogRecordExporterCustomizer(BiFunction)} this allows modifications to happen before + * batching occurs. As a result, it is possible to efficiently filter logs, add artificial logs or + * delay logs for enhancing them with external, delayed data. * *

Multiple calls will execute the customizers in order. */ From 3cafbbb6206afc6cebb984d9b81e2339a506f148 Mon Sep 17 00:00:00 2001 From: Liang Hu <35699841+LarryHu0217@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:29:51 -0400 Subject: [PATCH 15/17] Deprecate OpenCensus shim public API (#8674) --- README.md | 2 +- opencensus-shim/README.md | 6 ++++++ .../opencensusshim/OpenCensusMetricProducer.java | 10 ++++++++++ .../opencensusshim/OpenTelemetryContextManager.java | 13 +++++++++++++ .../OpenTelemetryTraceComponentImpl.java | 13 +++++++++++++ .../opentelemetry/opencensusshim/package-info.java | 8 +++++++- .../OpenCensusMetricProducerTest.java | 1 + .../opencensusshim/OpenCensusMetricsTest.java | 1 + 8 files changed, 52 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4e5f3829852..372a1d90d8a 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ Shims for bridging data from one observability library to another. | Component | Description | Artifact ID | Version | Javadoc | |----------------------------------------|--------------------------------------------------------------|----------------------------------|-------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [OpenCensus Shim](./opencensus-shim) | Bridge opencensus metrics into the OpenTelemetry metrics SDK | `opentelemetry-opencensus-shim` | 1.64.0-alpha | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-opencensus-shim.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opencensus-shim) | +| [OpenCensus Shim](./opencensus-shim) | **DEPRECATED** Bridge opencensus metrics into the OpenTelemetry metrics SDK | `opentelemetry-opencensus-shim` | 1.64.0-alpha | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-opencensus-shim.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opencensus-shim) | | [OpenTracing Shim](./opentracing-shim) | **DEPRECATED** Bridge opentracing spans into the OpenTelemetry trace API | `opentelemetry-opentracing-shim` | 1.64.0 | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-opentracing-shim.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opentracing-shim) | diff --git a/opencensus-shim/README.md b/opencensus-shim/README.md index b124e4d2c76..9e8b58a2a7d 100644 --- a/opencensus-shim/README.md +++ b/opencensus-shim/README.md @@ -1,5 +1,11 @@ # OpenTelemetry OpenCensus Shim +> [!WARNING] +> OpenCensus compatibility is deprecated in the OpenTelemetry specification, and this shim is +> deprecated accordingly. It remains available for legacy compatibility, but users should migrate +> OpenCensus instrumentation to the OpenTelemetry APIs. See the +> [OpenTelemetry specification guidance on OpenCensus compatibility](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/opencensus.md). + The OpenCensus shim allows applications and libraries that are instrumented with OpenTelemetry, but depend on other libraries instrumented with OpenCensus, to export trace spans from both OpenTelemetry and OpenCensus with the correct diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducer.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducer.java index 121c61360f1..ddb7b30b068 100644 --- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducer.java +++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducer.java @@ -21,7 +21,12 @@ * both OpenTelemetry and OpenCensus metrics. * *

To use, register with {@link SdkMeterProviderBuilder#registerMetricProducer(MetricProducer)}. + * + * @deprecated OpenCensus compatibility is deprecated in the OpenTelemetry specification (see #5138). + * Expect this artifact to no longer be published after June 2027. */ +@Deprecated public final class OpenCensusMetricProducer implements MetricProducer { private final MetricProducerManager openCensusMetricStorage; @@ -32,7 +37,12 @@ private OpenCensusMetricProducer(MetricProducerManager openCensusMetricStorage) /** * Constructs a new {@link OpenCensusMetricProducer} that reports against the given {@link * Resource}. + * + * @deprecated OpenCensus compatibility is deprecated in the OpenTelemetry specification (see #5138). + * Expect this artifact to no longer be published after June 2027. */ + @Deprecated public static MetricProducer create() { return new OpenCensusMetricProducer(Metrics.getExportComponent().getMetricProducerManager()); } diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryContextManager.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryContextManager.java index 24d9818645c..65c7a9174b4 100644 --- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryContextManager.java +++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryContextManager.java @@ -16,12 +16,25 @@ * {@link io.opencensus.trace.unsafe.ContextManagerImpl}. It is loaded by OpenCensus via reflection * automatically in {@link io.opencensus.trace.unsafe.ContextHandleUtils} when the OpenCensus shim * library exists as a dependency. + * + * @deprecated OpenCensus compatibility is deprecated in the OpenTelemetry specification (see #5138). + * Expect this artifact to no longer be published after June 2027. */ +@Deprecated public final class OpenTelemetryContextManager implements ContextManager { private static final Logger LOGGER = Logger.getLogger(OpenTelemetryContextManager.class.getName()); + /** + * Creates the context manager loaded by OpenCensus through reflection. + * + * @deprecated OpenCensus compatibility is deprecated in the OpenTelemetry specification (see #5138). + * Expect this artifact to no longer be published after June 2027. + */ + @Deprecated @SuppressWarnings("unused") // Loaded via reflection public OpenTelemetryContextManager() {} diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryTraceComponentImpl.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryTraceComponentImpl.java index 503220353b4..4a306aa5627 100644 --- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryTraceComponentImpl.java +++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryTraceComponentImpl.java @@ -21,7 +21,12 @@ * Implementation of the {@link TraceComponent} for OpenTelemetry migration, which uses the * OpenTelemetry migration StartEndHandler. This class is loaded by reflection in {@link * io.opencensus.trace.Tracing} and overrides the OpenCensus default implementation when present. + * + * @deprecated OpenCensus compatibility is deprecated in the OpenTelemetry specification (see #5138). + * Expect this artifact to no longer be published after June 2027. */ +@Deprecated public final class OpenTelemetryTraceComponentImpl extends TraceComponent { private final PropagationComponent propagationComponent = new OpenTelemetryPropagationComponentImpl(); @@ -30,6 +35,14 @@ public final class OpenTelemetryTraceComponentImpl extends TraceComponent { private final TraceConfig traceConfig = makeTraceConfig(); private final Tracer tracer; + /** + * Creates the trace component loaded by OpenCensus through reflection. + * + * @deprecated OpenCensus compatibility is deprecated in the OpenTelemetry specification (see #5138). + * Expect this artifact to no longer be published after June 2027. + */ + @Deprecated @SuppressWarnings("unused") // Loaded via reflection public OpenTelemetryTraceComponentImpl() { clock = MillisClock.getInstance(); diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/package-info.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/package-info.java index 36b5be41e94..9428c9c7dab 100644 --- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/package-info.java +++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/package-info.java @@ -3,7 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** The OpenCensus to OpenTelemetry shim. */ +/** + * Legacy OpenCensus compatibility built on top of OpenTelemetry. + * + *

OpenCensus compatibility is deprecated in the OpenTelemetry specification, and this shim is + * deprecated accordingly. Use this package only for legacy compatibility while migrating OpenCensus + * instrumentation to the OpenTelemetry APIs. + */ @ParametersAreNonnullByDefault package io.opentelemetry.opencensusshim; diff --git a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducerTest.java b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducerTest.java index 67996be5e06..c4fbca32ff3 100644 --- a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducerTest.java +++ b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricProducerTest.java @@ -30,6 +30,7 @@ import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; +@SuppressWarnings("deprecation") // testing deprecated shim API class OpenCensusMetricProducerTest { private final MetricProducer openCensusMetrics = OpenCensusMetricProducer.create(); diff --git a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricsTest.java b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricsTest.java index 4539045c435..3c0db5297b1 100644 --- a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricsTest.java +++ b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenCensusMetricsTest.java @@ -19,6 +19,7 @@ import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; +@SuppressWarnings("deprecation") // testing deprecated shim API class OpenCensusMetricsTest { private static final StatsRecorder STATS_RECORDER = Stats.getStatsRecorder(); From 2009d5840f24251e65aac98c0f2da2f304e0bf7b Mon Sep 17 00:00:00 2001 From: Mohammed AbdessetarElyagoubi Date: Wed, 5 Aug 2026 21:33:58 +0100 Subject: [PATCH 16/17] Avoid exposing configuration values in errors (#8669) --- .../exporter/otlp/internal/OtlpConfigUtil.java | 2 +- .../otlp/internal/OtlpSpanExporterProviderTest.java | 5 +++-- .../spi/internal/DefaultConfigProperties.java | 3 +-- .../autoconfigure/spi/internal/ConfigPropertiesTest.java | 7 ++++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java index 27872dbf03b..5948edb3b3e 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java @@ -165,7 +165,7 @@ static void configureOtlpHeaders( // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables addHeader.accept(key, URLDecoder.decode(value, StandardCharsets.UTF_8.name())); } catch (Exception e) { - throw new ConfigurationException("Cannot decode header value: " + value, e); + throw new ConfigurationException("Cannot decode header value for header: " + key, e); } } } diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java index 1454d209da4..827fdc009ba 100644 --- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java +++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java @@ -303,9 +303,10 @@ void createExporter_decodingError() { () -> { provider.createExporter( DefaultConfigProperties.createFromMap( - Collections.singletonMap("otel.exporter.otlp.headers", "header-key=%-1"))); + Collections.singletonMap( + "otel.exporter.otlp.headers", "header-key=Bearer%20s3cr3t%-1"))); }) .isInstanceOf(ConfigurationException.class) - .hasMessage("Cannot decode header value: %-1"); + .hasMessage("Cannot decode header value for header: header-key"); } } diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java index f8818c015bd..25f4821670e 100644 --- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java +++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java @@ -225,8 +225,7 @@ public Map getMap(String name) { entry -> { String[] split = entry.split("=", 2); if (split.length != 2 || StringUtils.isNullOrEmpty(split[0])) { - throw new ConfigurationException( - "Invalid map property: " + name + "=" + config.get(name)); + throw new ConfigurationException("Invalid map property: " + name); } return filterBlanksAndNulls(split); }) diff --git a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java index 4a119e600cc..4981c8c4f07 100644 --- a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java +++ b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java @@ -161,16 +161,17 @@ void uncleanMap() { void invalidMap() { assertThatThrownBy( () -> - DefaultConfigProperties.createFromMap(Collections.singletonMap("map", "a=1,b")) + DefaultConfigProperties.createFromMap( + Collections.singletonMap("map", "authorization=Bearer s3cr3t,malformed")) .getMap("map")) .isInstanceOf(ConfigurationException.class) - .hasMessage("Invalid map property: map=a=1,b"); + .hasMessage("Invalid map property: map"); assertThatThrownBy( () -> DefaultConfigProperties.createFromMap(Collections.singletonMap("map", "a=1,=b")) .getMap("map")) .isInstanceOf(ConfigurationException.class) - .hasMessage("Invalid map property: map=a=1,=b"); + .hasMessage("Invalid map property: map"); } @Test From 48b0185d06a8d34d713d4fc24d6c70502b6f1531 Mon Sep 17 00:00:00 2001 From: Eunbin Son <58901024+thswlsqls@users.noreply.github.com> Date: Thu, 6 Aug 2026 05:35:45 +0900 Subject: [PATCH 17/17] Do not overwrite existing baggage with empty baggage in JaegerPropagator (#8632) --- .../trace/propagation/JaegerPropagator.java | 6 +++++- .../propagation/JaegerPropagatorTest.java | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/JaegerPropagator.java b/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/JaegerPropagator.java index 4acebd2c399..c984ec7f2c6 100644 --- a/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/JaegerPropagator.java +++ b/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation/JaegerPropagator.java @@ -291,7 +291,11 @@ private static Baggage getBaggageFromHeader(@Nullable C carrier, TextMapGett } } } - return builder == null ? null : builder.build(); + if (builder == null) { + return null; + } + Baggage baggage = builder.build(); + return baggage.isEmpty() ? null : baggage; } /** Returns a two-element array of {@code [entriesAdded, bytesAdded]}. */ diff --git a/extensions/trace-propagators/src/test/java/io/opentelemetry/extension/trace/propagation/JaegerPropagatorTest.java b/extensions/trace-propagators/src/test/java/io/opentelemetry/extension/trace/propagation/JaegerPropagatorTest.java index 80165071e20..f1123fbee2b 100644 --- a/extensions/trace-propagators/src/test/java/io/opentelemetry/extension/trace/propagation/JaegerPropagatorTest.java +++ b/extensions/trace-propagators/src/test/java/io/opentelemetry/extension/trace/propagation/JaegerPropagatorTest.java @@ -443,6 +443,26 @@ void extract_baggageOnly_withHeader_invalid() { .isEqualTo(Baggage.empty()); } + @ParameterizedTest + @MethodSource + void extract_baggageOnly_withHeader_invalid_keepsExistingBaggage(String headerValue) { + Baggage existingBaggage = Baggage.builder().put("user", "alice").build(); + Map carrier = new LinkedHashMap<>(); + carrier.put(BAGGAGE_HEADER, headerValue); + + Context context = Context.root().with(existingBaggage); + assertThat(fromContext(jaegerPropagator.extract(context, carrier, getter))) + .isEqualTo(existingBaggage); + } + + static Stream extract_baggageOnly_withHeader_invalid_keepsExistingBaggage() { + return Stream.of( + Arguments.argumentSet("no separator", "nometa+novalue"), + Arguments.argumentSet("empty value", "user="), + Arguments.argumentSet("empty header", ""), + Arguments.argumentSet("too many separators", "a=b=c")); + } + @Test void extract_baggageOnly_withHeader_andPrefix() { Map carrier = new LinkedHashMap<>();