forked from spring-projects/spring-boot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add auto-configuration for Micrometer 2.0.0 Observation API
- Adds a ObservationRegistry bean - Add support for ObservationRegistryCustomizers - Enables timer creation for observations if micrometer-core is on the classpath - Registers ObservationPredicate, GlobalTagsProvider and ObservationHandler on the MeterRegistry - Applies grouping to the ObservationHandlers: MeterObservationHandler are added to a FirstMatchingCompositeObservationHandler - If micrometer-tracing is on the classpath, the TracingObservationHandler are added to a FirstMatchingCompositeObservationHandler See spring-projectsgh-29666
- Loading branch information
1 parent
47eb630
commit aeab402
Showing
17 changed files
with
1,170 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
...amework/boot/actuate/autoconfigure/observation/HandlersObservationRegistryCustomizer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* 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.List; | ||
import java.util.Map; | ||
import java.util.TreeMap; | ||
|
||
import io.micrometer.observation.ObservationHandler; | ||
import io.micrometer.observation.ObservationHandler.FirstMatchingCompositeObservationHandler; | ||
import io.micrometer.observation.ObservationRegistry; | ||
|
||
/** | ||
* Installs {@link ObservationHandler} into an {@link ObservationRegistry}. | ||
* | ||
* Uses an {@link ObservationHandlerGrouping} strategy to group the handlers. All handlers | ||
* which belong to a group are added with their group members into a | ||
* {@link FirstMatchingCompositeObservationHandler}. All handlers without a group are | ||
* added directly to the {@link ObservationRegistry}. The group numbers are ordered | ||
* ascending, meaning lower numbers are added first to the {@link ObservationRegistry}. | ||
* | ||
* @author Moritz Halbritter | ||
*/ | ||
class HandlersObservationRegistryCustomizer implements ObservationRegistryCustomizer<ObservationRegistry> { | ||
|
||
private final List<ObservationHandler<?>> observationHandlers; | ||
|
||
private final ObservationHandlerGrouping observationHandlerGrouping; | ||
|
||
HandlersObservationRegistryCustomizer(List<ObservationHandler<?>> observationHandlers, | ||
ObservationHandlerGrouping observationHandlerGrouping) { | ||
this.observationHandlers = observationHandlers; | ||
this.observationHandlerGrouping = observationHandlerGrouping; | ||
} | ||
|
||
@Override | ||
public void customize(ObservationRegistry registry) { | ||
Map<Integer, List<ObservationHandler<?>>> groupedHandlers = new TreeMap<>(); | ||
for (ObservationHandler<?> observationHandler : this.observationHandlers) { | ||
Integer group = this.observationHandlerGrouping.getGroup(observationHandler); | ||
if (group == null) { | ||
registry.observationConfig().observationHandler(observationHandler); | ||
} | ||
else { | ||
groupedHandlers.computeIfAbsent(group, (ignored) -> new ArrayList<>()).add(observationHandler); | ||
} | ||
} | ||
for (List<ObservationHandler<?>> handlers : groupedHandlers.values()) { | ||
registry.observationConfig() | ||
.observationHandler(new FirstMatchingCompositeObservationHandler(castToRawType(handlers))); | ||
} | ||
} | ||
|
||
@SuppressWarnings({ "unchecked", "rawtypes" }) | ||
private List<ObservationHandler> castToRawType(List<ObservationHandler<?>> handlers) { | ||
// See https://github.com/micrometer-metrics/micrometer/issues/3064 | ||
return (List) handlers; | ||
} | ||
|
||
} |
40 changes: 40 additions & 0 deletions
40
...framework/boot/actuate/autoconfigure/observation/NoTracingObservationHandlerGrouping.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* 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 io.micrometer.core.instrument.observation.MeterObservationHandler; | ||
import io.micrometer.observation.ObservationHandler; | ||
|
||
/** | ||
* {@link ObservationHandler} grouping used by {@link ObservationAutoConfiguration} if | ||
* micrometer-tracing is not on the classpath. | ||
* | ||
* @author Moritz Halbritter | ||
*/ | ||
class NoTracingObservationHandlerGrouping implements ObservationHandlerGrouping { | ||
|
||
private static final int METER_OBSERVATION_HANDLER_GROUP = 1; | ||
|
||
@Override | ||
public Integer getGroup(ObservationHandler<?> observationHandler) { | ||
if (observationHandler instanceof MeterObservationHandler) { | ||
return METER_OBSERVATION_HANDLER_GROUP; | ||
} | ||
return null; | ||
} | ||
|
||
} |
105 changes: 105 additions & 0 deletions
105
.../springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* 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.List; | ||
|
||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.observation.Observation.GlobalTagsProvider; | ||
import io.micrometer.observation.ObservationHandler; | ||
import io.micrometer.observation.ObservationPredicate; | ||
import io.micrometer.observation.ObservationRegistry; | ||
import io.micrometer.tracing.handler.TracingObservationHandler; | ||
|
||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; | ||
import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
/** | ||
* {@link EnableAutoConfiguration Auto-configuration} for the Micrometer Observation API. | ||
* | ||
* @author Moritz Halbritter | ||
* @since 3.0.0 | ||
*/ | ||
@AutoConfiguration(after = CompositeMeterRegistryAutoConfiguration.class) | ||
@ConditionalOnClass(ObservationRegistry.class) | ||
public class ObservationAutoConfiguration { | ||
|
||
@Bean | ||
static ObservationRegistryPostProcessor observationRegistryPostProcessor( | ||
ObjectProvider<ObservationRegistryCustomizer<?>> observationRegistryCustomizers, | ||
ObjectProvider<ObservationPredicate> observationPredicates, | ||
ObjectProvider<GlobalTagsProvider<?>> tagProviders) { | ||
return new ObservationRegistryPostProcessor(observationRegistryCustomizers, observationPredicates, | ||
tagProviders); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
ObservationRegistry observationRegistry() { | ||
return ObservationRegistry.create(); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
HandlersObservationRegistryCustomizer handlersObservationRegistryCustomizer( | ||
List<ObservationHandler<?>> observationHandlers, ObservationHandlerGrouping observationHandlerGrouping) { | ||
return new HandlersObservationRegistryCustomizer(observationHandlers, observationHandlerGrouping); | ||
} | ||
|
||
@Configuration(proxyBeanMethods = false) | ||
@ConditionalOnBean(MeterRegistry.class) | ||
static class MetricsConfiguration { | ||
|
||
@Bean | ||
TimerObservationHandlerObservationRegistryCustomizer enableTimerObservationHandler( | ||
MeterRegistry meterRegistry) { | ||
return new TimerObservationHandlerObservationRegistryCustomizer(meterRegistry); | ||
} | ||
|
||
} | ||
|
||
@Configuration(proxyBeanMethods = false) | ||
@ConditionalOnMissingClass("io.micrometer.tracing.handler.TracingObservationHandler") | ||
static class NoTracingConfiguration { | ||
|
||
@Bean | ||
ObservationHandlerGrouping noTracingObservationHandlerGrouping() { | ||
return new NoTracingObservationHandlerGrouping(); | ||
} | ||
|
||
} | ||
|
||
@Configuration(proxyBeanMethods = false) | ||
@ConditionalOnClass(TracingObservationHandler.class) | ||
static class TracingConfiguration { | ||
|
||
@Bean | ||
ObservationHandlerGrouping tracingObservationHandlerGrouping() { | ||
return new TracingObservationHandlerGrouping(); | ||
} | ||
|
||
} | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
...rg/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* 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 io.micrometer.observation.ObservationHandler; | ||
|
||
/** | ||
* Strategy to get the group for an {@link ObservationHandler}. | ||
* | ||
* @author Moritz Halbritter | ||
* @since 3.0.0 | ||
*/ | ||
public interface ObservationHandlerGrouping { | ||
|
||
/** | ||
* Returns the group number of the given {@code observationHandler}. If {@code null} | ||
* is returned, the {@link ObservationHandler} doesn't belong to any group. | ||
* @param observationHandler the observation handler to get the group for | ||
* @return group number or {@code null} if the handler doesn't belong to any group | ||
*/ | ||
Integer getGroup(ObservationHandler<?> observationHandler); | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
...springframework/boot/actuate/autoconfigure/observation/ObservationRegistryConfigurer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* 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.List; | ||
|
||
import io.micrometer.observation.Observation.GlobalTagsProvider; | ||
import io.micrometer.observation.ObservationPredicate; | ||
import io.micrometer.observation.ObservationRegistry; | ||
|
||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.boot.util.LambdaSafe; | ||
|
||
/** | ||
* Configurer to apply {@link ObservationRegistryCustomizer customizers} to | ||
* {@link ObservationRegistry observation registries}. Installs | ||
* {@link ObservationPredicate observation predicates} and {@link GlobalTagsProvider | ||
* global tag providers} into the {@link ObservationRegistry}. | ||
* | ||
* @author Moritz Halbritter | ||
*/ | ||
class ObservationRegistryConfigurer { | ||
|
||
private final ObjectProvider<ObservationRegistryCustomizer<?>> customizers; | ||
|
||
private final ObjectProvider<ObservationPredicate> observationPredicates; | ||
|
||
private final ObjectProvider<GlobalTagsProvider<?>> tagProviders; | ||
|
||
ObservationRegistryConfigurer(ObjectProvider<ObservationRegistryCustomizer<?>> customizers, | ||
ObjectProvider<ObservationPredicate> observationPredicates, | ||
ObjectProvider<GlobalTagsProvider<?>> tagProviders) { | ||
this.customizers = customizers; | ||
this.observationPredicates = observationPredicates; | ||
this.tagProviders = tagProviders; | ||
} | ||
|
||
void configure(ObservationRegistry registry) { | ||
registerObservationPredicates(registry); | ||
registerGlobalTagsProvider(registry); | ||
customize(registry); | ||
} | ||
|
||
private void registerObservationPredicates(ObservationRegistry registry) { | ||
this.observationPredicates.orderedStream().forEach( | ||
(observationPredicate) -> registry.observationConfig().observationPredicate(observationPredicate)); | ||
} | ||
|
||
private void registerGlobalTagsProvider(ObservationRegistry registry) { | ||
this.tagProviders.orderedStream() | ||
.forEach((tagProvider) -> registry.observationConfig().tagsProvider(tagProvider)); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private void customize(ObservationRegistry registry) { | ||
LambdaSafe.callbacks(ObservationRegistryCustomizer.class, asOrderedList(this.customizers), registry) | ||
.withLogger(ObservationRegistryConfigurer.class).invoke((customizer) -> customizer.customize(registry)); | ||
} | ||
|
||
private <T> List<T> asOrderedList(ObjectProvider<T> provider) { | ||
return provider.orderedStream().toList(); | ||
} | ||
|
||
} |
38 changes: 38 additions & 0 deletions
38
...springframework/boot/actuate/autoconfigure/observation/ObservationRegistryCustomizer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* 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 io.micrometer.observation.ObservationRegistry; | ||
|
||
/** | ||
* Callback interface that can be used to customize auto-configured | ||
* {@link ObservationRegistry ObservationRegistries}. | ||
* | ||
* @param <T> the registry type to customize | ||
* @author Moritz Halbritter | ||
* @since 3.0.0 | ||
*/ | ||
@FunctionalInterface | ||
public interface ObservationRegistryCustomizer<T extends ObservationRegistry> { | ||
|
||
/** | ||
* Customize the given {@code registry}. | ||
* @param registry the registry to customize | ||
*/ | ||
void customize(T registry); | ||
|
||
} |
Oops, something went wrong.