Skip to content

Commit a454712

Browse files
jonatan-ivanovmhalbritter
authored andcommitted
Add auto-configuration for CountedAspect and TimedAspect
See gh-37626
1 parent 4493958 commit a454712

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.metrics;
18+
19+
import io.micrometer.core.aop.CountedAspect;
20+
import io.micrometer.core.aop.MeterTagAnnotationHandler;
21+
import io.micrometer.core.aop.TimedAspect;
22+
import io.micrometer.core.instrument.MeterRegistry;
23+
import org.aspectj.weaver.Advice;
24+
25+
import org.springframework.beans.factory.ObjectProvider;
26+
import org.springframework.boot.autoconfigure.AutoConfiguration;
27+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
29+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
30+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
31+
import org.springframework.context.annotation.Bean;
32+
33+
/**
34+
* {@link EnableAutoConfiguration Auto-configuration} for Micrometer-based metrics
35+
* aspects.
36+
*
37+
* @author Jonatan Ivanov
38+
* @since 3.2.0
39+
*/
40+
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class })
41+
@ConditionalOnClass({ MeterRegistry.class, Advice.class })
42+
@ConditionalOnBean(MeterRegistry.class)
43+
public class MetricsAspectsAutoConfiguration {
44+
45+
@Bean
46+
@ConditionalOnMissingBean
47+
CountedAspect countedAspect(MeterRegistry registry) {
48+
return new CountedAspect(registry);
49+
}
50+
51+
@Bean
52+
@ConditionalOnMissingBean
53+
TimedAspect timedAspect(MeterRegistry registry,
54+
ObjectProvider<MeterTagAnnotationHandler> meterTagAnnotationHandler) {
55+
TimedAspect timedAspect = new TimedAspect(registry);
56+
meterTagAnnotationHandler.ifAvailable(timedAspect::setMeterTagAnnotationHandler);
57+
return timedAspect;
58+
}
59+
60+
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfigurati
4343
org.springframework.boot.actuate.autoconfigure.metrics.KafkaMetricsAutoConfiguration
4444
org.springframework.boot.actuate.autoconfigure.metrics.Log4J2MetricsAutoConfiguration
4545
org.springframework.boot.actuate.autoconfigure.metrics.LogbackMetricsAutoConfiguration
46+
org.springframework.boot.actuate.autoconfigure.metrics.MetricsAspectsAutoConfiguration
4647
org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration
4748
org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration
4849
org.springframework.boot.actuate.autoconfigure.metrics.SystemMetricsAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.metrics;
18+
19+
import io.micrometer.core.aop.CountedAspect;
20+
import io.micrometer.core.aop.MeterTagAnnotationHandler;
21+
import io.micrometer.core.aop.TimedAspect;
22+
import io.micrometer.core.instrument.MeterRegistry;
23+
import org.aspectj.weaver.Advice;
24+
import org.junit.jupiter.api.Test;
25+
26+
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
27+
import org.springframework.boot.autoconfigure.AutoConfigurations;
28+
import org.springframework.boot.test.context.FilteredClassLoader;
29+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
30+
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.test.util.ReflectionTestUtils;
33+
34+
import static org.assertj.core.api.Assertions.assertThat;
35+
36+
/**
37+
* Tests for {@link MetricsAspectsAutoConfiguration}.
38+
*
39+
* @author Jonatan Ivanov
40+
*/
41+
class MetricsAspectsAutoConfigurationTests {
42+
43+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
44+
.withConfiguration(AutoConfigurations.of(MetricsAspectsAutoConfiguration.class));
45+
46+
@Test
47+
void shouldConfigureAspects() {
48+
this.contextRunner.run((context) -> {
49+
assertThat(context).hasSingleBean(CountedAspect.class);
50+
assertThat(context).hasSingleBean(TimedAspect.class);
51+
});
52+
}
53+
54+
@Test
55+
void shouldConfigureMeterTagAnnotationHandler() {
56+
this.contextRunner.withUserConfiguration(MeterTagAnnotationHandlerConfiguration.class).run((context) -> {
57+
assertThat(context).hasSingleBean(CountedAspect.class);
58+
assertThat(ReflectionTestUtils.getField(context.getBean(TimedAspect.class), "meterTagAnnotationHandler"))
59+
.isSameAs(context.getBean(MeterTagAnnotationHandler.class));
60+
});
61+
}
62+
63+
@Test
64+
void shouldNotConfigureAspectsIfMicrometerIsMissing() {
65+
this.contextRunner.withClassLoader(new FilteredClassLoader(MeterRegistry.class)).run((context) -> {
66+
assertThat(context).doesNotHaveBean(CountedAspect.class);
67+
assertThat(context).doesNotHaveBean(TimedAspect.class);
68+
});
69+
}
70+
71+
@Test
72+
void shouldNotConfigureAspectsIfAspectjIsMissing() {
73+
this.contextRunner.withClassLoader(new FilteredClassLoader(Advice.class)).run((context) -> {
74+
assertThat(context).doesNotHaveBean(CountedAspect.class);
75+
assertThat(context).doesNotHaveBean(TimedAspect.class);
76+
});
77+
}
78+
79+
@Test
80+
void shouldNotConfigureAspectsIfMeterRegistryBeanIsMissing() {
81+
new ApplicationContextRunner().run((context) -> {
82+
assertThat(context).doesNotHaveBean(MeterRegistry.class);
83+
assertThat(context).doesNotHaveBean(CountedAspect.class);
84+
assertThat(context).doesNotHaveBean(TimedAspect.class);
85+
});
86+
}
87+
88+
@Test
89+
void shouldBackOffIfAspectBeansExist() {
90+
this.contextRunner.withUserConfiguration(CustomAspectsConfiguration.class).run((context) -> {
91+
assertThat(context).hasSingleBean(CountedAspect.class).hasBean("customCountedAspect");
92+
assertThat(context).hasSingleBean(TimedAspect.class).hasBean("customTimedAspect");
93+
});
94+
}
95+
96+
@Configuration(proxyBeanMethods = false)
97+
static class CustomAspectsConfiguration {
98+
99+
@Bean
100+
CountedAspect customCountedAspect(MeterRegistry registry) {
101+
return new CountedAspect(registry);
102+
}
103+
104+
@Bean
105+
TimedAspect customTimedAspect(MeterRegistry registry) {
106+
return new TimedAspect(registry);
107+
}
108+
109+
}
110+
111+
@Configuration(proxyBeanMethods = false)
112+
static class MeterTagAnnotationHandlerConfiguration {
113+
114+
@Bean
115+
MeterTagAnnotationHandler meterTagAnnotationHandler() {
116+
return new MeterTagAnnotationHandler(null, null);
117+
}
118+
119+
}
120+
121+
}

0 commit comments

Comments
 (0)