Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SpanExporterFactory support for zipkin exporter #5771

Merged
merged 2 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Comparing source compatibility of against
No changes.
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.zipkin.ZipkinSpanExporter (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,20 @@ public final class ZipkinSpanExporter implements SpanExporter {

private final ThrottlingLogger logger = new ThrottlingLogger(baseLogger);
private final AtomicBoolean isShutdown = new AtomicBoolean();
private final ZipkinSpanExporterBuilder builder;
private final BytesEncoder<Span> encoder;
private final Sender sender;
private final ExporterMetrics exporterMetrics;

private final OtelToZipkinSpanTransformer transformer;

ZipkinSpanExporter(
ZipkinSpanExporterBuilder builder,
BytesEncoder<Span> encoder,
Sender sender,
Supplier<MeterProvider> meterProviderSupplier,
OtelToZipkinSpanTransformer transformer) {
this.builder = builder;
this.encoder = encoder;
this.sender = sender;
this.exporterMetrics =
Expand Down Expand Up @@ -114,6 +117,11 @@ public CompletableResultCode shutdown() {
return CompletableResultCode.ofSuccess();
}

@Override
public String toString() {
return "ZipkinSpanExporter{" + builder.toString(false) + "}";
}

/**
* Returns a new Builder for {@link ZipkinSpanExporter}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.opentelemetry.api.metrics.MeterProvider;
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;
Expand Down Expand Up @@ -68,13 +69,14 @@
* implementation uses a Supplier that returns a single unchanging IP address that is captured at
* creation time.
*
* @param supplier - A supplier that returns an InetAddress that may be null.
* @param localIpAddressSupplier - A supplier that returns an InetAddress that may be null.
* @return this
* @since 1.18.0
*/
public ZipkinSpanExporterBuilder setLocalIpAddressSupplier(Supplier<InetAddress> supplier) {
requireNonNull(supplier, "encoder");
this.localIpAddressSupplier = supplier;
public ZipkinSpanExporterBuilder setLocalIpAddressSupplier(
Supplier<InetAddress> localIpAddressSupplier) {
requireNonNull(localIpAddressSupplier, "localIpAddressSupplier");
this.localIpAddressSupplier = localIpAddressSupplier;
return this;
}

Expand Down Expand Up @@ -151,6 +153,21 @@
return this;
}

String toString(boolean includePrefixAndSuffix) {
StringJoiner joiner =
includePrefixAndSuffix
? new StringJoiner(", ", "ZipkinSpanExporterBuilder{", "}")

Check warning on line 159 in exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java

View check run for this annotation

Codecov / codecov/patch

exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterBuilder.java#L159

Added line #L159 was not covered by tests
: new StringJoiner(", ");
joiner.add("endpoint=" + endpoint);
joiner.add("compressionEnabled=" + compressionEnabled);
joiner.add("readTimeoutMillis=" + readTimeoutMillis);
// 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}.
*
Expand All @@ -168,6 +185,6 @@
}
OtelToZipkinSpanTransformer transformer =
OtelToZipkinSpanTransformer.create(localIpAddressSupplier);
return new ZipkinSpanExporter(encoder, sender, meterProviderSupplier, transformer);
return new ZipkinSpanExporter(this, encoder, sender, meterProviderSupplier, transformer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -51,7 +52,12 @@ void testExport() {
TestSpanData testSpanData = spanBuilder().build();

ZipkinSpanExporter zipkinSpanExporter =
new ZipkinSpanExporter(mockEncoder, mockSender, MeterProvider::noop, mockTransformer);
new ZipkinSpanExporter(
new ZipkinSpanExporterBuilder(),
mockEncoder,
mockSender,
MeterProvider::noop,
mockTransformer);

byte[] someBytes = new byte[0];
Span zipkinSpan =
Expand Down Expand Up @@ -82,7 +88,12 @@ void testExport_failed() {
TestSpanData testSpanData = spanBuilder().build();

ZipkinSpanExporter zipkinSpanExporter =
new ZipkinSpanExporter(mockEncoder, mockSender, MeterProvider::noop, mockTransformer);
new ZipkinSpanExporter(
new ZipkinSpanExporterBuilder(),
mockEncoder,
mockSender,
MeterProvider::noop,
mockTransformer);

byte[] someBytes = new byte[0];
Span zipkinSpan =
Expand Down Expand Up @@ -204,4 +215,23 @@ void compressionEnabledAndDisabled() {
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}");
}
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}");
}
}
}
1 change: 1 addition & 0 deletions sdk-extensions/incubator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
testImplementation(project(":sdk:testing"))
testImplementation(project(":sdk-extensions:autoconfigure"))
testImplementation(project(":exporters:otlp:all"))
testImplementation(project(":exporters:zipkin"))
testImplementation(project(":sdk-extensions:jaeger-remote-sampler"))
testImplementation(project(":extensions:trace-propagators"))
// As a part of the tests we check that we can parse examples without error. The https://github.com/open-telemetry/opentelemetry-configuration/blob/main/examples/kitchen-sink.yam contains a reference to the xray propagator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Zipkin;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.io.Closeable;
import java.util.HashMap;
Expand Down Expand Up @@ -44,9 +45,8 @@ public SpanExporter create(
return SpanExporter.composite();
}

if (model.getOtlp() != null) {
Otlp otlp = model.getOtlp();

Otlp otlp = model.getOtlp();
if (otlp != null) {
// Translate from file configuration scheme to environment variable scheme. This is ultimately
// interpreted by Otlp*ExporterProviders, but we want to avoid the dependency on
// opentelemetry-exporter-otlp
Expand Down Expand Up @@ -93,6 +93,29 @@ public SpanExporter create(
"otlp exporter"));
}

Zipkin zipkin = model.getZipkin();
if (zipkin != null) {
jack-berg marked this conversation as resolved.
Show resolved Hide resolved
// Translate from file configuration scheme to environment variable scheme. This is ultimately
// interpreted by ZipkinSpanExporterProvider, but we want to avoid the dependency on
// opentelemetry-exporter-zipkin
Map<String, String> properties = new HashMap<>();
if (zipkin.getEndpoint() != null) {
properties.put("otel.exporter.zipkin.endpoint", zipkin.getEndpoint());
}
if (zipkin.getTimeout() != null) {
properties.put("otel.exporter.zipkin.timeout", Integer.toString(zipkin.getTimeout()));
}

// TODO(jack-berg): add method for creating from map
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);

return FileConfigUtil.addAndReturn(
closeables,
FileConfigUtil.assertNotNull(
spanExporterSpiManager(configProperties, spiHelper).getByName("zipkin"),
"zipkin exporter"));
}

