Skip to content

Commit 4d65fbd

Browse files
committed
Merge pull request spring-projects#37640 from jonatan-ivanov
* pr/37640: Add auto-configuration for SpanAspect Closes spring-projectsgh-37640
2 parents cfb6ee2 + 346db8e commit 4d65fbd

File tree

2 files changed

+130
-11
lines changed

2 files changed

+130
-11
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfiguration.java

+41-3
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,39 @@
1717
package org.springframework.boot.actuate.autoconfigure.tracing;
1818

1919
import io.micrometer.tracing.Tracer;
20+
import io.micrometer.tracing.annotation.DefaultNewSpanParser;
21+
import io.micrometer.tracing.annotation.ImperativeMethodInvocationProcessor;
22+
import io.micrometer.tracing.annotation.MethodInvocationProcessor;
23+
import io.micrometer.tracing.annotation.NewSpanParser;
24+
import io.micrometer.tracing.annotation.SpanAspect;
25+
import io.micrometer.tracing.annotation.SpanTagAnnotationHandler;
2026
import io.micrometer.tracing.handler.DefaultTracingObservationHandler;
2127
import io.micrometer.tracing.handler.PropagatingReceiverTracingObservationHandler;
2228
import io.micrometer.tracing.handler.PropagatingSenderTracingObservationHandler;
2329
import io.micrometer.tracing.propagation.Propagator;
30+
import org.aspectj.weaver.Advice;
2431

32+
import org.springframework.beans.factory.ObjectProvider;
2533
import org.springframework.boot.autoconfigure.AutoConfiguration;
2634
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2735
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2836
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2937
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3038
import org.springframework.context.annotation.Bean;
39+
import org.springframework.context.annotation.Configuration;
3140
import org.springframework.core.Ordered;
3241
import org.springframework.core.annotation.Order;
3342

