diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/MetricsAndTracingObservationHandlerGrouping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/MetricsAndTracingObservationHandlerGrouping.java deleted file mode 100644 index 6992d5f75d..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/MetricsAndTracingObservationHandlerGrouping.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.observation; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import io.micrometer.core.instrument.observation.MeterObservationHandler; -import io.micrometer.observation.ObservationHandler; -import io.micrometer.observation.ObservationHandler.FirstMatchingCompositeObservationHandler; -import io.micrometer.observation.ObservationRegistry.ObservationConfig; -import io.micrometer.tracing.handler.TracingObservationHandler; - -/** - * {@link ObservationHandlerGrouping} used by {@link ObservationAutoConfiguration} if both - * micrometer-core and micrometer-tracing are on the classpath. - * - * Groups all {@link TracingObservationHandler} into a - * {@link FirstMatchingCompositeObservationHandler}, and {@link MeterObservationHandler} - * into a {@link FirstMatchingCompositeObservationHandler}. All other handlers are added - * to the {@link ObservationConfig} directly. - * - * @author Moritz Halbritter - */ -class MetricsAndTracingObservationHandlerGrouping implements ObservationHandlerGrouping { - - @Override - public void apply(Collection> handlers, ObservationConfig config) { - List> meterObservationHandlers = new ArrayList<>(); - List> tracingObservationHandlers = new ArrayList<>(); - for (ObservationHandler handler : handlers) { - if (handler instanceof TracingObservationHandler) { - tracingObservationHandlers.add(handler); - } - else if (handler instanceof MeterObservationHandler) { - meterObservationHandlers.add(handler); - } - else { - config.observationHandler(handler); - } - } - if (!tracingObservationHandlers.isEmpty()) { - config.observationHandler(new FirstMatchingCompositeObservationHandler(tracingObservationHandlers)); - } - if (!meterObservationHandlers.isEmpty()) { - config.observationHandler(new FirstMatchingCompositeObservationHandler(meterObservationHandlers)); - } - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java index 604a214b54..df97d94641 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.autoconfigure.observation; +import java.util.List; + import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler; import io.micrometer.core.instrument.observation.MeterObservationHandler; @@ -26,6 +28,7 @@ import io.micrometer.observation.ObservationPredicate; import io.micrometer.observation.ObservationRegistry; import io.micrometer.tracing.Tracer; import io.micrometer.tracing.handler.TracingAwareMeterObservationHandler; +import io.micrometer.tracing.handler.TracingObservationHandler; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; @@ -76,15 +79,8 @@ public class ObservationAutoConfiguration { static class OnlyMetricsConfiguration { @Bean - @ConditionalOnMissingBean(MeterObservationHandler.class) - @ConditionalOnBean(MeterRegistry.class) - DefaultMeterObservationHandler defaultMeterObservationHandler(MeterRegistry meterRegistry) { - return new DefaultMeterObservationHandler(meterRegistry); - } - - @Bean - OnlyMetricsObservationHandlerGrouping onlyMetricsObservationHandlerGrouping() { - return new OnlyMetricsObservationHandlerGrouping(); + ObservationHandlerGrouping metricsObservationHandlerGrouping() { + return new ObservationHandlerGrouping(MeterObservationHandler.class); } } @@ -95,8 +91,8 @@ public class ObservationAutoConfiguration { static class OnlyTracingConfiguration { @Bean - OnlyTracingObservationHandlerGrouping tracingObservationHandlerGrouping() { - return new OnlyTracingObservationHandlerGrouping(); + ObservationHandlerGrouping tracingObservationHandlerGrouping() { + return new ObservationHandlerGrouping(TracingObservationHandler.class); } } @@ -106,23 +102,40 @@ public class ObservationAutoConfiguration { static class MetricsWithTracingConfiguration { @Bean - @ConditionalOnMissingBean(MeterObservationHandler.class) - @ConditionalOnBean({ MeterRegistry.class, Tracer.class }) - TracingAwareMeterObservationHandler tracingAwareMeterObservationHandler( - MeterRegistry meterRegistry, Tracer tracer) { - return new TracingAwareMeterObservationHandler<>(new DefaultMeterObservationHandler(meterRegistry), tracer); + ObservationHandlerGrouping metricsAndTracingObservationHandlerGrouping() { + return new ObservationHandlerGrouping( + List.of(TracingObservationHandler.class, MeterObservationHandler.class)); } - @Bean - @ConditionalOnMissingBean({ MeterObservationHandler.class, Tracer.class }) - @ConditionalOnBean(MeterRegistry.class) - DefaultMeterObservationHandler defaultMeterObservationHandler(MeterRegistry meterRegistry) { - return new DefaultMeterObservationHandler(meterRegistry); + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnBean(MeterRegistry.class) + @ConditionalOnMissingBean(MeterObservationHandler.class) + static class MeterObservationHandlerConfiguration { + + @ConditionalOnMissingBean(Tracer.class) + @Configuration(proxyBeanMethods = false) + static class OnlyMetricsMeterObservationHandlerConfiguration { + + @Bean + DefaultMeterObservationHandler defaultMeterObservationHandler(MeterRegistry meterRegistry) { + return new DefaultMeterObservationHandler(meterRegistry); + } + } - @Bean - MetricsAndTracingObservationHandlerGrouping metricsAndTracingObservationHandlerGrouping() { - return new MetricsAndTracingObservationHandlerGrouping(); + @ConditionalOnBean(Tracer.class) + @Configuration(proxyBeanMethods = false) + static class TracingAndMetricsObservationHandlerConfiguration { + + @Bean + TracingAwareMeterObservationHandler tracingAwareMeterObservationHandler( + MeterRegistry meterRegistry, Tracer tracer) { + return new TracingAwareMeterObservationHandler<>(new DefaultMeterObservationHandler(meterRegistry), + tracer); + } + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java index e5713ec304..fcdbd5fb2f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java @@ -16,24 +16,61 @@ package org.springframework.boot.actuate.autoconfigure.observation; -import java.util.Collection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import io.micrometer.observation.ObservationHandler; +import io.micrometer.observation.ObservationHandler.FirstMatchingCompositeObservationHandler; import io.micrometer.observation.ObservationRegistry.ObservationConfig; +import org.springframework.util.CollectionUtils; + /** - * Strategy to apply {@link ObservationHandler ObservationHandlers} to an - * {@link ObservationConfig}. + * Groups {@link ObservationHandler ObservationHandlers} by type. * - * @author Moritz Halbritter + * @author Andy Wilkinson */ -interface ObservationHandlerGrouping { - - /** - * Applies the given list of {@code handlers} to the given {@code config}. - * @param handlers the list of observation handlers - * @param config the config to apply the handlers to - */ - void apply(Collection> handlers, ObservationConfig config); +@SuppressWarnings("rawtypes") +class ObservationHandlerGrouping { + + private final List> categories; + + ObservationHandlerGrouping(Class category) { + this(List.of(category)); + } + + ObservationHandlerGrouping(List> categories) { + this.categories = categories; + } + + void apply(List> handlers, ObservationConfig config) { + Map, List>> groupings = new HashMap<>(); + for (ObservationHandler handler : handlers) { + Class category = findCategory(handler); + if (category != null) { + groupings.computeIfAbsent(category, (c) -> new ArrayList<>()).add(handler); + } + else { + config.observationHandler(handler); + } + } + for (Class category : this.categories) { + List> handlerGroup = groupings.get(category); + if (!CollectionUtils.isEmpty(handlerGroup)) { + config.observationHandler(new FirstMatchingCompositeObservationHandler(handlerGroup)); + } + } + } + + private Class findCategory(ObservationHandler handler) { + for (Class category : this.categories) { + if (category.isInstance(handler)) { + return category; + } + } + return null; + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/OnlyMetricsObservationHandlerGrouping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/OnlyMetricsObservationHandlerGrouping.java deleted file mode 100644 index 23089c030d..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/OnlyMetricsObservationHandlerGrouping.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.observation; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import io.micrometer.core.instrument.observation.MeterObservationHandler; -import io.micrometer.observation.ObservationHandler; -import io.micrometer.observation.ObservationHandler.FirstMatchingCompositeObservationHandler; -import io.micrometer.observation.ObservationRegistry.ObservationConfig; - -/** - * {@link ObservationHandlerGrouping} used by {@link ObservationAutoConfiguration} if - * micrometer-tracing is not on the classpath but micrometer-core is. - * - * Groups all {@link MeterObservationHandler} into a - * {@link FirstMatchingCompositeObservationHandler}. All other handlers are added to the - * {@link ObservationConfig} directly. - * - * @author Moritz Halbritter - */ -class OnlyMetricsObservationHandlerGrouping implements ObservationHandlerGrouping { - - @Override - public void apply(Collection> handlers, ObservationConfig config) { - List> meterObservationHandlers = new ArrayList<>(); - for (ObservationHandler handler : handlers) { - if (handler instanceof MeterObservationHandler) { - meterObservationHandlers.add(handler); - } - else { - config.observationHandler(handler); - } - } - if (!meterObservationHandlers.isEmpty()) { - config.observationHandler(new FirstMatchingCompositeObservationHandler(meterObservationHandlers)); - } - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/OnlyTracingObservationHandlerGrouping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/OnlyTracingObservationHandlerGrouping.java deleted file mode 100644 index ad1588d622..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/OnlyTracingObservationHandlerGrouping.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.observation; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import io.micrometer.observation.ObservationHandler; -import io.micrometer.observation.ObservationRegistry; -import io.micrometer.tracing.handler.TracingObservationHandler; - -/** - * {@link ObservationHandlerGrouping} used by {@link ObservationAutoConfiguration} if - * micrometer-core is not on the classpath but micrometer-tracing is. - * - * Groups all {@link TracingObservationHandler} into a - * {@link ObservationHandler.FirstMatchingCompositeObservationHandler}. All other handlers - * are added to the {@link ObservationRegistry.ObservationConfig} directly. - * - * @author Jonatan Ivanov - */ -class OnlyTracingObservationHandlerGrouping implements ObservationHandlerGrouping { - - @Override - public void apply(Collection> handlers, ObservationRegistry.ObservationConfig config) { - List> tracingObservationHandlers = new ArrayList<>(); - for (ObservationHandler handler : handlers) { - if (handler instanceof TracingObservationHandler) { - tracingObservationHandlers.add(handler); - } - else { - config.observationHandler(handler); - } - } - if (!tracingObservationHandlers.isEmpty()) { - config.observationHandler( - new ObservationHandler.FirstMatchingCompositeObservationHandler(tracingObservationHandlers)); - } - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfigurationTests.java index a37ceab85a..13a724ac90 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfigurationTests.java @@ -98,7 +98,7 @@ class ObservationAutoConfigurationTests { assertThat(context).hasSingleBean(ObservationHandler.class); assertThat(context).hasSingleBean(DefaultMeterObservationHandler.class); assertThat(context).hasSingleBean(ObservationHandlerGrouping.class); - assertThat(context).hasSingleBean(OnlyMetricsObservationHandlerGrouping.class); + assertThat(context).hasBean("metricsObservationHandlerGrouping"); }); } @@ -109,7 +109,7 @@ class ObservationAutoConfigurationTests { Observation.start("test-observation", observationRegistry).stop(); assertThat(context).doesNotHaveBean(ObservationHandler.class); assertThat(context).hasSingleBean(ObservationHandlerGrouping.class); - assertThat(context).hasSingleBean(OnlyTracingObservationHandlerGrouping.class); + assertThat(context).hasBean("tracingObservationHandlerGrouping"); }); } @@ -123,7 +123,7 @@ class ObservationAutoConfigurationTests { assertThat(context).hasSingleBean(ObservationHandler.class); assertThat(context).hasSingleBean(TracingAwareMeterObservationHandler.class); assertThat(context).hasSingleBean(ObservationHandlerGrouping.class); - assertThat(context).hasSingleBean(MetricsAndTracingObservationHandlerGrouping.class); + assertThat(context).hasBean("metricsAndTracingObservationHandlerGrouping"); }); } @@ -136,7 +136,7 @@ class ObservationAutoConfigurationTests { assertThat(context).hasSingleBean(ObservationHandler.class); assertThat(context).hasSingleBean(DefaultMeterObservationHandler.class); assertThat(context).hasSingleBean(ObservationHandlerGrouping.class); - assertThat(context).hasSingleBean(MetricsAndTracingObservationHandlerGrouping.class); + assertThat(context).hasBean("metricsAndTracingObservationHandlerGrouping"); }); }