// TODO(jack-berg): add support for generic SPI exporters
if (!model.getAdditionalProperties().isEmpty()) {
throw new ConfigurationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
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.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Headers;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Zipkin;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.io.Closeable;
import java.io.IOException;
Expand Down Expand Up @@ -163,6 +165,73 @@ void create_OtlpConfigured(@TempDir Path tempDir)
.isEqualTo(clientCertificatePath);
}

@Test
void create_ZipkinDefaults() {
spiHelper = spy(spiHelper);
List<Closeable> closeables = new ArrayList<>();
ZipkinSpanExporter expectedExporter = ZipkinSpanExporter.builder().build();
cleanup.addCloseable(expectedExporter);

SpanExporter exporter =
SpanExporterFactory.getInstance()
.create(
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
.SpanExporter()
.withZipkin(new Zipkin()),
spiHelper,
closeables);
cleanup.addCloseable(exporter);
cleanup.addCloseables(closeables);

assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());

ArgumentCaptor<ConfigProperties> configCaptor = ArgumentCaptor.forClass(ConfigProperties.class);
verify(spiHelper)
.loadConfigurable(
eq(ConfigurableSpanExporterProvider.class), any(), any(), configCaptor.capture());
ConfigProperties configProperties = configCaptor.getValue();
assertThat(configProperties.getString("otel.exporter.zipkin.endpoint")).isNull();
assertThat(configProperties.getDuration("otel.exporter.zipkin.timeout")).isNull();
}

@Test
void create_ZipkinConfigured() {
spiHelper = spy(spiHelper);
List<Closeable> closeables = new ArrayList<>();
ZipkinSpanExporter expectedExporter =
ZipkinSpanExporter.builder()
.setEndpoint("http://zipkin:9411/v1/v2/spans")
.setReadTimeout(Duration.ofSeconds(15))
.build();
cleanup.addCloseable(expectedExporter);

SpanExporter exporter =
SpanExporterFactory.getInstance()
.create(
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
.SpanExporter()
.withZipkin(
new Zipkin()
.withEndpoint("http://zipkin:9411/v1/v2/spans")
.withTimeout(15_000)),
spiHelper,
closeables);
cleanup.addCloseable(exporter);
cleanup.addCloseables(closeables);

assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());

ArgumentCaptor<ConfigProperties> configCaptor = ArgumentCaptor.forClass(ConfigProperties.class);
verify(spiHelper)
.loadConfigurable(
eq(ConfigurableSpanExporterProvider.class), any(), any(), configCaptor.capture());
ConfigProperties configProperties = configCaptor.getValue();
assertThat(configProperties.getString("otel.exporter.zipkin.endpoint"))
.isEqualTo("http://zipkin:9411/v1/v2/spans");
assertThat(configProperties.getDuration("otel.exporter.zipkin.timeout"))
.isEqualTo(Duration.ofSeconds(15));
}

@Test
void create_SpiExporter() {
List<Closeable> closeables = new ArrayList<>();
Expand Down