3443
/**
3544
* {@link EnableAutoConfiguration Auto-configuration} for the Micrometer Tracing API.
3645
*
3746
* @author Moritz Halbritter
47+
* @author Jonatan Ivanov
3848
* @since 3.0.0
3949
*/
4050
@AutoConfiguration
4151
@ConditionalOnClass(Tracer.class)
52+
@ConditionalOnBean(Tracer.class)
4253
public class MicrometerTracingAutoConfiguration {
4354

4455
/**
@@ -60,15 +71,14 @@ public class MicrometerTracingAutoConfiguration {
6071

6172
@Bean
6273
@ConditionalOnMissingBean
63-
@ConditionalOnBean(Tracer.class)
6474
@Order(DEFAULT_TRACING_OBSERVATION_HANDLER_ORDER)
6575
public DefaultTracingObservationHandler defaultTracingObservationHandler(Tracer tracer) {
6676
return new DefaultTracingObservationHandler(tracer);
6777
}
6878

6979
@Bean
7080
@ConditionalOnMissingBean
71-
@ConditionalOnBean({ Tracer.class, Propagator.class })
81+
@ConditionalOnBean(Propagator.class)
7282
@Order(SENDER_TRACING_OBSERVATION_HANDLER_ORDER)
7383
public PropagatingSenderTracingObservationHandler<?> propagatingSenderTracingObservationHandler(Tracer tracer,
7484
Propagator propagator) {
@@ -77,11 +87,39 @@ public PropagatingSenderTracingObservationHandler<?> propagatingSenderTracingObs
7787

7888
@Bean
7989
@ConditionalOnMissingBean
80-
@ConditionalOnBean({ Tracer.class, Propagator.class })
90+
@ConditionalOnBean(Propagator.class)
8191
@Order(RECEIVER_TRACING_OBSERVATION_HANDLER_ORDER)
8292
public PropagatingReceiverTracingObservationHandler<?> propagatingReceiverTracingObservationHandler(Tracer tracer,
8393
Propagator propagator) {
8494
return new PropagatingReceiverTracingObservationHandler<>(tracer, propagator);
8595
}
8696

97+
@Configuration(proxyBeanMethods = false)
98+
@ConditionalOnClass(Advice.class)
99+
static class SpanAspectConfiguration {
100+
101+
@Bean
102+
@ConditionalOnMissingBean
103+
DefaultNewSpanParser newSpanParser() {
104+
return new DefaultNewSpanParser();
105+
}
106+
107+
@Bean
108+
@ConditionalOnMissingBean
109+
ImperativeMethodInvocationProcessor imperativeMethodInvocationProcessor(NewSpanParser newSpanParser,
110+
Tracer tracer, ObjectProvider<SpanTagAnnotationHandler> spanTagAnnotationHandler) {
111+
ImperativeMethodInvocationProcessor methodInvocationProcessor = new ImperativeMethodInvocationProcessor(
112+
newSpanParser, tracer);
113+
spanTagAnnotationHandler.ifAvailable(methodInvocationProcessor::setSpanTagAnnotationHandler);
114+
return methodInvocationProcessor;
115+
}
116+
117+
@Bean
118+
@ConditionalOnMissingBean
119+
SpanAspect spanAspect(MethodInvocationProcessor methodInvocationProcessor) {
120+
return new SpanAspect(methodInvocationProcessor);
121+
}
122+
123+
}
124+
87125
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfigurationTests.java

+89-8
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,27 @@
1919
import java.util.List;
2020

2121
import io.micrometer.tracing.Tracer;
22+
import io.micrometer.tracing.annotation.DefaultNewSpanParser;
23+
import io.micrometer.tracing.annotation.ImperativeMethodInvocationProcessor;
24+
import io.micrometer.tracing.annotation.MethodInvocationProcessor;
25+
import io.micrometer.tracing.annotation.NewSpanParser;
26+
import io.micrometer.tracing.annotation.SpanAspect;
27+
import io.micrometer.tracing.annotation.SpanTagAnnotationHandler;
2228
import io.micrometer.tracing.handler.DefaultTracingObservationHandler;
2329
import io.micrometer.tracing.handler.PropagatingReceiverTracingObservationHandler;
2430
import io.micrometer.tracing.handler.PropagatingSenderTracingObservationHandler;
2531
import io.micrometer.tracing.handler.TracingObservationHandler;
2632
import io.micrometer.tracing.propagation.Propagator;
33+
import org.aspectj.weaver.Advice;
2734
import org.junit.jupiter.api.Test;
2835

2936
import org.springframework.boot.autoconfigure.AutoConfigurations;
37+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3038
import org.springframework.boot.test.context.FilteredClassLoader;
3139
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3240
import org.springframework.context.annotation.Bean;
3341
import org.springframework.context.annotation.Configuration;
42+
import org.springframework.test.util.ReflectionTestUtils;
3443

3544
import static org.assertj.core.api.Assertions.assertThat;
3645
import static org.mockito.Mockito.mock;
@@ -39,6 +48,7 @@
3948
* Tests for {@link MicrometerTracingAutoConfiguration}.
4049
*
4150
* @author Moritz Halbritter
51+
* @author Jonatan Ivanov
4252
*/
4353
class MicrometerTracingAutoConfigurationTests {
4454

@@ -52,6 +62,9 @@ void shouldSupplyBeans() {
5262
assertThat(context).hasSingleBean(DefaultTracingObservationHandler.class);
5363
assertThat(context).hasSingleBean(PropagatingReceiverTracingObservationHandler.class);
5464
assertThat(context).hasSingleBean(PropagatingSenderTracingObservationHandler.class);
65+
assertThat(context).hasSingleBean(DefaultNewSpanParser.class);
66+
assertThat(context).hasSingleBean(ImperativeMethodInvocationProcessor.class);
67+
assertThat(context).hasSingleBean(SpanAspect.class);
5568
});
5669
}
5770

@@ -75,14 +88,21 @@ void shouldSupplyBeansInCorrectOrder() {
7588

7689
@Test
7790
void shouldBackOffOnCustomBeans() {
78-
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
79-
assertThat(context).hasBean("customDefaultTracingObservationHandler");
80-
assertThat(context).hasSingleBean(DefaultTracingObservationHandler.class);
81-
assertThat(context).hasBean("customPropagatingReceiverTracingObservationHandler");
82-
assertThat(context).hasSingleBean(PropagatingReceiverTracingObservationHandler.class);
83-
assertThat(context).hasBean("customPropagatingSenderTracingObservationHandler");
84-
assertThat(context).hasSingleBean(PropagatingSenderTracingObservationHandler.class);
85-
});
91+
this.contextRunner.withUserConfiguration(TracerConfiguration.class, CustomConfiguration.class)
92+
.run((context) -> {
93+
assertThat(context).hasBean("customDefaultTracingObservationHandler");
94+
assertThat(context).hasSingleBean(DefaultTracingObservationHandler.class);
95+
assertThat(context).hasBean("customPropagatingReceiverTracingObservationHandler");
96+
assertThat(context).hasSingleBean(PropagatingReceiverTracingObservationHandler.class);
97+
assertThat(context).hasBean("customPropagatingSenderTracingObservationHandler");
98+
assertThat(context).hasSingleBean(PropagatingSenderTracingObservationHandler.class);
99+
assertThat(context).hasBean("customDefaultNewSpanParser");
100+
assertThat(context).hasSingleBean(DefaultNewSpanParser.class);
101+
assertThat(context).hasBean("customImperativeMethodInvocationProcessor");
102+
assertThat(context).hasSingleBean(ImperativeMethodInvocationProcessor.class);
103+
assertThat(context).hasBean("customSpanAspect");
104+
assertThat(context).hasSingleBean(SpanAspect.class);
105+
});
86106
}
87107

