From 81b4084bfba4a9da156eb178eb254ee16b9b3427 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 10 Feb 2024 17:43:23 +0700 Subject: [PATCH] Migrates to Brave 6 and Zipkin Reporter 3 Signed-off-by: Adrian Cole --- .../BravePropagationConfigurations.java | 4 +- .../tracing/CompositePropagationFactory.java | 6 +- .../tracing/zipkin/HttpSender.java | 127 ++++++------------ .../zipkin/ZipkinAutoConfiguration.java | 17 +-- .../tracing/zipkin/ZipkinConfigurations.java | 50 +++---- .../zipkin/ZipkinRestTemplateSender.java | 46 +------ .../tracing/zipkin/ZipkinWebClientSender.java | 62 ++------- .../CompositePropagationFactoryTests.java | 6 +- .../tracing/LocalBaggageFieldsTests.java | 4 +- .../tracing/zipkin/NoopSender.java | 35 ++--- ...ConfigurationsBraveConfigurationTests.java | 50 +++---- .../spring-boot-dependencies/build.gradle | 11 +- .../testcontainers/DockerImageNames.java | 2 +- 13 files changed, 126 insertions(+), 294 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BravePropagationConfigurations.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BravePropagationConfigurations.java index 31de139c7df3..974c93a86f37 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BravePropagationConfigurations.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BravePropagationConfigurations.java @@ -30,7 +30,6 @@ import brave.propagation.CurrentTraceContext.ScopeDecorator; import brave.propagation.Propagation; import brave.propagation.Propagation.Factory; -import brave.propagation.Propagation.KeyFactory; import io.micrometer.tracing.brave.bridge.BraveBaggageManager; import org.springframework.beans.factory.ObjectProvider; @@ -99,12 +98,11 @@ BaggagePropagation.FactoryBuilder propagationFactoryBuilder( return builder; } - @SuppressWarnings("deprecation") private Factory createThrowAwayFactory() { return new Factory() { @Override - public Propagation create(KeyFactory keyFactory) { + public Propagation get() { return null; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactory.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactory.java index 14ec2aea1e66..baaf9bc0a901 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactory.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactory.java @@ -22,7 +22,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import brave.internal.propagation.StringPropagationAdapter; import brave.propagation.B3Propagation; import brave.propagation.Propagation; import brave.propagation.Propagation.Factory; @@ -71,9 +70,8 @@ public boolean requires128BitTraceId() { } @Override - @SuppressWarnings("deprecation") - public Propagation create(Propagation.KeyFactory keyFactory) { - return StringPropagationAdapter.create(this.propagation, keyFactory); + public Propagation get() { + return this.propagation; } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/HttpSender.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/HttpSender.java index ac7ba066671e..fc9825f31817 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/HttpSender.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/HttpSender.java @@ -18,37 +18,37 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.Collections; import java.util.List; import java.util.zip.GZIPOutputStream; -import zipkin2.Call; -import zipkin2.CheckResult; -import zipkin2.codec.Encoding; import zipkin2.reporter.BytesMessageEncoder; import zipkin2.reporter.ClosedSenderException; -import zipkin2.reporter.Sender; +import zipkin2.reporter.BytesMessageSender; +import zipkin2.reporter.Encoding; import org.springframework.http.HttpHeaders; import org.springframework.util.unit.DataSize; /** - * A Zipkin {@link Sender} that uses an HTTP client to send JSON spans. Supports automatic + * A Zipkin {@link BytesMessageSender} that uses an HTTP client to send JSON spans. Supports automatic * compression with gzip. * * @author Moritz Halbritter * @author Stefan Bratanov */ -abstract class HttpSender extends Sender { +abstract class HttpSender extends BytesMessageSender.Base { private static final DataSize MESSAGE_MAX_SIZE = DataSize.ofKilobytes(512); + /** + * Only use gzip compression on data which is bigger than this in bytes. + */ + private static final DataSize COMPRESSION_THRESHOLD = DataSize.ofKilobytes(1); + private volatile boolean closed; - @Override - public Encoding encoding() { - return Encoding.JSON; + HttpSender() { + super(Encoding.JSON); } @Override @@ -57,96 +57,49 @@ public int messageMaxBytes() { } @Override - public int messageSizeInBytes(List encodedSpans) { - return encoding().listSizeInBytes(encodedSpans); - } - - @Override - public int messageSizeInBytes(int encodedSizeInBytes) { - return encoding().listSizeInBytes(encodedSizeInBytes); - } - - @Override - public CheckResult check() { - try { - sendSpans(Collections.emptyList()).execute(); - return CheckResult.OK; - } - catch (IOException | RuntimeException ex) { - return CheckResult.failed(ex); - } - } - - @Override - public void close() throws IOException { + public void close() { this.closed = true; } /** - * The returned {@link HttpPostCall} will send span(s) as a POST to a zipkin endpoint - * when executed. - * @param batchedEncodedSpans list of encoded spans as a byte array - * @return an instance of a Zipkin {@link Call} which can be executed + * This will send span(s) as a POST to a zipkin endpoint. For example, + * http://localhost:9411/api/v2/spans. + * + * @param headers headers for the POST request + * @param body list of possibly gzipped, encoded spans. */ - protected abstract HttpPostCall sendSpans(byte[] batchedEncodedSpans); + abstract void postSpans(HttpHeaders headers, byte[] body); @Override - public Call sendSpans(List encodedSpans) { + public void send(List encodedSpans) throws IOException { if (this.closed) { throw new ClosedSenderException(); } - return sendSpans(BytesMessageEncoder.JSON.encode(encodedSpans)); - } - - abstract static class HttpPostCall extends Call.Base { - - /** - * Only use gzip compression on data which is bigger than this in bytes. - */ - private static final DataSize COMPRESSION_THRESHOLD = DataSize.ofKilobytes(1); - - private final byte[] body; - - HttpPostCall(byte[] body) { - this.body = body; - } - - protected byte[] getBody() { - if (needsCompression()) { - return compress(this.body); - } - return this.body; - } - - protected byte[] getUncompressedBody() { - return this.body; + byte[] body = BytesMessageEncoder.JSON.encode(encodedSpans); + HttpHeaders headers = getDefaultHeaders(); + if (needsCompression(body)) { + body = compress(body); + headers.set("Content-Encoding", "gzip"); } + postSpans(headers, body); + } - protected HttpHeaders getDefaultHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.set("b3", "0"); - headers.set("Content-Type", "application/json"); - if (needsCompression()) { - headers.set("Content-Encoding", "gzip"); - } - return headers; - } + HttpHeaders getDefaultHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.set("b3", "0"); + headers.set("Content-Type", "application/json"); + return headers; + } - private boolean needsCompression() { - return this.body.length > COMPRESSION_THRESHOLD.toBytes(); - } + private boolean needsCompression(byte[] body) { + return body.length > COMPRESSION_THRESHOLD.toBytes(); + } - private byte[] compress(byte[] input) { - ByteArrayOutputStream result = new ByteArrayOutputStream(); - try (GZIPOutputStream gzip = new GZIPOutputStream(result)) { - gzip.write(input); - } - catch (IOException ex) { - throw new UncheckedIOException(ex); - } - return result.toByteArray(); + private byte[] compress(byte[] input) throws IOException { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + try (GZIPOutputStream gzip = new GZIPOutputStream(result)) { + gzip.write(input); } - + return result.toByteArray(); } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfiguration.java index daff635f8631..9c48af3ca21f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfiguration.java @@ -16,14 +16,10 @@ package org.springframework.boot.actuate.autoconfigure.tracing.zipkin; -import zipkin2.Span; -import zipkin2.codec.BytesEncoder; -import zipkin2.codec.SpanBytesEncoder; -import zipkin2.reporter.Sender; +import zipkin2.reporter.BytesMessageSender; import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration; import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.OpenTelemetryConfiguration; -import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.ReporterConfiguration; import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.SenderConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -44,9 +40,8 @@ * @since 3.0.0 */ @AutoConfiguration(after = RestTemplateAutoConfiguration.class) -@ConditionalOnClass(Sender.class) -@Import({ SenderConfiguration.class, ReporterConfiguration.class, BraveConfiguration.class, - OpenTelemetryConfiguration.class }) +@ConditionalOnClass(BytesMessageSender.class) +@Import({ SenderConfiguration.class, BraveConfiguration.class, OpenTelemetryConfiguration.class }) @EnableConfigurationProperties(ZipkinProperties.class) public class ZipkinAutoConfiguration { @@ -56,10 +51,4 @@ PropertiesZipkinConnectionDetails zipkinConnectionDetails(ZipkinProperties prope return new PropertiesZipkinConnectionDetails(properties); } - @Bean - @ConditionalOnMissingBean - public BytesEncoder spanBytesEncoder() { - return SpanBytesEncoder.JSON_V2; - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java index f4ecc9503125..e55792cc12ed 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java @@ -16,13 +16,16 @@ package org.springframework.boot.actuate.autoconfigure.tracing.zipkin; +import java.util.Optional; + +import brave.handler.MutableSpan; import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; +import io.opentelemetry.exporter.zipkin.ZipkinSpanExporterBuilder; import zipkin2.Span; -import zipkin2.codec.BytesEncoder; -import zipkin2.reporter.AsyncReporter; -import zipkin2.reporter.Reporter; -import zipkin2.reporter.Sender; -import zipkin2.reporter.brave.ZipkinSpanHandler; +import zipkin2.reporter.BytesEncoder; +import zipkin2.reporter.BytesMessageSender; +import zipkin2.reporter.brave.AsyncZipkinSpanHandler; +import zipkin2.reporter.brave.AsyncZipkinSpanHandler.Builder; import zipkin2.reporter.urlconnection.URLConnectionSender; import org.springframework.beans.factory.ObjectProvider; @@ -59,7 +62,7 @@ static class SenderConfiguration { static class UrlConnectionSenderConfiguration { @Bean - @ConditionalOnMissingBean(Sender.class) + @ConditionalOnMissingBean(BytesMessageSender.class) URLConnectionSender urlConnectionSender(ZipkinProperties properties, ObjectProvider connectionDetailsProvider) { ZipkinConnectionDetails connectionDetails = connectionDetailsProvider @@ -79,7 +82,7 @@ URLConnectionSender urlConnectionSender(ZipkinProperties properties, static class RestTemplateSenderConfiguration { @Bean - @ConditionalOnMissingBean(Sender.class) + @ConditionalOnMissingBean(BytesMessageSender.class) ZipkinRestTemplateSender restTemplateSender(ZipkinProperties properties, ObjectProvider customizers, ObjectProvider connectionDetailsProvider) { @@ -111,7 +114,7 @@ private RestTemplateBuilder applyCustomizers(RestTemplateBuilder restTemplateBui static class WebClientSenderConfiguration { @Bean - @ConditionalOnMissingBean(Sender.class) + @ConditionalOnMissingBean(BytesMessageSender.class) ZipkinWebClientSender webClientSender(ZipkinProperties properties, ObjectProvider customizers, ObjectProvider connectionDetailsProvider) { @@ -126,29 +129,16 @@ ZipkinWebClientSender webClientSender(ZipkinProperties properties, } @Configuration(proxyBeanMethods = false) - static class ReporterConfiguration { - - @Bean - @ConditionalOnMissingBean(Reporter.class) - @ConditionalOnBean(Sender.class) - AsyncReporter spanReporter(Sender sender, BytesEncoder encoder) { - return AsyncReporter.builder(sender).build(encoder); - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(ZipkinSpanHandler.class) + @ConditionalOnClass(AsyncZipkinSpanHandler.class) static class BraveConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnBean(Reporter.class) - @ConditionalOnEnabledTracing - ZipkinSpanHandler zipkinSpanHandler(Reporter spanReporter) { - return (ZipkinSpanHandler) ZipkinSpanHandler.newBuilder(spanReporter).build(); + @ConditionalOnBean(BytesMessageSender.class) + AsyncZipkinSpanHandler spanReporter(BytesMessageSender sender, Optional> encoder) { + Builder builder = AsyncZipkinSpanHandler.newBuilder(sender); + return encoder.map(builder::build).orElseGet(builder::build); } - } @Configuration(proxyBeanMethods = false) @@ -157,10 +147,12 @@ static class OpenTelemetryConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnBean(Sender.class) + @ConditionalOnBean(BytesMessageSender.class) @ConditionalOnEnabledTracing - ZipkinSpanExporter zipkinSpanExporter(BytesEncoder encoder, Sender sender) { - return ZipkinSpanExporter.builder().setEncoder(encoder).setSender(sender).build(); + ZipkinSpanExporter zipkinSpanExporter(BytesMessageSender sender, Optional> encoder) { + ZipkinSpanExporterBuilder builder = ZipkinSpanExporter.builder().setSender(sender); + encoder.ifPresent(builder::setEncoder); + return builder.build(); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinRestTemplateSender.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinRestTemplateSender.java index d29e9eee60ff..846853985048 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinRestTemplateSender.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinRestTemplateSender.java @@ -16,10 +16,8 @@ package org.springframework.boot.actuate.autoconfigure.tracing.zipkin; -import zipkin2.Call; -import zipkin2.Callback; - import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.web.client.RestTemplate; @@ -41,45 +39,9 @@ class ZipkinRestTemplateSender extends HttpSender { } @Override - public HttpPostCall sendSpans(byte[] batchedEncodedSpans) { - return new RestTemplateHttpPostCall(this.endpoint, batchedEncodedSpans, this.restTemplate); - } - - private static class RestTemplateHttpPostCall extends HttpPostCall { - - private final String endpoint; - - private final RestTemplate restTemplate; - - RestTemplateHttpPostCall(String endpoint, byte[] body, RestTemplate restTemplate) { - super(body); - this.endpoint = endpoint; - this.restTemplate = restTemplate; - } - - @Override - public Call clone() { - return new RestTemplateHttpPostCall(this.endpoint, getUncompressedBody(), this.restTemplate); - } - - @Override - protected Void doExecute() { - HttpEntity request = new HttpEntity<>(getBody(), getDefaultHeaders()); - this.restTemplate.exchange(this.endpoint, HttpMethod.POST, request, Void.class); - return null; - } - - @Override - protected void doEnqueue(Callback callback) { - try { - doExecute(); - callback.onSuccess(null); - } - catch (Exception ex) { - callback.onError(ex); - } - } - + void postSpans(HttpHeaders headers, byte[] body) { + HttpEntity request = new HttpEntity<>(body, headers); + this.restTemplate.exchange(this.endpoint, HttpMethod.POST, request, Void.class); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java index 2ef8cb74c09a..aa35bacd22de 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java @@ -18,12 +18,7 @@ import java.time.Duration; -import reactor.core.publisher.Mono; -import zipkin2.Call; -import zipkin2.Callback; - import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; /** @@ -47,55 +42,14 @@ class ZipkinWebClientSender extends HttpSender { } @Override - public HttpPostCall sendSpans(byte[] batchedEncodedSpans) { - return new WebClientHttpPostCall(this.endpoint, batchedEncodedSpans, this.webClient, this.timeout); - } - - private static class WebClientHttpPostCall extends HttpPostCall { - - private final String endpoint; - - private final WebClient webClient; - - private final Duration timeout; - - WebClientHttpPostCall(String endpoint, byte[] body, WebClient webClient, Duration timeout) { - super(body); - this.endpoint = endpoint; - this.webClient = webClient; - this.timeout = timeout; - } - - @Override - public Call clone() { - return new WebClientHttpPostCall(this.endpoint, getUncompressedBody(), this.webClient, this.timeout); - } - - @Override - protected Void doExecute() { - sendRequest().block(); - return null; - } - - @Override - protected void doEnqueue(Callback callback) { - sendRequest().subscribe((entity) -> callback.onSuccess(null), callback::onError); - } - - private Mono> sendRequest() { - return this.webClient.post() - .uri(this.endpoint) - .headers(this::addDefaultHeaders) - .bodyValue(getBody()) - .retrieve() - .toBodilessEntity() - .timeout(this.timeout); - } - - private void addDefaultHeaders(HttpHeaders headers) { - headers.addAll(getDefaultHeaders()); - } - + void postSpans(HttpHeaders headers, byte[] body) { + this.webClient.post() + .uri(this.endpoint) + .headers(h -> h.addAll(headers)) + .bodyValue(body) + .retrieve() + .toBodilessEntity() + .timeout(this.timeout).block(); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactoryTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactoryTests.java index 5c756514684c..954faa0d2fe2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactoryTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactoryTests.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.Map; -import brave.internal.propagation.StringPropagationAdapter; import brave.propagation.Propagation; import brave.propagation.TraceContext; import brave.propagation.TraceContextOrSamplingFlags; @@ -143,9 +142,8 @@ private DummyPropagation(String field) { } @Override - @SuppressWarnings("deprecation") - public Propagation create(Propagation.KeyFactory keyFactory) { - return StringPropagationAdapter.create(this, keyFactory); + public Propagation get() { + return this; } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/LocalBaggageFieldsTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/LocalBaggageFieldsTests.java index 6f6e99d87d35..15d4508066d5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/LocalBaggageFieldsTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/LocalBaggageFieldsTests.java @@ -22,7 +22,6 @@ import brave.baggage.BaggagePropagationConfig; import brave.propagation.Propagation; import brave.propagation.Propagation.Factory; -import brave.propagation.Propagation.KeyFactory; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -50,11 +49,10 @@ void empty() { assertThat(LocalBaggageFields.empty().asList()).isEmpty(); } - @SuppressWarnings("deprecation") private static FactoryBuilder createBuilder() { return BaggagePropagation.newFactoryBuilder(new Factory() { @Override - public Propagation create(KeyFactory keyFactory) { + public Propagation get() { return null; } }); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/NoopSender.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/NoopSender.java index 48a7926e7818..cf4e05a5c71a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/NoopSender.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/NoopSender.java @@ -16,18 +16,16 @@ package org.springframework.boot.actuate.autoconfigure.tracing.zipkin; +import java.io.IOException; import java.util.List; -import zipkin2.Call; -import zipkin2.Callback; -import zipkin2.codec.Encoding; -import zipkin2.reporter.Sender; +import zipkin2.reporter.Encoding; +import zipkin2.reporter.BytesMessageSender; -class NoopSender extends Sender { +class NoopSender extends BytesMessageSender.Base { - @Override - public Encoding encoding() { - return Encoding.JSON; + NoopSender() { + super(Encoding.JSON); } @Override @@ -36,27 +34,10 @@ public int messageMaxBytes() { } @Override - public int messageSizeInBytes(List encodedSpans) { - return encoding().listSizeInBytes(encodedSpans); + public void send(List encodedSpans) { } @Override - public Call sendSpans(List encodedSpans) { - return new Call.Base<>() { - @Override - public Call clone() { - return this; - } - - @Override - protected Void doExecute() { - return null; - } - - @Override - protected void doEnqueue(Callback callback) { - } - }; + public void close() throws IOException { } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsBraveConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsBraveConfigurationTests.java index 7874d5ec7730..66d7aac51520 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsBraveConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsBraveConfigurationTests.java @@ -18,9 +18,8 @@ import brave.handler.SpanHandler; import org.junit.jupiter.api.Test; -import zipkin2.Span; -import zipkin2.reporter.Reporter; -import zipkin2.reporter.brave.ZipkinSpanHandler; +import zipkin2.reporter.BytesMessageSender; +import zipkin2.reporter.brave.AsyncZipkinSpanHandler; import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -47,54 +46,58 @@ class ZipkinConfigurationsBraveConfigurationTests { @Test void shouldSupplyBeans() { - this.contextRunner.withUserConfiguration(ReporterConfiguration.class) - .run((context) -> assertThat(context).hasSingleBean(ZipkinSpanHandler.class)); + this.contextRunner.withUserConfiguration(BytesMessageSenderConfiguration.class) + .run((context) -> assertThat(context).hasSingleBean(AsyncZipkinSpanHandler.class)); } @Test void shouldNotSupplySpanHandlerIfReporterIsMissing() { - this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanHandler.class)); + this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(AsyncZipkinSpanHandler.class)); } @Test void shouldNotSupplyIfZipkinReporterBraveIsNotOnClasspath() { + // Note: Technically, Brave can work without zipkin-reporter. For example, + // WavefrontSpanHandler doesn't require this to operate. If we remove this + // dependency enforcement when WavefrontSpanHandler is in use, we can resolve + // micrometer-metrics/tracing#509. We also need this for any configuration that + // uses senders defined in the Spring Boot source tree, such as HttpSender. this.contextRunner.withClassLoader(new FilteredClassLoader("zipkin2.reporter.brave")) - .withUserConfiguration(ReporterConfiguration.class) - .run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanHandler.class)); + .withUserConfiguration(BytesMessageSenderConfiguration.class) + .run((context) -> assertThat(context).doesNotHaveBean(AsyncZipkinSpanHandler.class)); } @Test void shouldBackOffOnCustomBeans() { - this.contextRunner.withUserConfiguration(ReporterConfiguration.class, CustomConfiguration.class) + this.contextRunner.withUserConfiguration(BytesMessageSenderConfiguration.class, CustomConfiguration.class) .run((context) -> { - assertThat(context).hasBean("customZipkinSpanHandler"); - assertThat(context).hasSingleBean(ZipkinSpanHandler.class); + assertThat(context).hasBean("customAsyncZipkinSpanHandler"); + assertThat(context).hasSingleBean(AsyncZipkinSpanHandler.class); }); } @Test - void shouldSupplyZipkinSpanHandlerWithCustomSpanHandler() { - this.contextRunner.withUserConfiguration(ReporterConfiguration.class, CustomSpanHandlerConfiguration.class) + void shouldSupplyAsyncZipkinSpanHandlerWithCustomSpanHandler() { + this.contextRunner.withUserConfiguration(BytesMessageSenderConfiguration.class, CustomSpanHandlerConfiguration.class) .run((context) -> { assertThat(context).hasBean("customSpanHandler"); - assertThat(context).hasSingleBean(ZipkinSpanHandler.class); + assertThat(context).hasSingleBean(AsyncZipkinSpanHandler.class); }); } @Test - void shouldNotSupplyZipkinSpanHandlerIfTracingIsDisabled() { - this.tracingDisabledContextRunner.withUserConfiguration(ReporterConfiguration.class) - .run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanHandler.class)); + void shouldNotSupplyAsyncZipkinSpanHandlerIfTracingIsDisabled() { + this.tracingDisabledContextRunner.withUserConfiguration(BytesMessageSenderConfiguration.class) + .run((context) -> assertThat(context).doesNotHaveBean(AsyncZipkinSpanHandler.class)); } @Configuration(proxyBeanMethods = false) - private static final class ReporterConfiguration { + private static final class BytesMessageSenderConfiguration { @Bean - @SuppressWarnings("unchecked") - Reporter reporter() { - return mock(Reporter.class); + BytesMessageSender sender() { + return mock(BytesMessageSender.class); } } @@ -103,9 +106,8 @@ Reporter reporter() { private static final class CustomConfiguration { @Bean - @SuppressWarnings("unchecked") - ZipkinSpanHandler customZipkinSpanHandler() { - return (ZipkinSpanHandler) ZipkinSpanHandler.create(mock(Reporter.class)); + AsyncZipkinSpanHandler customAsyncZipkinSpanHandler() { + return AsyncZipkinSpanHandler.create(mock(BytesMessageSender.class)); } } diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f0f4eeabadbc..c5852c8992d9 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -109,7 +109,14 @@ bom { ] } } - library("Brave", "5.17.1") { + library("Zipkin Reporter", "3.2.1") { + group("io.zipkin.reporter2") { + imports = [ + "zipkin-reporter-bom" + ] + } + } + library("Brave", "6.0.0") { group("io.zipkin.brave") { imports = [ "brave-bom" @@ -1096,7 +1103,7 @@ bom { ] } } - library("OpenTelemetry", "1.33.0") { + library("OpenTelemetry", "1.35.0") { group("io.opentelemetry") { imports = [ "opentelemetry-bom" diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/DockerImageNames.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/DockerImageNames.java index da27927f0704..a0e9f0f95cc0 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/DockerImageNames.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/DockerImageNames.java @@ -70,7 +70,7 @@ public final class DockerImageNames { private static final String REGISTRY_VERSION = "2.7.1"; - private static final String ZIPKIN_VERSION = "2.24.1"; + private static final String ZIPKIN_VERSION = "3.0.6"; private DockerImageNames() { }