From 625c44c1cdd229986fec6b890d1d98c2e5846888 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 28 Nov 2022 14:08:13 -0600 Subject: [PATCH] Implement zipkin exporter provider (#4991) --- exporters/zipkin/build.gradle.kts | 1 + .../internal/ZipkinSpanExporterProvider.java | 43 +++++++++++++++++++ ...pi.traces.ConfigurableSpanExporterProvider | 1 + sdk-extensions/autoconfigure/build.gradle.kts | 1 - .../SpanExporterConfiguration.java | 43 ++++++------------- .../sdk/autoconfigure/NotOnClasspathTest.java | 3 +- .../SpanExporterConfigurationTest.java | 10 +++-- 7 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProvider.java create mode 100644 exporters/zipkin/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider diff --git a/exporters/zipkin/build.gradle.kts b/exporters/zipkin/build.gradle.kts index 69d95fad01e..77343900a19 100644 --- a/exporters/zipkin/build.gradle.kts +++ b/exporters/zipkin/build.gradle.kts @@ -15,6 +15,7 @@ dependencies { implementation(project(":exporters:common")) implementation(project(":semconv")) + implementation(project(":sdk-extensions:autoconfigure-spi")) implementation("io.zipkin.reporter2:zipkin-sender-okhttp3") 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 new file mode 100644 index 00000000000..cbd55d386dc --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/internal/ZipkinSpanExporterProvider.java @@ -0,0 +1,43 @@ +/* + * 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 ZipkinSpanExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +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/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 new file mode 100644 index 00000000000..8a45b6fab18 --- /dev/null +++ b/exporters/zipkin/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.zipkin.internal.ZipkinSpanExporterProvider diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index 7c1d6b827a3..0f9fc1295ec 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -21,7 +21,6 @@ dependencies { compileOnly(project(":exporters:otlp:logs")) compileOnly(project(":exporters:otlp:common")) compileOnly(project(":exporters:prometheus")) - compileOnly(project(":exporters:zipkin")) annotationProcessor("com.google.auto.value:auto-value") 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 380cc3c5eaf..7c19a82f45c 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 @@ -19,8 +19,6 @@ import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder; -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.ConfigurationException; import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; @@ -41,6 +39,7 @@ final class SpanExporterConfiguration { static { EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + EXPORTER_ARTIFACT_ID_BY_NAME.put("zipkin", "opentelemetry-exporter-zipkin"); } // Visible for testing @@ -69,12 +68,7 @@ static Map configureSpanExporters( } NamedSpiManager spiExportersManager = - SpiUtil.loadConfigurable( - ConfigurableSpanExporterProvider.class, - ConfigurableSpanExporterProvider::getName, - ConfigurableSpanExporterProvider::createExporter, - config, - serviceClassLoader); + spanExporterSpiManager(config, serviceClassLoader); return exporterNames.stream() .collect( @@ -86,6 +80,17 @@ static Map configureSpanExporters( config))); } + // Visible for testing + static NamedSpiManager spanExporterSpiManager( + ConfigProperties config, ClassLoader serviceClassLoader) { + return SpiUtil.loadConfigurable( + ConfigurableSpanExporterProvider.class, + ConfigurableSpanExporterProvider::getName, + ConfigurableSpanExporterProvider::createExporter, + config, + serviceClassLoader); + } + // Visible for testing static SpanExporter configureExporter( String name, @@ -97,8 +102,6 @@ static SpanExporter configureExporter( return configureOtlp(config, meterProvider); case "jaeger": return configureJaeger(config, meterProvider); - case "zipkin": - return configureZipkin(config); case "logging-otlp": ClasspathUtil.checkClassExists( "io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter", @@ -196,25 +199,5 @@ private static SpanExporter configureJaeger( return builder.build(); } - private static SpanExporter configureZipkin(ConfigProperties config) { - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.zipkin.ZipkinSpanExporter", - "Zipkin Exporter", - "opentelemetry-exporter-zipkin"); - 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(); - } - private SpanExporterConfiguration() {} } diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java index 06d971c8fc6..2abb4617b7e 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java @@ -66,7 +66,8 @@ void zipkin() { "zipkin", EMPTY, NamedSpiManager.createEmpty(), MeterProvider.noop())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Zipkin Exporter enabled but opentelemetry-exporter-zipkin not found on classpath"); + "otel.traces.exporter set to \"zipkin\" but opentelemetry-exporter-zipkin not found on classpath." + + " Make sure to add it as a dependency."); } @Test 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 8622f8f6a10..5bc04ef890f 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,6 +12,7 @@ import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.util.Collections; @@ -76,12 +77,15 @@ void configureJaegerTimeout() { // Timeout difficult to test using real exports so just check that things don't blow up. @Test void configureZipkinTimeout() { + ConfigProperties config = + DefaultConfigProperties.createForTest( + Collections.singletonMap("otel.exporter.zipkin.timeout", "5s")); SpanExporter exporter = SpanExporterConfiguration.configureExporter( "zipkin", - DefaultConfigProperties.createForTest( - Collections.singletonMap("otel.exporter.zipkin.timeout", "5s")), - NamedSpiManager.createEmpty(), + config, + SpanExporterConfiguration.spanExporterSpiManager( + config, SpanExporterConfigurationTest.class.getClassLoader()), MeterProvider.noop()); try { assertThat(exporter).isNotNull();