88108
@Test
@@ -91,6 +111,9 @@ void shouldNotSupplyBeansIfMicrometerIsMissing() {
91111
assertThat(context).doesNotHaveBean(DefaultTracingObservationHandler.class);
92112
assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class);
93113
assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class);
114+
assertThat(context).doesNotHaveBean(DefaultNewSpanParser.class);
115+
assertThat(context).doesNotHaveBean(ImperativeMethodInvocationProcessor.class);
116+
assertThat(context).doesNotHaveBean(SpanAspect.class);
94117
});
95118
}
96119

@@ -100,17 +123,47 @@ void shouldNotSupplyBeansIfTracerIsMissing() {
100123
assertThat(context).doesNotHaveBean(DefaultTracingObservationHandler.class);
101124
assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class);
102125
assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class);
126+
assertThat(context).doesNotHaveBean(DefaultNewSpanParser.class);
127+
assertThat(context).doesNotHaveBean(ImperativeMethodInvocationProcessor.class);
128+
assertThat(context).doesNotHaveBean(SpanAspect.class);
103129
});
104130
}
105131

132+
@Test
133+
void shouldNotSupplyBeansIfAspectjIsMissing() {
134+
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
135+
.withClassLoader(new FilteredClassLoader(Advice.class))
136+
.run((context) -> {
137+
assertThat(context).doesNotHaveBean(DefaultNewSpanParser.class);
138+
assertThat(context).doesNotHaveBean(ImperativeMethodInvocationProcessor.class);
139+
assertThat(context).doesNotHaveBean(SpanAspect.class);
140+
});
141+
}
142+
106143
@Test
107144
void shouldNotSupplyBeansIfPropagatorIsMissing() {
108145
this.contextRunner.withUserConfiguration(TracerConfiguration.class).run((context) -> {
109146
assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class);
110147
assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class);
148+
149+
assertThat(context).hasSingleBean(DefaultNewSpanParser.class);
150+
assertThat(context).hasSingleBean(ImperativeMethodInvocationProcessor.class);
151+
assertThat(context).hasSingleBean(SpanAspect.class);
111152
});
112153
}
113154

155+
@Test
156+
void shouldConfigureSpanTagAnnotationHandler() {
157+
this.contextRunner.withUserConfiguration(TracerConfiguration.class, SpanTagAnnotationHandlerConfiguration.class)
158+
.run((context) -> {
159+
assertThat(context).hasSingleBean(DefaultNewSpanParser.class);
160+
assertThat(context).hasSingleBean(SpanAspect.class);
161+
assertThat(ReflectionTestUtils.getField(context.getBean(ImperativeMethodInvocationProcessor.class),
162+
"spanTagAnnotationHandler"))
163+
.isSameAs(context.getBean(SpanTagAnnotationHandler.class));
164+
});
165+
}
166+
114167
@Configuration(proxyBeanMethods = false)
115168
private static class TracerConfiguration {
116169

@@ -149,6 +202,34 @@ PropagatingSenderTracingObservationHandler<?> customPropagatingSenderTracingObse
149202
return mock(PropagatingSenderTracingObservationHandler.class);
150203
}
151204

205+
@Bean
206+
DefaultNewSpanParser customDefaultNewSpanParser() {
207+
return new DefaultNewSpanParser();
208+
}
209+
210+
@Bean
211+
@ConditionalOnMissingBean
212+
ImperativeMethodInvocationProcessor customImperativeMethodInvocationProcessor(NewSpanParser newSpanParser,
213+
Tracer tracer) {
214+
return new ImperativeMethodInvocationProcessor(newSpanParser, tracer);
215+
}
216+
217+
@Bean
218+
@ConditionalOnMissingBean
219+
SpanAspect customSpanAspect(MethodInvocationProcessor methodInvocationProcessor) {
220+
return new SpanAspect(methodInvocationProcessor);
221+
}
222+
223+
}
224+
225+
@Configuration(proxyBeanMethods = false)
226+
private static class SpanTagAnnotationHandlerConfiguration {
227+
228+
@Bean
229+
SpanTagAnnotationHandler spanTagAnnotationHandler() {
230+
return new SpanTagAnnotationHandler((aClass) -> null, (aClass) -> null);
231+
}
232+
152233
}
153234

154235
}

0 commit comments

Comments
 (0)