diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index eb8501ba9a9..d4c4ca11de3 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -16,8 +16,8 @@ val DEPENDENCY_BOMS = listOf( "com.squareup.okio:okio-bom:3.7.0", // applies to transitive dependencies of okhttp "io.grpc:grpc-bom:1.60.1", "io.netty:netty-bom:4.1.104.Final", + "io.zipkin.reporter2:zipkin-reporter-bom:3.1.1", "io.zipkin.brave:brave-bom:5.17.0", - "io.zipkin.reporter2:zipkin-reporter-bom:2.17.1", "org.assertj:assertj-bom:3.25.1", "org.junit:junit-bom:5.10.1", "org.testcontainers:testcontainers-bom:1.19.3", diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt index df26146497b..73d401a04b9 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt @@ -1,2 +1,6 @@ Comparing source compatibility of against -No changes. \ No newline at end of file +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.zipkin.ZipkinSpanExporterBuilder (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + === UNCHANGED METHOD: PUBLIC io.opentelemetry.exporter.zipkin.ZipkinSpanExporterBuilder setEncoder(zipkin2.codec.BytesEncoder) + +++ NEW ANNOTATION: java.lang.Deprecated + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.zipkin.ZipkinSpanExporterBuilder setEncoder(zipkin2.reporter.BytesEncoder) diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java new file mode 100644 index 00000000000..8605eacd936 --- /dev/null +++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapter.java @@ -0,0 +1,58 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.zipkin; + +import zipkin2.Span; +import zipkin2.reporter.BytesEncoder; +import zipkin2.reporter.Encoding; + +/** + * This supports the deprecated method {@link + * ZipkinSpanExporterBuilder#setEncoder(zipkin2.codec.BytesEncoder)}. + */ +final class BytesEncoderAdapter implements BytesEncoder { + private final zipkin2.codec.BytesEncoder delegate; + private final Encoding encoding; + + @SuppressWarnings("deprecation") // we have to use the deprecated thrift encoding to return it + BytesEncoderAdapter(zipkin2.codec.BytesEncoder delegate) { + this.delegate = delegate; + switch (delegate.encoding()) { + case JSON: + this.encoding = Encoding.JSON; + break; + case PROTO3: + this.encoding = Encoding.PROTO3; + break; + case THRIFT: + this.encoding = Encoding.THRIFT; + break; + default: + // Only possible if zipkin2 adds an encoding besides above, which is very unlikely. + throw new UnsupportedOperationException("unsupported encoding " + delegate.encoding()); + } + } + + @Override + public Encoding encoding() { + return encoding; + } + + @Override + public int sizeInBytes(Span span) { + return delegate.sizeInBytes(span); + } + + @Override + public byte[] encode(Span span) { + return delegate.encode(span); + } + + @Override + public String toString() { + return delegate.toString(); + } +} diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java index 37d8c1fd022..840e53b58de 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 @@ -19,10 +19,10 @@ import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; -import zipkin2.Callback; import zipkin2.Span; -import zipkin2.codec.BytesEncoder; -import zipkin2.codec.Encoding; +import zipkin2.reporter.BytesEncoder; +import zipkin2.reporter.Callback; +import zipkin2.reporter.Encoding; import zipkin2.reporter.Sender; /** 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 2691c700954..ad19cbc8d33 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 @@ -17,9 +17,9 @@ import java.util.function.Supplier; import javax.annotation.Nullable; import zipkin2.Span; -import zipkin2.codec.BytesEncoder; -import zipkin2.codec.SpanBytesEncoder; +import zipkin2.reporter.BytesEncoder; import zipkin2.reporter.Sender; +import zipkin2.reporter.SpanBytesEncoder; import zipkin2.reporter.okhttp3.OkHttpSender; /** Builder class for {@link ZipkinSpanExporter}. */ @@ -49,6 +49,21 @@ public ZipkinSpanExporterBuilder setSender(Sender sender) { return this; } + /** + * Sets the {@link zipkin2.codec.BytesEncoder}, which controls the format used by the {@link + * Sender}. Defaults to the {@link zipkin2.codec.SpanBytesEncoder#JSON_V2}. + * + * @param encoder the {@code BytesEncoder} to use. + * @return this. + * @see zipkin2.codec.SpanBytesEncoder + * @deprecated Use {@link #setEncoder(BytesEncoder)} instead. + */ + @Deprecated + public ZipkinSpanExporterBuilder setEncoder(zipkin2.codec.BytesEncoder encoder) { + requireNonNull(encoder, "encoder"); + return setEncoder(new BytesEncoderAdapter(encoder)); + } + /** * Sets the {@link BytesEncoder}, which controls the format used by the {@link Sender}. Defaults * to the {@link SpanBytesEncoder#JSON_V2}. diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java new file mode 100644 index 00000000000..24b16eb3a06 --- /dev/null +++ b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/BytesEncoderAdapterTest.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.zipkin; + +import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.PARENT_SPAN_ID; +import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.SPAN_ID; +import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.TRACE_ID; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import zipkin2.Endpoint; +import zipkin2.Span; +import zipkin2.reporter.Encoding; +import zipkin2.reporter.SpanBytesEncoder; + +class BytesEncoderAdapterTest { + + /** Contains {@link Span#localEndpoint()} to ensure would be encoded differently. */ + private final Span testSpan = + Span.newBuilder() + .traceId(TRACE_ID) + .parentId(PARENT_SPAN_ID) + .id(SPAN_ID) + .localEndpoint(Endpoint.newBuilder().serviceName("test").build()) + .build(); + + @Test + void testJsonV2() { + BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.JSON_V2); + assertThat(adapter.encoding()).isEqualTo(Encoding.JSON); + assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.JSON_V2.encode(testSpan)); + assertThat(adapter.sizeInBytes(testSpan)) + .isEqualTo(SpanBytesEncoder.JSON_V2.sizeInBytes(testSpan)); + assertThat(adapter).hasToString(SpanBytesEncoder.JSON_V2.toString()); + } + + @Test + void testProtobuf() { + BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.PROTO3); + assertThat(adapter.encoding()).isEqualTo(Encoding.PROTO3); + assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.PROTO3.encode(testSpan)); + assertThat(adapter.sizeInBytes(testSpan)) + .isEqualTo(SpanBytesEncoder.PROTO3.sizeInBytes(testSpan)); + assertThat(adapter).hasToString(SpanBytesEncoder.PROTO3.toString()); + } + + @Test + @SuppressWarnings("deprecation") // we have to use the deprecated thrift encoding to test it + void testThrift() { + BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.THRIFT); + assertThat(adapter.encoding()).isEqualTo(Encoding.THRIFT); + assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.THRIFT.encode(testSpan)); + assertThat(adapter.sizeInBytes(testSpan)) + .isEqualTo(SpanBytesEncoder.THRIFT.sizeInBytes(testSpan)); + assertThat(adapter).hasToString(SpanBytesEncoder.THRIFT.toString()); + } + + @Test + void testJsonV1() { + BytesEncoderAdapter adapter = new BytesEncoderAdapter(zipkin2.codec.SpanBytesEncoder.JSON_V1); + assertThat(adapter.encoding()).isEqualTo(Encoding.JSON); + assertThat(adapter.encode(testSpan)).isEqualTo(SpanBytesEncoder.JSON_V1.encode(testSpan)); + assertThat(adapter.sizeInBytes(testSpan)) + .isEqualTo(SpanBytesEncoder.JSON_V1.sizeInBytes(testSpan)); + assertThat(adapter).hasToString(SpanBytesEncoder.JSON_V1.toString()); + } +} diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java index c7d23af452f..c55d2c01c67 100644 --- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java +++ b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterEndToEndHttpTest.java @@ -44,9 +44,9 @@ import org.testcontainers.junit.jupiter.Testcontainers; import zipkin2.Endpoint; import zipkin2.Span; -import zipkin2.codec.Encoding; import zipkin2.codec.SpanBytesDecoder; -import zipkin2.codec.SpanBytesEncoder; +import zipkin2.reporter.Encoding; +import zipkin2.reporter.SpanBytesEncoder; import zipkin2.reporter.okhttp3.OkHttpSender; @Testcontainers(disabledWithoutDocker = true) @@ -82,7 +82,7 @@ class ZipkinSpanExporterEndToEndHttpTest { @Container public static final GenericContainer zipkinContainer = - new GenericContainer<>("ghcr.io/openzipkin/zipkin:2.23") + new GenericContainer<>("ghcr.io/openzipkin/zipkin:2.27") .withExposedPorts(ZIPKIN_API_PORT) .waitingFor(Wait.forHttp("/health").forPort(ZIPKIN_API_PORT)); 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 263edadad53..38e4534c71a 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 @@ -29,11 +29,13 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import zipkin2.Call; -import zipkin2.Callback; import zipkin2.Span; -import zipkin2.codec.SpanBytesEncoder; +import zipkin2.reporter.BytesEncoder; +import zipkin2.reporter.Call; +import zipkin2.reporter.Callback; +import zipkin2.reporter.Encoding; import zipkin2.reporter.Sender; +import zipkin2.reporter.SpanBytesEncoder; @ExtendWith(MockitoExtension.class) class ZipkinSpanExporterTest { @@ -144,7 +146,8 @@ void testShutdown() throws IOException { } @Test - @SuppressWarnings("PreferJavaTimeOverload") + @SuppressWarnings({"PreferJavaTimeOverload", "deprecation"}) + // we have to use the deprecated setEncoder overload to test it void invalidConfig() { assertThatThrownBy(() -> ZipkinSpanExporter.builder().setReadTimeout(-1, TimeUnit.MILLISECONDS)) .isInstanceOf(IllegalArgumentException.class) @@ -170,9 +173,33 @@ void invalidConfig() { .isInstanceOf(NullPointerException.class) .hasMessage("sender"); - assertThatThrownBy(() -> ZipkinSpanExporter.builder().setEncoder(null)) + assertThatThrownBy( + () -> ZipkinSpanExporter.builder().setEncoder((zipkin2.codec.BytesEncoder) null)) .isInstanceOf(NullPointerException.class) .hasMessage("encoder"); + + assertThatThrownBy(() -> ZipkinSpanExporter.builder().setEncoder((BytesEncoder) null)) + .isInstanceOf(NullPointerException.class) + .hasMessage("encoder"); + } + + @Test + void encoderProtobuf() { + @SuppressWarnings("deprecation") // we have to use the deprecated setEncoderto test it + ZipkinSpanExporter exporter = + ZipkinSpanExporter.builder().setEncoder(zipkin2.codec.SpanBytesEncoder.PROTO3).build(); + try { + assertThat(exporter).extracting("encoder.encoding").isEqualTo(Encoding.PROTO3); + } finally { + exporter.shutdown(); + } + + exporter = ZipkinSpanExporter.builder().setEncoder(SpanBytesEncoder.PROTO3).build(); + try { + assertThat(exporter).extracting("encoder").isEqualTo(SpanBytesEncoder.PROTO3); + } finally { + exporter.shutdown(); + } } @Test