Auto-configure CompositeSpanHandler with Brave
Closes gh-32753
This commit is contained in:
@@ -53,7 +53,11 @@ import io.micrometer.tracing.brave.bridge.BraveHttpClientHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpServerHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BravePropagator;
|
||||
import io.micrometer.tracing.brave.bridge.BraveTracer;
|
||||
import io.micrometer.tracing.brave.bridge.CompositeSpanHandler;
|
||||
import io.micrometer.tracing.brave.bridge.W3CPropagation;
|
||||
import io.micrometer.tracing.exporter.SpanExportingPredicate;
|
||||
import io.micrometer.tracing.exporter.SpanFilter;
|
||||
import io.micrometer.tracing.exporter.SpanReporter;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
@@ -64,6 +68,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@@ -87,6 +92,15 @@ public class BraveAutoConfiguration {
|
||||
*/
|
||||
private static final String DEFAULT_APPLICATION_NAME = "application";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
CompositeSpanHandler compositeSpanHandler(ObjectProvider<SpanExportingPredicate> predicates,
|
||||
ObjectProvider<SpanReporter> reporters, ObjectProvider<SpanFilter> filters) {
|
||||
return new CompositeSpanHandler(predicates.orderedStream().toList(), reporters.orderedStream().toList(),
|
||||
filters.orderedStream().toList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Tracing braveTracing(Environment environment, List<SpanHandler> spanHandlers,
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import brave.Span;
|
||||
import brave.Tracer;
|
||||
import brave.Tracing;
|
||||
import brave.baggage.BaggagePropagation;
|
||||
import brave.baggage.CorrelationScopeConfig.SingleCorrelationField;
|
||||
import brave.handler.SpanHandler;
|
||||
import brave.http.HttpClientHandler;
|
||||
import brave.http.HttpClientRequest;
|
||||
import brave.http.HttpClientResponse;
|
||||
@@ -37,16 +40,22 @@ import io.micrometer.tracing.brave.bridge.BraveBaggageManager;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpClientHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpServerHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveTracer;
|
||||
import io.micrometer.tracing.brave.bridge.CompositeSpanHandler;
|
||||
import io.micrometer.tracing.brave.bridge.W3CPropagation;
|
||||
import io.micrometer.tracing.exporter.SpanExportingPredicate;
|
||||
import io.micrometer.tracing.exporter.SpanFilter;
|
||||
import io.micrometer.tracing.exporter.SpanReporter;
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Answers;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfigurationTests.SpanHandlerConfiguration.AdditionalSpanHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -81,6 +90,7 @@ class BraveAutoConfigurationTests {
|
||||
assertThat(context).hasSingleBean(BraveTracer.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpServerHandler.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpClientHandler.class);
|
||||
assertThat(context).hasSingleBean(CompositeSpanHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,6 +125,8 @@ class BraveAutoConfigurationTests {
|
||||
assertThat(context).hasSingleBean(HttpServerHandler.class);
|
||||
assertThat(context).hasBean("customHttpClientHandler");
|
||||
assertThat(context).hasSingleBean(HttpClientHandler.class);
|
||||
assertThat(context).hasBean("customCompositeSpanHandler");
|
||||
assertThat(context).hasSingleBean(CompositeSpanHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -237,6 +249,108 @@ class BraveAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
void compositeSpanHandlerShouldBeFirstSpanHandler() {
|
||||
this.contextRunner.withUserConfiguration(SpanHandlerConfiguration.class).run((context) -> {
|
||||
Tracing tracing = context.getBean(Tracing.class);
|
||||
assertThat(tracing).extracting("tracer.spanHandler.delegate.handlers")
|
||||
.asInstanceOf(InstanceOfAssertFactories.array(SpanHandler[].class))
|
||||
.extracting((handler) -> (Class) handler.getClass())
|
||||
.containsExactly(CompositeSpanHandler.class, AdditionalSpanHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void compositeSpanHandlerUsesFilterPredicateAndReportersInOrder() {
|
||||
this.contextRunner.withUserConfiguration(CompositeSpanHandlerComponentsConfiguration.class).run((context) -> {
|
||||
CompositeSpanHandlerComponentsConfiguration components = context
|
||||
.getBean(CompositeSpanHandlerComponentsConfiguration.class);
|
||||
CompositeSpanHandler composite = context.getBean(CompositeSpanHandler.class);
|
||||
assertThat(composite).extracting("spanFilters").asList().containsExactly(components.filter1,
|
||||
components.filter2);
|
||||
assertThat(composite).extracting("filters").asList().containsExactly(components.predicate2,
|
||||
components.predicate1);
|
||||
assertThat(composite).extracting("reporters").asList().containsExactly(components.reporter1,
|
||||
components.reporter3, components.reporter2);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CompositeSpanHandlerComponentsConfiguration {
|
||||
|
||||
private final SpanFilter filter1 = mock(SpanFilter.class);
|
||||
|
||||
private final SpanFilter filter2 = mock(SpanFilter.class);
|
||||
|
||||
private final SpanExportingPredicate predicate1 = mock(SpanExportingPredicate.class);
|
||||
|
||||
private final SpanExportingPredicate predicate2 = mock(SpanExportingPredicate.class);
|
||||
|
||||
private final SpanReporter reporter1 = mock(SpanReporter.class);
|
||||
|
||||
private final SpanReporter reporter2 = mock(SpanReporter.class);
|
||||
|
||||
private final SpanReporter reporter3 = mock(SpanReporter.class);
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
SpanFilter filter1() {
|
||||
return this.filter1;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
SpanFilter filter2() {
|
||||
return this.filter2;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
SpanExportingPredicate predicate1() {
|
||||
return this.predicate1;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
SpanExportingPredicate predicate2() {
|
||||
return this.predicate2;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
SpanReporter reporter1() {
|
||||
return this.reporter1;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(3)
|
||||
SpanReporter reporter2() {
|
||||
return this.reporter2;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
SpanReporter reporter3() {
|
||||
return this.reporter3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class SpanHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
SpanHandler additionalSpanHandler() {
|
||||
return new AdditionalSpanHandler();
|
||||
}
|
||||
|
||||
static class AdditionalSpanHandler extends SpanHandler {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class CustomConfiguration {
|
||||
|
||||
@@ -302,6 +416,11 @@ class BraveAutoConfigurationTests {
|
||||
return mock(BraveHttpClientHandler.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
CompositeSpanHandler customCompositeSpanHandler() {
|
||||
return new CompositeSpanHandler(Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user