From 9e466863052d17fc443d767a1ac33b6a5f40992b Mon Sep 17 00:00:00 2001 From: Jack Berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 18 May 2026 13:01:51 -0500 Subject: [PATCH 1/3] Copy zipkin shared internal code refs --- .../all/NoSharedInternalCodeTest.java | 1 - .../InstrumentationUtil.java | 10 +- .../api/internal/InstrumentationUtilTest.java | 1 + .../current_vs_latest/opentelemetry-api.txt | 5 + .../internal/InstrumentationUtil.java | 8 +- .../okhttp/internal/OkHttpGrpcSender.java | 2 +- .../okhttp/internal/OkHttpHttpSender.java | 2 +- .../AbstractOkHttpSuppressionTest.java | 2 +- exporters/zipkin/build.gradle.kts | 1 - .../exporter/zipkin/ZipkinSpanExporter.java | 10 +- .../zipkin/ZipkinSpanExporterBuilder.java | 12 +- .../exporter/zipkin/internal/ComponentId.java | 71 +++++++ .../internal/ExporterInstrumentation.java | 144 +++++++++++++ .../zipkin/internal/ExporterMetrics.java | 61 ++++++ .../internal/LegacyExporterMetrics.java | 199 ++++++++++++++++++ .../zipkin/internal/NoopExporterMetrics.java | 29 +++ .../exporter/zipkin/internal/RateLimiter.java | 68 ++++++ .../zipkin/internal/SemConvAttributes.java | 44 ++++ .../internal/SemConvExporterMetrics.java | 187 ++++++++++++++++ .../exporter/zipkin/internal/Signal.java | 41 ++++ .../zipkin/internal/StandardComponentId.java | 65 ++++++ .../zipkin/internal/ThrottlingLogger.java | 129 ++++++++++++ .../zipkin/ZipkinSpanExporterTest.java | 2 +- 23 files changed, 1071 insertions(+), 23 deletions(-) rename api/all/src/main/java/io/opentelemetry/api/{internal => impl}/InstrumentationUtil.java (74%) create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ComponentId.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterInstrumentation.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterMetrics.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/LegacyExporterMetrics.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/NoopExporterMetrics.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/RateLimiter.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvAttributes.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvExporterMetrics.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/Signal.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/StandardComponentId.java create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ThrottlingLogger.java diff --git a/all/src/test/java/io/opentelemetry/all/NoSharedInternalCodeTest.java b/all/src/test/java/io/opentelemetry/all/NoSharedInternalCodeTest.java index c87fa540198..ec10e2eb172 100644 --- a/all/src/test/java/io/opentelemetry/all/NoSharedInternalCodeTest.java +++ b/all/src/test/java/io/opentelemetry/all/NoSharedInternalCodeTest.java @@ -36,7 +36,6 @@ class NoSharedInternalCodeTest { "opentelemetry-exporter-logging", "opentelemetry-exporter-logging-otlp", "opentelemetry-exporter-prometheus", - "opentelemetry-exporter-zipkin", "opentelemetry-extension-trace-propagators", "opentelemetry-opencensus-shim", "opentelemetry-sdk-common", diff --git a/api/all/src/main/java/io/opentelemetry/api/internal/InstrumentationUtil.java b/api/all/src/main/java/io/opentelemetry/api/impl/InstrumentationUtil.java similarity index 74% rename from api/all/src/main/java/io/opentelemetry/api/internal/InstrumentationUtil.java rename to api/all/src/main/java/io/opentelemetry/api/impl/InstrumentationUtil.java index 4f5c1e676bf..381e03fef3b 100644 --- a/api/all/src/main/java/io/opentelemetry/api/internal/InstrumentationUtil.java +++ b/api/all/src/main/java/io/opentelemetry/api/impl/InstrumentationUtil.java @@ -3,15 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.api.internal; +package io.opentelemetry.api.impl; import io.opentelemetry.context.Context; import io.opentelemetry.context.ContextKey; import java.util.Objects; /** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. + * Utility for suppressing instrumentation cycles between exporters which leverage various client + * libraries in their implementations and the otel java agent which instruments those client + * libraries. + * + *

This class is not intended for use by application developers. Its API is stable and will not + * be changed or removed in a backwards-incompatible manner. */ public final class InstrumentationUtil { private static final ContextKey SUPPRESS_INSTRUMENTATION_KEY = diff --git a/api/all/src/test/java/io/opentelemetry/api/internal/InstrumentationUtilTest.java b/api/all/src/test/java/io/opentelemetry/api/internal/InstrumentationUtilTest.java index 066c906d875..fe235644692 100644 --- a/api/all/src/test/java/io/opentelemetry/api/internal/InstrumentationUtilTest.java +++ b/api/all/src/test/java/io/opentelemetry/api/internal/InstrumentationUtilTest.java @@ -8,6 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import io.opentelemetry.api.impl.InstrumentationUtil; import io.opentelemetry.context.Context; import org.junit.jupiter.api.Test; diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt index 3fe1b53a43e..ee4d560df8c 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt @@ -1,4 +1,9 @@ Comparing source compatibility of opentelemetry-api-1.63.0-SNAPSHOT.jar against opentelemetry-api-1.62.0.jar ++++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.api.impl.InstrumentationUtil (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean shouldSuppressInstrumentation(io.opentelemetry.context.Context) + +++ NEW METHOD: PUBLIC(+) STATIC(+) void suppressInstrumentation(java.lang.Runnable) *** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.logs.LogRecordBuilder (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.logs.LogRecordBuilder setAttribute(java.lang.String, io.opentelemetry.api.common.Value) diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/InstrumentationUtil.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/InstrumentationUtil.java index 9a88fe85060..a40ea3a8664 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/InstrumentationUtil.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/InstrumentationUtil.java @@ -11,8 +11,8 @@ * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. * - * @deprecated use {@link io.opentelemetry.api.internal.InstrumentationUtil} instead. This class - * should be removed once instrumentation does not refer to it anymore. + * @deprecated use {@link io.opentelemetry.api.impl.InstrumentationUtil} instead. This class should + * be removed once instrumentation does not refer to it anymore. */ @Deprecated public final class InstrumentationUtil { @@ -25,7 +25,7 @@ private InstrumentationUtil() {} * calls. */ public static void suppressInstrumentation(Runnable runnable) { - io.opentelemetry.api.internal.InstrumentationUtil.suppressInstrumentation(runnable); + io.opentelemetry.api.impl.InstrumentationUtil.suppressInstrumentation(runnable); } /** @@ -35,6 +35,6 @@ public static void suppressInstrumentation(Runnable runnable) { * instrumentation. */ public static boolean shouldSuppressInstrumentation(Context context) { - return io.opentelemetry.api.internal.InstrumentationUtil.shouldSuppressInstrumentation(context); + return io.opentelemetry.api.impl.InstrumentationUtil.shouldSuppressInstrumentation(context); } } 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 20374358317..fd5ac0f2f03 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 @@ -23,7 +23,7 @@ package io.opentelemetry.exporter.sender.okhttp.internal; -import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.api.impl.InstrumentationUtil; import io.opentelemetry.exporter.internal.RetryUtil; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.Compressor; diff --git a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java index ad35eae4a60..f19bba6204c 100644 --- a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java +++ b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java @@ -5,7 +5,7 @@ package io.opentelemetry.exporter.sender.okhttp.internal; -import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.api.impl.InstrumentationUtil; import io.opentelemetry.exporter.internal.RetryUtil; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.Compressor; diff --git a/exporters/sender/okhttp/src/test/java/io/opentelemetry/exporter/sender/okhttp/internal/AbstractOkHttpSuppressionTest.java b/exporters/sender/okhttp/src/test/java/io/opentelemetry/exporter/sender/okhttp/internal/AbstractOkHttpSuppressionTest.java index 4787bb8a610..f143eb67965 100644 --- a/exporters/sender/okhttp/src/test/java/io/opentelemetry/exporter/sender/okhttp/internal/AbstractOkHttpSuppressionTest.java +++ b/exporters/sender/okhttp/src/test/java/io/opentelemetry/exporter/sender/okhttp/internal/AbstractOkHttpSuppressionTest.java @@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; -import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.api.impl.InstrumentationUtil; import io.opentelemetry.context.Context; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/exporters/zipkin/build.gradle.kts b/exporters/zipkin/build.gradle.kts index bee1da945c4..79171a9b228 100644 --- a/exporters/zipkin/build.gradle.kts +++ b/exporters/zipkin/build.gradle.kts @@ -13,7 +13,6 @@ dependencies { api("io.zipkin.reporter2:zipkin-reporter") - implementation(project(":exporters:common")) implementation(project(":sdk-extensions:autoconfigure-spi")) compileOnly(project(":api:incubator")) 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 index 34405dbbf14..d726a5d5655 100644 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java @@ -5,14 +5,14 @@ package io.opentelemetry.exporter.zipkin; -import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.api.impl.InstrumentationUtil; import io.opentelemetry.api.metrics.MeterProvider; -import io.opentelemetry.exporter.internal.metrics.ExporterInstrumentation; +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.common.internal.ComponentId; -import io.opentelemetry.sdk.common.internal.StandardComponentId; -import io.opentelemetry.sdk.common.internal.ThrottlingLogger; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.io.IOException; 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 index 68007dc442a..98dc68bbc66 100644 --- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java @@ -5,7 +5,6 @@ package io.opentelemetry.exporter.zipkin; -import static io.opentelemetry.api.internal.Utils.checkArgument; import static java.util.Objects.requireNonNull; import io.opentelemetry.api.GlobalOpenTelemetry; @@ -151,9 +150,10 @@ public ZipkinSpanExporterBuilder setEndpoint(String endpoint) { */ public ZipkinSpanExporterBuilder setCompression(String compressionMethod) { requireNonNull(compressionMethod, "compressionMethod"); - checkArgument( - compressionMethod.equals("gzip") || compressionMethod.equals("none"), - "Unsupported compression method. Supported compression methods include: gzip, none."); + 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; } @@ -166,7 +166,9 @@ public ZipkinSpanExporterBuilder setCompression(String compressionMethod) { */ public ZipkinSpanExporterBuilder setReadTimeout(long timeout, TimeUnit unit) { requireNonNull(unit, "unit"); - checkArgument(timeout >= 0, "timeout must be non-negative"); + 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; 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 new file mode 100644 index 00000000000..052b5add211 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ComponentId.java @@ -0,0 +1,71 @@ +/* + * 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 ComponentId generateLazy(String componentType) { + return new Lazy(componentType); + } + + 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 new file mode 100644 index 00000000000..72fb1f0ac7e --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterInstrumentation.java @@ -0,0 +1,144 @@ +/* + * 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 io.opentelemetry.sdk.common.export.GrpcStatusCode; +import java.net.URI; +import java.util.function.Supplier; +import javax.annotation.Nullable; + +/** + * 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(componentId.getStandardType()) + ? new LegacyExporterMetrics(meterProviderSupplier, componentId.getStandardType()) + : NoopExporterMetrics.INSTANCE; + break; + case LATEST: + implementation = + signal == Signal.PROFILE + ? NoopExporterMetrics.INSTANCE + : 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; + @Nullable private Long httpStatusCode; + @Nullable private GrpcStatusCode grpcStatusCode; + + private Recording(ExporterMetrics.Recording delegate) { + this.delegate = delegate; + } + + public void setHttpStatusCode(long httpStatusCode) { + if (grpcStatusCode != null) { + throw new IllegalStateException( + "gRPC status code already set, can only set either gRPC or HTTP"); + } + this.httpStatusCode = httpStatusCode; + } + + public void setGrpcStatusCode(GrpcStatusCode grpcStatusCode) { + if (httpStatusCode != null) { + throw new IllegalStateException( + "HTTP status code already set, can only set either gRPC or HTTP"); + } + this.grpcStatusCode = grpcStatusCode; + } + + /** 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 Attributes buildRequestAttributes() { + if (httpStatusCode != null) { + return Attributes.of(SemConvAttributes.HTTP_RESPONSE_STATUS_CODE, httpStatusCode); + } + if (grpcStatusCode != null) { + return Attributes.of(SemConvAttributes.RPC_RESPONSE_STATUS_CODE, grpcStatusCode.name()); + } + 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 new file mode 100644 index 00000000000..7ef471fe126 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ExporterMetrics.java @@ -0,0 +1,61 @@ +/* + * 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 new file mode 100644 index 00000000000..501f94d9cb9 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/LegacyExporterMetrics.java @@ -0,0 +1,199 @@ +/* + * 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 = getExporterName(exporterType); + this.transportName = getTransportName(exporterType); + this.seenAttrs = + Attributes.builder().put(ATTRIBUTE_KEY_TYPE, getTypeString(exporterType.signal())).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(StandardComponentId.ExporterType exporterType) { + switch (exporterType) { + case OTLP_GRPC_SPAN_EXPORTER: + case OTLP_HTTP_SPAN_EXPORTER: + case OTLP_HTTP_JSON_SPAN_EXPORTER: + case ZIPKIN_HTTP_SPAN_EXPORTER: + case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: + case OTLP_GRPC_LOG_EXPORTER: + case OTLP_HTTP_LOG_EXPORTER: + case OTLP_HTTP_JSON_LOG_EXPORTER: + case OTLP_GRPC_METRIC_EXPORTER: + case OTLP_HTTP_METRIC_EXPORTER: + case OTLP_HTTP_JSON_METRIC_EXPORTER: + return true; + default: + return false; + } + } + + private static String getTypeString(Signal signal) { + switch (signal) { + case SPAN: + return "span"; + case LOG: + return "log"; + case METRIC: + return "metric"; + case PROFILE: + throw new IllegalArgumentException("Profiles are not supported"); + } + throw new IllegalArgumentException("Unhandled signal type: " + signal); + } + + private static String getExporterName(StandardComponentId.ExporterType exporterType) { + switch (exporterType) { + case OTLP_GRPC_SPAN_EXPORTER: + case OTLP_HTTP_SPAN_EXPORTER: + case OTLP_HTTP_JSON_SPAN_EXPORTER: + case OTLP_GRPC_LOG_EXPORTER: + case OTLP_HTTP_LOG_EXPORTER: + case OTLP_HTTP_JSON_LOG_EXPORTER: + case OTLP_GRPC_METRIC_EXPORTER: + case OTLP_HTTP_METRIC_EXPORTER: + case OTLP_HTTP_JSON_METRIC_EXPORTER: + return "otlp"; + case ZIPKIN_HTTP_SPAN_EXPORTER: + case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: + return "zipkin"; + case OTLP_GRPC_PROFILES_EXPORTER: + throw new IllegalArgumentException("Profiles are not supported"); + } + throw new IllegalArgumentException("Not a supported exporter type: " + exporterType); + } + + private static String getTransportName(StandardComponentId.ExporterType exporterType) { + switch (exporterType) { + case OTLP_GRPC_SPAN_EXPORTER: + case OTLP_GRPC_LOG_EXPORTER: + case OTLP_GRPC_METRIC_EXPORTER: + return "grpc"; + case OTLP_HTTP_SPAN_EXPORTER: + case OTLP_HTTP_LOG_EXPORTER: + case OTLP_HTTP_METRIC_EXPORTER: + case ZIPKIN_HTTP_SPAN_EXPORTER: + return "http"; + case OTLP_HTTP_JSON_SPAN_EXPORTER: + case OTLP_HTTP_JSON_LOG_EXPORTER: + case OTLP_HTTP_JSON_METRIC_EXPORTER: + case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: + return "http-json"; + case OTLP_GRPC_PROFILES_EXPORTER: + throw new IllegalArgumentException("Profiles are not supported"); + } + 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 new file mode 100644 index 00000000000..abea8c9c45a --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/NoopExporterMetrics.java @@ -0,0 +1,29 @@ +/* + * 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 new file mode 100644 index 00000000000..03230f9ede2 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/RateLimiter.java @@ -0,0 +1,68 @@ +/* + * 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 new file mode 100644 index 00000000000..27ce2b4b058 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvAttributes.java @@ -0,0 +1,44 @@ +/* + * 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"); + + public static final AttributeKey RPC_RESPONSE_STATUS_CODE = + AttributeKey.stringKey("rpc.response.status_code"); + public static final AttributeKey HTTP_RESPONSE_STATUS_CODE = + AttributeKey.longKey("http.response.status_code"); + + public static final AttributeKey OTEL_SPAN_PARENT_ORIGIN = + AttributeKey.stringKey("otel.span.parent.origin"); + public static final AttributeKey OTEL_SPAN_SAMPLING_RESULT = + AttributeKey.stringKey("otel.span.sampling_result"); +} 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 new file mode 100644 index 00000000000..18254fd21ec --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/SemConvExporterMetrics.java @@ -0,0 +1,187 @@ +/* + * 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 new file mode 100644 index 00000000000..0fde7303854 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/Signal.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.zipkin.internal; + +import java.util.Locale; + +/** + * 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"), + METRIC("otel.sdk.exporter.metric_data_point", "data_point"), + LOG("otel.sdk.exporter.log", "log_record"), + PROFILE("TBD", "TBD"); + + private final String exporterMetricNamespace; + private final String metricUnit; + + Signal(String exporterMetricNamespace, String metricUnit) { + this.exporterMetricNamespace = exporterMetricNamespace; + this.metricUnit = metricUnit; + } + + public String logFriendlyName() { + return name().toLowerCase(Locale.ENGLISH); + } + + 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 new file mode 100644 index 00000000000..a748e5e6c65 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/StandardComponentId.java @@ -0,0 +1,65 @@ +/* + * 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 { + OTLP_GRPC_SPAN_EXPORTER("otlp_grpc_span_exporter", Signal.SPAN), + OTLP_HTTP_SPAN_EXPORTER("otlp_http_span_exporter", Signal.SPAN), + OTLP_HTTP_JSON_SPAN_EXPORTER("otlp_http_json_span_exporter", Signal.SPAN), + OTLP_GRPC_LOG_EXPORTER("otlp_grpc_log_exporter", Signal.LOG), + OTLP_HTTP_LOG_EXPORTER("otlp_http_log_exporter", Signal.LOG), + OTLP_HTTP_JSON_LOG_EXPORTER("otlp_http_json_log_exporter", Signal.LOG), + OTLP_GRPC_METRIC_EXPORTER("otlp_grpc_metric_exporter", Signal.METRIC), + OTLP_HTTP_METRIC_EXPORTER("otlp_http_metric_exporter", Signal.METRIC), + OTLP_HTTP_JSON_METRIC_EXPORTER("otlp_http_json_metric_exporter", Signal.METRIC), + 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), + + OTLP_GRPC_PROFILES_EXPORTER("TBD", Signal.PROFILE); // TODO: not yet standardized in semconv + + 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 new file mode 100644 index 00000000000..0640d1f3399 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ThrottlingLogger.java @@ -0,0 +1,129 @@ +/* + * 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) { + this(delegate, Clock.getDefault()); + } + + /** Alternate way to create logger that allows setting custom intervals and units. * */ + public ThrottlingLogger( + Logger delegate, double rateLimit, double throttledRateLimit, TimeUnit rateTimeUnit) { + this(delegate, Clock.getDefault(), rateLimit, throttledRateLimit, rateTimeUnit); + } + + // visible for testing + ThrottlingLogger(Logger delegate, Clock clock) { + this(delegate, clock, DEFAULT_RATE_LIMIT, DEFAULT_THROTTLED_RATE_LIMIT, DEFAULT_RATE_TIME_UNIT); + } + + ThrottlingLogger( + Logger delegate, + Clock clock, + double rateLimit, + double throttledRateLimit, + TimeUnit rateTimeUnit) { + this.delegate = delegate; + this.rateLimit = rateLimit; + this.throttledRateLimit = throttledRateLimit; + this.rateTimeUnit = rateTimeUnit; + 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/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java index 463b81fc953..2227c8ff76a 100644 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java +++ b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java @@ -15,7 +15,7 @@ import static org.mockito.Mockito.when; import io.github.netmikey.logunit.api.LogCapturer; -import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.api.impl.InstrumentationUtil; import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.context.Context; import io.opentelemetry.internal.testing.slf4j.SuppressLogger; From 79194d34adcab20f80f7d835445360ac3d5d5041 Mon Sep 17 00:00:00 2001 From: Jack Berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 18 May 2026 13:12:11 -0500 Subject: [PATCH 2/3] tree shaking --- .../exporter/zipkin/internal/ComponentId.java | 4 -- .../internal/ExporterInstrumentation.java | 34 +-------- .../internal/LegacyExporterMetrics.java | 71 ++----------------- .../zipkin/internal/SemConvAttributes.java | 10 --- .../exporter/zipkin/internal/Signal.java | 11 +-- .../zipkin/internal/StandardComponentId.java | 13 +--- .../zipkin/internal/ThrottlingLogger.java | 27 ++----- 7 files changed, 13 insertions(+), 157 deletions(-) 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 index 052b5add211..15d735df0cf 100644 --- 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 @@ -61,10 +61,6 @@ public String getComponentName() { } } - public static ComponentId generateLazy(String componentType) { - return new Lazy(componentType); - } - 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 index 72fb1f0ac7e..3812c34f153 100644 --- 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 @@ -9,10 +9,8 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.sdk.common.InternalTelemetryVersion; -import io.opentelemetry.sdk.common.export.GrpcStatusCode; import java.net.URI; import java.util.function.Supplier; -import javax.annotation.Nullable; /** * Copied from {@code io.opentelemetry.exporter.internal.ExporterInstrumentation} to avoid shared @@ -35,16 +33,14 @@ public ExporterInstrumentation( switch (schema) { case LEGACY: implementation = - LegacyExporterMetrics.isSupportedType(componentId.getStandardType()) + LegacyExporterMetrics.isSupportedType() ? new LegacyExporterMetrics(meterProviderSupplier, componentId.getStandardType()) : NoopExporterMetrics.INSTANCE; break; case LATEST: implementation = - signal == Signal.PROFILE - ? NoopExporterMetrics.INSTANCE - : new SemConvExporterMetrics( - meterProviderSupplier, signal, componentId, extractServerAttributes(endpoint)); + new SemConvExporterMetrics( + meterProviderSupplier, signal, componentId, extractServerAttributes(endpoint)); break; default: throw new IllegalStateException("Unhandled case: " + schema); @@ -84,29 +80,11 @@ public Recording startRecordingExport(int itemCount) { public static class Recording { private final ExporterMetrics.Recording delegate; - @Nullable private Long httpStatusCode; - @Nullable private GrpcStatusCode grpcStatusCode; private Recording(ExporterMetrics.Recording delegate) { this.delegate = delegate; } - public void setHttpStatusCode(long httpStatusCode) { - if (grpcStatusCode != null) { - throw new IllegalStateException( - "gRPC status code already set, can only set either gRPC or HTTP"); - } - this.httpStatusCode = httpStatusCode; - } - - public void setGrpcStatusCode(GrpcStatusCode grpcStatusCode) { - if (httpStatusCode != null) { - throw new IllegalStateException( - "HTTP status code already set, can only set either gRPC or HTTP"); - } - this.grpcStatusCode = grpcStatusCode; - } - /** Callback to notify that the export was successful. */ public void finishSuccessful() { delegate.finishSuccessful(buildRequestAttributes()); @@ -132,12 +110,6 @@ public void finishFailed(String errorType) { } private Attributes buildRequestAttributes() { - if (httpStatusCode != null) { - return Attributes.of(SemConvAttributes.HTTP_RESPONSE_STATUS_CODE, httpStatusCode); - } - if (grpcStatusCode != null) { - return Attributes.of(SemConvAttributes.RPC_RESPONSE_STATUS_CODE, grpcStatusCode.name()); - } return Attributes.empty(); } } 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 index 501f94d9cb9..9eae9e1f843 100644 --- 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 @@ -48,86 +48,23 @@ public class LegacyExporterMetrics implements ExporterMetrics { Supplier meterProviderSupplier, StandardComponentId.ExporterType exporterType) { this.meterProviderSupplier = meterProviderSupplier; - this.exporterName = getExporterName(exporterType); + this.exporterName = "zipkin"; this.transportName = getTransportName(exporterType); - this.seenAttrs = - Attributes.builder().put(ATTRIBUTE_KEY_TYPE, getTypeString(exporterType.signal())).build(); + 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(StandardComponentId.ExporterType exporterType) { - switch (exporterType) { - case OTLP_GRPC_SPAN_EXPORTER: - case OTLP_HTTP_SPAN_EXPORTER: - case OTLP_HTTP_JSON_SPAN_EXPORTER: - case ZIPKIN_HTTP_SPAN_EXPORTER: - case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: - case OTLP_GRPC_LOG_EXPORTER: - case OTLP_HTTP_LOG_EXPORTER: - case OTLP_HTTP_JSON_LOG_EXPORTER: - case OTLP_GRPC_METRIC_EXPORTER: - case OTLP_HTTP_METRIC_EXPORTER: - case OTLP_HTTP_JSON_METRIC_EXPORTER: - return true; - default: - return false; - } - } - - private static String getTypeString(Signal signal) { - switch (signal) { - case SPAN: - return "span"; - case LOG: - return "log"; - case METRIC: - return "metric"; - case PROFILE: - throw new IllegalArgumentException("Profiles are not supported"); - } - throw new IllegalArgumentException("Unhandled signal type: " + signal); - } - - private static String getExporterName(StandardComponentId.ExporterType exporterType) { - switch (exporterType) { - case OTLP_GRPC_SPAN_EXPORTER: - case OTLP_HTTP_SPAN_EXPORTER: - case OTLP_HTTP_JSON_SPAN_EXPORTER: - case OTLP_GRPC_LOG_EXPORTER: - case OTLP_HTTP_LOG_EXPORTER: - case OTLP_HTTP_JSON_LOG_EXPORTER: - case OTLP_GRPC_METRIC_EXPORTER: - case OTLP_HTTP_METRIC_EXPORTER: - case OTLP_HTTP_JSON_METRIC_EXPORTER: - return "otlp"; - case ZIPKIN_HTTP_SPAN_EXPORTER: - case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: - return "zipkin"; - case OTLP_GRPC_PROFILES_EXPORTER: - throw new IllegalArgumentException("Profiles are not supported"); - } - throw new IllegalArgumentException("Not a supported exporter type: " + exporterType); + public static boolean isSupportedType() { + return true; } private static String getTransportName(StandardComponentId.ExporterType exporterType) { switch (exporterType) { - case OTLP_GRPC_SPAN_EXPORTER: - case OTLP_GRPC_LOG_EXPORTER: - case OTLP_GRPC_METRIC_EXPORTER: - return "grpc"; - case OTLP_HTTP_SPAN_EXPORTER: - case OTLP_HTTP_LOG_EXPORTER: - case OTLP_HTTP_METRIC_EXPORTER: case ZIPKIN_HTTP_SPAN_EXPORTER: return "http"; - case OTLP_HTTP_JSON_SPAN_EXPORTER: - case OTLP_HTTP_JSON_LOG_EXPORTER: - case OTLP_HTTP_JSON_METRIC_EXPORTER: case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: return "http-json"; - case OTLP_GRPC_PROFILES_EXPORTER: - throw new IllegalArgumentException("Profiles are not supported"); } throw new IllegalArgumentException("Not a supported exporter type: " + exporterType); } 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 index 27ce2b4b058..14a39c7c0a7 100644 --- 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 @@ -31,14 +31,4 @@ private SemConvAttributes() {} public static final AttributeKey SERVER_ADDRESS = AttributeKey.stringKey("server.address"); public static final AttributeKey SERVER_PORT = AttributeKey.longKey("server.port"); - - public static final AttributeKey RPC_RESPONSE_STATUS_CODE = - AttributeKey.stringKey("rpc.response.status_code"); - public static final AttributeKey HTTP_RESPONSE_STATUS_CODE = - AttributeKey.longKey("http.response.status_code"); - - public static final AttributeKey OTEL_SPAN_PARENT_ORIGIN = - AttributeKey.stringKey("otel.span.parent.origin"); - public static final AttributeKey OTEL_SPAN_SAMPLING_RESULT = - AttributeKey.stringKey("otel.span.sampling_result"); } 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 index 0fde7303854..30736dead3d 100644 --- 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 @@ -5,8 +5,6 @@ package io.opentelemetry.exporter.zipkin.internal; -import java.util.Locale; - /** * Copied from {@code io.opentelemetry.sdk.common.internal.Signal} to avoid shared internal code. * @@ -14,10 +12,7 @@ * at any time. */ public enum Signal { - SPAN("otel.sdk.exporter.span", "span"), - METRIC("otel.sdk.exporter.metric_data_point", "data_point"), - LOG("otel.sdk.exporter.log", "log_record"), - PROFILE("TBD", "TBD"); + SPAN("otel.sdk.exporter.span", "span"); private final String exporterMetricNamespace; private final String metricUnit; @@ -27,10 +22,6 @@ public enum Signal { this.metricUnit = metricUnit; } - public String logFriendlyName() { - return name().toLowerCase(Locale.ENGLISH); - } - public String getExporterMetricNamespace() { return exporterMetricNamespace; } 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 index a748e5e6c65..608a361e9b7 100644 --- 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 @@ -21,23 +21,12 @@ public class StandardComponentId extends ComponentId.Lazy { * any time. */ public enum ExporterType { - OTLP_GRPC_SPAN_EXPORTER("otlp_grpc_span_exporter", Signal.SPAN), - OTLP_HTTP_SPAN_EXPORTER("otlp_http_span_exporter", Signal.SPAN), - OTLP_HTTP_JSON_SPAN_EXPORTER("otlp_http_json_span_exporter", Signal.SPAN), - OTLP_GRPC_LOG_EXPORTER("otlp_grpc_log_exporter", Signal.LOG), - OTLP_HTTP_LOG_EXPORTER("otlp_http_log_exporter", Signal.LOG), - OTLP_HTTP_JSON_LOG_EXPORTER("otlp_http_json_log_exporter", Signal.LOG), - OTLP_GRPC_METRIC_EXPORTER("otlp_grpc_metric_exporter", Signal.METRIC), - OTLP_HTTP_METRIC_EXPORTER("otlp_http_metric_exporter", Signal.METRIC), - OTLP_HTTP_JSON_METRIC_EXPORTER("otlp_http_json_metric_exporter", Signal.METRIC), 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), - - OTLP_GRPC_PROFILES_EXPORTER("TBD", Signal.PROFILE); // TODO: not yet standardized in semconv + ZIPKIN_HTTP_JSON_SPAN_EXPORTER("zipkin_http_span_exporter", Signal.SPAN); final String value; private final Signal signal; 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 index 0640d1f3399..b5d8c808bc5 100644 --- 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 @@ -40,30 +40,11 @@ public class ThrottlingLogger { /** Create a new logger which will enforce a max number of messages per minute. */ public ThrottlingLogger(Logger delegate) { - this(delegate, Clock.getDefault()); - } - - /** Alternate way to create logger that allows setting custom intervals and units. * */ - public ThrottlingLogger( - Logger delegate, double rateLimit, double throttledRateLimit, TimeUnit rateTimeUnit) { - this(delegate, Clock.getDefault(), rateLimit, throttledRateLimit, rateTimeUnit); - } - - // visible for testing - ThrottlingLogger(Logger delegate, Clock clock) { - this(delegate, clock, DEFAULT_RATE_LIMIT, DEFAULT_THROTTLED_RATE_LIMIT, DEFAULT_RATE_TIME_UNIT); - } - - ThrottlingLogger( - Logger delegate, - Clock clock, - double rateLimit, - double throttledRateLimit, - TimeUnit rateTimeUnit) { + Clock clock = Clock.getDefault(); this.delegate = delegate; - this.rateLimit = rateLimit; - this.throttledRateLimit = throttledRateLimit; - this.rateTimeUnit = rateTimeUnit; + 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 = From 87d95e3507ccccefab02e735f87906fb89441a69 Mon Sep 17 00:00:00 2001 From: Jack Berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 18 May 2026 13:17:03 -0500 Subject: [PATCH 3/3] Remove zipkin refs in common exporter metric utils --- .../exporter/internal/metrics/LegacyExporterMetrics.java | 7 ------- .../exporter/zipkin/internal/ExporterInstrumentation.java | 2 +- .../sdk/common/internal/StandardComponentId.java | 7 ------- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/metrics/LegacyExporterMetrics.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/metrics/LegacyExporterMetrics.java index a68df15c2c9..235ab16fdaa 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/metrics/LegacyExporterMetrics.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/metrics/LegacyExporterMetrics.java @@ -60,8 +60,6 @@ public static boolean isSupportedType(StandardComponentId.ExporterType exporterT case OTLP_GRPC_SPAN_EXPORTER: case OTLP_HTTP_SPAN_EXPORTER: case OTLP_HTTP_JSON_SPAN_EXPORTER: - case ZIPKIN_HTTP_SPAN_EXPORTER: - case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: case OTLP_GRPC_LOG_EXPORTER: case OTLP_HTTP_LOG_EXPORTER: case OTLP_HTTP_JSON_LOG_EXPORTER: @@ -100,9 +98,6 @@ private static String getExporterName(StandardComponentId.ExporterType exporterT case OTLP_HTTP_METRIC_EXPORTER: case OTLP_HTTP_JSON_METRIC_EXPORTER: return "otlp"; - case ZIPKIN_HTTP_SPAN_EXPORTER: - case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: - return "zipkin"; case OTLP_GRPC_PROFILES_EXPORTER: throw new IllegalArgumentException("Profiles are not supported"); } @@ -118,12 +113,10 @@ private static String getTransportName(StandardComponentId.ExporterType exporter case OTLP_HTTP_SPAN_EXPORTER: case OTLP_HTTP_LOG_EXPORTER: case OTLP_HTTP_METRIC_EXPORTER: - case ZIPKIN_HTTP_SPAN_EXPORTER: return "http"; case OTLP_HTTP_JSON_SPAN_EXPORTER: case OTLP_HTTP_JSON_LOG_EXPORTER: case OTLP_HTTP_JSON_METRIC_EXPORTER: - case ZIPKIN_HTTP_JSON_SPAN_EXPORTER: return "http-json"; case OTLP_GRPC_PROFILES_EXPORTER: throw new IllegalArgumentException("Profiles are not supported"); 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 index 3812c34f153..fc2f2fb8919 100644 --- 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 @@ -109,7 +109,7 @@ public void finishFailed(String errorType) { delegate.finishFailed(errorType, buildRequestAttributes()); } - private Attributes buildRequestAttributes() { + private static Attributes buildRequestAttributes() { return Attributes.empty(); } } diff --git a/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/StandardComponentId.java b/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/StandardComponentId.java index 17cc94fe36f..c9716bdfc15 100644 --- a/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/StandardComponentId.java +++ b/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/StandardComponentId.java @@ -27,13 +27,6 @@ public enum ExporterType { OTLP_GRPC_METRIC_EXPORTER("otlp_grpc_metric_exporter", Signal.METRIC), OTLP_HTTP_METRIC_EXPORTER("otlp_http_metric_exporter", Signal.METRIC), OTLP_HTTP_JSON_METRIC_EXPORTER("otlp_http_json_metric_exporter", Signal.METRIC), - 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), - OTLP_GRPC_PROFILES_EXPORTER("TBD", Signal.PROFILE); // TODO: not yet standardized in semconv final String value;