Skip to content

Commit c05b4df

Browse files
committed
Introduce ObservationHandlerGroup interface
Add a new `ObservationHandlerGroup` interface that allows grouping logic to be implemented by the metrics and tracing modules. This update removes the need for `ObservabilityAutoConfiguration`. Issue: 45746
1 parent 6c6f44e commit c05b4df

File tree

22 files changed

+617
-783
lines changed

22 files changed

+617
-783
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/main/java/org/springframework/boot/actuate/autoconfigure/observability/ObservabilityAutoConfiguration.java

Lines changed: 0 additions & 131 deletions
This file was deleted.

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/main/java/org/springframework/boot/actuate/autoconfigure/observability/package-info.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.micrometer.tracing.handler.DefaultTracingObservationHandler;
2828
import io.micrometer.tracing.handler.PropagatingReceiverTracingObservationHandler;
2929
import io.micrometer.tracing.handler.PropagatingSenderTracingObservationHandler;
30+
import io.micrometer.tracing.handler.TracingObservationHandler;
3031
import io.micrometer.tracing.propagation.Propagator;
3132
import org.aspectj.weaver.Advice;
3233

@@ -37,6 +38,7 @@
3738
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
3839
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3940
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
41+
import org.springframework.boot.observation.autoconfigure.ObservationHandlerGroup;
4042
import org.springframework.context.annotation.Bean;
4143
import org.springframework.context.annotation.Configuration;
4244
import org.springframework.core.Ordered;
@@ -45,6 +47,7 @@
4547
import org.springframework.expression.ExpressionParser;
4648
import org.springframework.expression.spel.standard.SpelExpressionParser;
4749
import org.springframework.expression.spel.support.SimpleEvaluationContext;
50+
import org.springframework.util.ClassUtils;
4851

4952
/**
5053
* {@link EnableAutoConfiguration Auto-configuration} for the Micrometer Tracing API.
@@ -54,7 +57,6 @@
5457
* @since 3.0.0
5558
*/
5659
@AutoConfiguration
57-
@ConditionalOnClass(Tracer.class)
5860
@ConditionalOnBean(Tracer.class)
5961
public class MicrometerTracingAutoConfiguration {
6062

@@ -75,6 +77,13 @@ public class MicrometerTracingAutoConfiguration {
7577
*/
7678
public static final int SENDER_TRACING_OBSERVATION_HANDLER_ORDER = 2000;
7779

80+
@Bean
81+
public ObservationHandlerGroup tracingObservationHandlerGroup(Tracer tracer) {
82+
return ClassUtils.isPresent("io.micrometer.core.instrument.MeterRegistry", null)
83+
? new TracingAndMeterObservationHandlerGroup(tracer)
84+
: ObservationHandlerGroup.of(TracingObservationHandler.class);
85+
}
86+
7887
@Bean
7988
@ConditionalOnMissingBean
8089
@Order(DEFAULT_TRACING_OBSERVATION_HANDLER_ORDER)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2012-2025 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.tracing;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
22+
import io.micrometer.core.instrument.observation.MeterObservationHandler;
23+
import io.micrometer.observation.ObservationHandler;
24+
import io.micrometer.observation.ObservationHandler.FirstMatchingCompositeObservationHandler;
25+
import io.micrometer.observation.ObservationRegistry.ObservationConfig;
26+
import io.micrometer.tracing.Tracer;
27+
import io.micrometer.tracing.handler.TracingAwareMeterObservationHandler;
28+
import io.micrometer.tracing.handler.TracingObservationHandler;
29+
30+
import org.springframework.boot.observation.autoconfigure.ObservationHandlerGroup;
31+
32+
/**
33+
* {@link ObservationHandlerGroup} that considers both {@link TracingObservationHandler}
34+
* and {@link MeterObservationHandler} types as members. This group takes precedence over
35+
* any regular {@link MeterObservationHandler} group in order to use ensure
36+
* {@link TracingAwareMeterObservationHandler} wrapping is applied during registration.
37+
*
38+
* @author Phillip Webb
39+
*/
40+
class TracingAndMeterObservationHandlerGroup implements ObservationHandlerGroup {
41+
42+
private final Tracer tracer;
43+
44+
TracingAndMeterObservationHandlerGroup(Tracer tracer) {
45+
this.tracer = tracer;
46+
}
47+
48+
@Override
49+
public boolean isMember(ObservationHandler<?> handler) {
50+
return MeterObservationHandler.class.isInstance(handler) || TracingObservationHandler.class.isInstance(handler);
51+
}
52+
53+
@Override
54+
public int compareTo(ObservationHandlerGroup other) {
55+
if (other instanceof TracingAndMeterObservationHandlerGroup) {
56+
return 0;
57+
}
58+
return MeterObservationHandler.class.isAssignableFrom(other.handlerType()) ? -1 : 1;
59+
}
60+
61+
@Override
62+
public void registerMembers(ObservationConfig config, List<ObservationHandler<?>> members) {
63+
List<ObservationHandler<?>> tracingHandlers = new ArrayList<>(members.size());
64+
List<ObservationHandler<?>> metricsHandlers = new ArrayList<>(members.size());
65+
for (ObservationHandler<?> member : members) {
66+
if (member instanceof MeterObservationHandler<?> meterObservationHandler
67+
&& !(member instanceof TracingAwareMeterObservationHandler<?>)) {
68+
metricsHandlers.add(new TracingAwareMeterObservationHandler<>(meterObservationHandler, this.tracer));
69+
}
70+
else {
71+
tracingHandlers.add(member);
72+
}
73+
}
74+
registerHandlers(config, tracingHandlers);
75+
registerHandlers(config, metricsHandlers);
76+
}
77+
78+
private void registerHandlers(ObservationConfig config, List<ObservationHandler<?>> handlers) {
79+
if (handlers.size() == 1) {
80+
config.observationHandler(handlers.get(0));
81+
}
82+
else if (!handlers.isEmpty()) {
83+
config.observationHandler(new FirstMatchingCompositeObservationHandler(handlers));
84+
}
85+
}
86+
87+
@Override
88+
public Class<?> handlerType() {
89+
return TracingObservationHandler.class;
90+
}
91+
92+
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive.ReactiveCloudFoundryActuatorAutoConfiguration
22
org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet.CloudFoundryActuatorAutoConfiguration
3-
org.springframework.boot.actuate.autoconfigure.observability.ObservabilityAutoConfiguration
43
org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration
54
org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
65
org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration

0 commit comments

Comments
 (0)