-
Notifications
You must be signed in to change notification settings - Fork 40.6k
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 Closes gh-29666
- Loading branch information
1 parent
4a8901b
commit 5ab9112
Showing
17 changed files
with
1,102 additions
and
2 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
98 changes: 98 additions & 0 deletions
98
.../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,98 @@ | ||
/* | ||
* 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.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, | ||
ObjectProvider<ObservationHandler<?>> observationHandlers, | ||
ObjectProvider<ObservationHandlerGrouping> observationHandlerGrouping) { | ||
return new ObservationRegistryPostProcessor(observationRegistryCustomizers, observationPredicates, tagProviders, | ||
observationHandlers, observationHandlerGrouping); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
ObservationRegistry observationRegistry() { | ||
return ObservationRegistry.create(); | ||
} | ||
|
||
@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 OnlyMetricsObservationHandlerGrouping(); | ||
} | ||
|
||
} | ||
|
||
@Configuration(proxyBeanMethods = false) | ||
@ConditionalOnClass(TracingObservationHandler.class) | ||
static class TracingConfiguration { | ||
|
||
@Bean | ||
ObservationHandlerGrouping tracingObservationHandlerGrouping() { | ||
return new TracingObservationHandlerGrouping(); | ||
} | ||
|
||
} | ||
|
||
} |
39 changes: 39 additions & 0 deletions
39
...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,39 @@ | ||
/* | ||
* 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.Collection; | ||
|
||
import io.micrometer.observation.ObservationHandler; | ||
import io.micrometer.observation.ObservationRegistry.ObservationConfig; | ||
|
||
/** | ||
* Strategy to apply {@link ObservationHandler ObservationHandlers} to an | ||
* {@link ObservationConfig}. | ||
* | ||
* @author Moritz Halbritter | ||
*/ | ||
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<ObservationHandler<?>> handlers, ObservationConfig config); | ||
|
||
} |
95 changes: 95 additions & 0 deletions
95
...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,95 @@ | ||
/* | ||
* 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.ObservationHandler; | ||
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}. Also uses a | ||
* {@link ObservationHandlerGrouping} to group handlers, which are then added to the | ||
* {@link ObservationRegistry}. | ||
* | ||
* @author Moritz Halbritter | ||
*/ | ||
class ObservationRegistryConfigurer { | ||
|
||
private final ObjectProvider<ObservationRegistryCustomizer<?>> customizers; | ||
|
||
private final ObjectProvider<ObservationPredicate> observationPredicates; | ||
|
||
private final ObjectProvider<GlobalTagsProvider<?>> tagProviders; | ||
|
||
private final ObjectProvider<ObservationHandler<?>> observationHandlers; | ||
|
||
private final ObjectProvider<ObservationHandlerGrouping> observationHandlerGrouping; | ||
|
||
ObservationRegistryConfigurer(ObjectProvider<ObservationRegistryCustomizer<?>> customizers, | ||
ObjectProvider<ObservationPredicate> observationPredicates, | ||
ObjectProvider<GlobalTagsProvider<?>> tagProviders, | ||
ObjectProvider<ObservationHandler<?>> observationHandlers, | ||
ObjectProvider<ObservationHandlerGrouping> observationHandlerGrouping) { | ||
this.customizers = customizers; | ||
this.observationPredicates = observationPredicates; | ||
this.tagProviders = tagProviders; | ||
this.observationHandlers = observationHandlers; | ||
this.observationHandlerGrouping = observationHandlerGrouping; | ||
} | ||
|
||
void configure(ObservationRegistry registry) { | ||
registerObservationPredicates(registry); | ||
registerGlobalTagsProvider(registry); | ||
registerHandlers(registry); | ||
customize(registry); | ||
} | ||
|
||
private void registerHandlers(ObservationRegistry registry) { | ||
this.observationHandlerGrouping.getObject().apply(asOrderedList(this.observationHandlers), | ||
registry.observationConfig()); | ||
} | ||
|
||
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 observation registries}. | ||
* | ||
* @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); | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
...ingframework/boot/actuate/autoconfigure/observation/ObservationRegistryPostProcessor.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 io.micrometer.observation.Observation.GlobalTagsProvider; | ||
import io.micrometer.observation.ObservationHandler; | ||
import io.micrometer.observation.ObservationPredicate; | ||
import io.micrometer.observation.ObservationRegistry; | ||
|
||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.beans.factory.config.BeanPostProcessor; | ||
|
||
/** | ||
* {@link BeanPostProcessor} that delegates to a lazily created | ||
* {@link ObservationRegistryConfigurer} to post-process {@link ObservationRegistry} | ||
* beans. | ||
* | ||
* @author Moritz Halbritter | ||
*/ | ||
class ObservationRegistryPostProcessor implements BeanPostProcessor { | ||
|
||
private final ObjectProvider<ObservationRegistryCustomizer<?>> observationRegistryCustomizers; | ||
|
||
private final ObjectProvider<ObservationPredicate> observationPredicates; | ||
|
||
private final ObjectProvider<GlobalTagsProvider<?>> tagProviders; | ||
|
||
private final ObjectProvider<ObservationHandler<?>> observationHandlers; | ||
|
||
private final ObjectProvider<ObservationHandlerGrouping> observationHandlerGrouping; | ||
|
||
private volatile ObservationRegistryConfigurer configurer; | ||
|
||
ObservationRegistryPostProcessor(ObjectProvider<ObservationRegistryCustomizer<?>> observationRegistryCustomizers, | ||
ObjectProvider<ObservationPredicate> observationPredicates, | ||
ObjectProvider<GlobalTagsProvider<?>> tagProviders, | ||
ObjectProvider<ObservationHandler<?>> observationHandlers, | ||
ObjectProvider<ObservationHandlerGrouping> observationHandlerGrouping) { | ||
this.observationRegistryCustomizers = observationRegistryCustomizers; | ||
this.observationPredicates = observationPredicates; | ||
this.tagProviders = tagProviders; | ||
this.observationHandlers = observationHandlers; | ||
this.observationHandlerGrouping = observationHandlerGrouping; | ||
} | ||
|
||
@Override | ||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { | ||
if (bean instanceof ObservationRegistry) { | ||
getConfigurer().configure((ObservationRegistry) bean); | ||
} | ||
return bean; | ||
} | ||
|
||
private ObservationRegistryConfigurer getConfigurer() { | ||
if (this.configurer == null) { | ||
this.configurer = new ObservationRegistryConfigurer(this.observationRegistryCustomizers, | ||
this.observationPredicates, this.tagProviders, this.observationHandlers, | ||
this.observationHandlerGrouping); | ||
} | ||
return this.configurer; | ||
} | ||
|
||
} |
Oops, something went wrong.