Skip to content

Commit c4be302

Browse files
committed
Auto-configure SpanTagAnnotationHandler
Closes gh-38662
1 parent a7d88b6 commit c4be302

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.tracing;
1818

19+
import io.micrometer.common.annotation.ValueExpressionResolver;
1920
import io.micrometer.tracing.Tracer;
2021
import io.micrometer.tracing.annotation.DefaultNewSpanParser;
2122
import io.micrometer.tracing.annotation.ImperativeMethodInvocationProcessor;
@@ -29,7 +30,7 @@
2930
import io.micrometer.tracing.propagation.Propagator;
3031
import org.aspectj.weaver.Advice;
3132

32-
import org.springframework.beans.factory.ObjectProvider;
33+
import org.springframework.beans.factory.BeanFactory;
3334
import org.springframework.boot.autoconfigure.AutoConfiguration;
3435
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3536
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -39,6 +40,10 @@
3940
import org.springframework.context.annotation.Configuration;
4041
import org.springframework.core.Ordered;
4142
import org.springframework.core.annotation.Order;
43+
import org.springframework.expression.Expression;
44+
import org.springframework.expression.ExpressionParser;
45+
import org.springframework.expression.spel.standard.SpelExpressionParser;
46+
import org.springframework.expression.spel.support.SimpleEvaluationContext;
4247

4348
/**
4449
* {@link EnableAutoConfiguration Auto-configuration} for the Micrometer Tracing API.
@@ -104,14 +109,18 @@ DefaultNewSpanParser newSpanParser() {
104109
return new DefaultNewSpanParser();
105110
}
106111

112+
@Bean
113+
@ConditionalOnMissingBean
114+
SpanTagAnnotationHandler spanTagAnnotationHandler(BeanFactory beanFactory) {
115+
ValueExpressionResolver valueExpressionResolver = new SpelTagValueExpressionResolver();
116+
return new SpanTagAnnotationHandler(beanFactory::getBean, (ignored) -> valueExpressionResolver);
117+
}
118+
107119
@Bean
108120
@ConditionalOnMissingBean(MethodInvocationProcessor.class)
109121
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;
122+
Tracer tracer, SpanTagAnnotationHandler spanTagAnnotationHandler) {
123+
return new ImperativeMethodInvocationProcessor(newSpanParser, tracer, spanTagAnnotationHandler);
115124
}
116125

117126
@Bean
@@ -122,4 +131,21 @@ SpanAspect spanAspect(MethodInvocationProcessor methodInvocationProcessor) {
122131

123132
}
124133

134+
private static class SpelTagValueExpressionResolver implements ValueExpressionResolver {
135+
136+
@Override
137+
public String resolve(String expression, Object parameter) {
138+
try {
139+
SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
140+
ExpressionParser expressionParser = new SpelExpressionParser();
141+
Expression expressionToEvaluate = expressionParser.parseExpression(expression);
142+
return expressionToEvaluate.getValue(context, parameter, String.class);
143+
}
144+
catch (Exception ex) {
145+
throw new IllegalStateException("Unable to evaluate SpEL expression '%s'".formatted(expression), ex);
146+
}
147+
}
148+
149+
}
150+
125151
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
1818

1919
import java.util.List;
2020

21+
import io.micrometer.common.annotation.ValueExpressionResolver;
22+
import io.micrometer.common.annotation.ValueResolver;
2123
import io.micrometer.tracing.Tracer;
2224
import io.micrometer.tracing.annotation.DefaultNewSpanParser;
2325
import io.micrometer.tracing.annotation.ImperativeMethodInvocationProcessor;
@@ -63,6 +65,7 @@ void shouldSupplyBeans() {
6365
assertThat(context).hasSingleBean(DefaultNewSpanParser.class);
6466
assertThat(context).hasSingleBean(ImperativeMethodInvocationProcessor.class);
6567
assertThat(context).hasSingleBean(SpanAspect.class);
68+
assertThat(context).hasSingleBean(SpanTagAnnotationHandler.class);
6669
});
6770
}
6871

@@ -100,6 +103,8 @@ void shouldBackOffOnCustomBeans() {
100103
assertThat(context).hasSingleBean(ImperativeMethodInvocationProcessor.class);
101104
assertThat(context).hasBean("customSpanAspect");
102105
assertThat(context).hasSingleBean(SpanAspect.class);
106+
assertThat(context).hasBean("customSpanTagAnnotationHandler");
107+
assertThat(context).hasSingleBean(SpanTagAnnotationHandler.class);
103108
});
104109
}
105110

@@ -215,6 +220,12 @@ SpanAspect customSpanAspect(MethodInvocationProcessor methodInvocationProcessor)
215220
return new SpanAspect(methodInvocationProcessor);
216221
}
217222

223+
@Bean
224+
SpanTagAnnotationHandler customSpanTagAnnotationHandler() {
225+
return new SpanTagAnnotationHandler((aClass) -> mock(ValueResolver.class),
226+
(aClass) -> mock(ValueExpressionResolver.class));
227+
}
228+
218229
}
219230

220231
@Configuration(proxyBeanMethods = false)

0 commit comments

Comments
 (0)