WIP. Current code works with tracing 1.5.0 - leaving this for future reference

This commit is contained in:
Marcin Grzejszczak
2024-11-14 16:52:07 +01:00
parent e84ca0df72
commit 52dcb593c6
13 changed files with 227 additions and 85 deletions

10
pom.xml
View File

@@ -47,6 +47,8 @@
<spring-framework.version>6.2.0-RC3</spring-framework.version> <!-- For Javadoc links only -->
<spring-cloud-aws-bom.version>3.1.1</spring-cloud-aws-bom.version>
<testcontainers.version>1.17.6</testcontainers.version>
<!-- TODO: For snapshots -->
<micrometer-tracing.version>1.5.0-SNAPSHOT</micrometer-tracing.version>
</properties>
@@ -96,6 +98,14 @@ limitations under the License.
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- TODO: For snapshots -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>${micrometer-tracing.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>

View File

@@ -3,35 +3,48 @@ package org.springframework.modulith.observability;
import java.lang.reflect.Method;
import io.micrometer.common.KeyValues;
import org.springframework.modulith.observability.ModulithObservations.HighKeys;
import org.springframework.modulith.observability.ModulithObservations.LowKeys;
/**
* Default implementation of {@link ModulithObservationConvention}.
*
* @author Marcin Grzejszczak
* @since 1.3
*/
public class DefaultModulithObservationConvention implements ModulithObservationConvention {
@Override
public KeyValues getLowCardinalityKeyValues(ModulithContext context) {
ObservedModule currentModule = context.getModule();
if (currentModule != null) {
return KeyValues.of(LowKeys.MODULE_KEY.withValue(currentModule.getName()));
}
return KeyValues.empty();
}
@Override
public KeyValues getLowCardinalityKeyValues(ModulithContext context) {
KeyValues keyValues = KeyValues.of(LowKeys.MODULE_KEY.withValue(context.getModule().getIdentifier().toString()));
if (isEventListener(context)) {
return keyValues.and(LowKeys.INVOCATION_TYPE.withValue("event-listener"));
}
return keyValues;
}
@Override
public KeyValues getHighCardinalityKeyValues(ModulithContext context) {
Method method = context.getInvocation().getMethod();
return KeyValues.of(HighKeys.MODULE_METHOD.withValue(method.getName()));
}
private boolean isEventListener(ModulithContext context) {
try {
return context.getModule().isEventListenerInvocation(context.getInvocation());
} catch (Exception e) {
return false;
}
}
@Override
public String getName() {
return "module.requests";
}
@Override
public KeyValues getHighCardinalityKeyValues(ModulithContext context) {
Method method = context.getInvocation().getMethod();
return KeyValues.of(HighKeys.MODULE_METHOD.withValue(method.getName()));
}
@Override
public String getContextualName(ModulithContext context) {
// TODO: Change this to application name
return "[" + context.getModule().getDisplayName() + "] " + context.getModule()
.getDisplayName();
}
@Override
public String getName() {
return "module.requests";
}
@Override
public String getContextualName(ModulithContext context) {
return "[" + context.getApplicationName() + "] " + context.getModule().getDisplayName();
}
}

View File

@@ -0,0 +1,24 @@
package org.springframework.modulith.observability;
import io.micrometer.tracing.exporter.FinishedSpan;
import io.micrometer.tracing.exporter.SpanFilter;
/**
* {@link SpanFilter} that sets a local service name according
* to the current module's name.
*
* @author Marcin Grzejszczak
* @since 1.3
*/
public class LocalServiceRenamingSpanFilter implements SpanFilter {
@Override
public FinishedSpan map(FinishedSpan span) {
String moduleKey = span.getTags().get(ModulithObservations.LowKeys.MODULE_KEY.asString());
if (moduleKey != null) {
// Wait for tracing 1.5.0
span.setLocalServiceName(moduleKey);
}
return span;
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.modulith.observability;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
@@ -26,32 +27,34 @@ import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.lang.Nullable;
import org.springframework.modulith.core.ApplicationModuleIdentifier;
import org.springframework.modulith.observability.ModulithObservations.LowKeys;
import org.springframework.util.Assert;
class ModuleEntryInterceptor implements MethodInterceptor {
private static Logger LOGGER = LoggerFactory.getLogger(ModuleEntryInterceptor.class);
private static Map<String, ModuleEntryInterceptor> CACHE = new HashMap<>();
private static final String MODULE_KEY = ModuleTracingBeanPostProcessor.MODULE_BAGGAGE_KEY;
private static Map<ApplicationModuleIdentifier, ModuleEntryInterceptor> CACHE = new HashMap<>();
private static final ModulithObservationConvention DEFAULT = new DefaultModulithObservationConvention();
private final ObservedModule module;
private final ObservationRegistry observationRegistry;
@Nullable private final ModulithObservationConvention customModulithObservationConvention;
@Nullable
private final ModulithObservationConvention customModulithObservationConvention;
private final Environment environment;
/**
* Creates a new {@link ModuleEntryInterceptor} for the given {@link ObservedModule} and {@link ObservationRegistry}.
*
* @param module must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
private ModuleEntryInterceptor(ObservedModule module, ObservationRegistry observationRegistry) {
this(module, observationRegistry, null);
private ModuleEntryInterceptor(ObservedModule module, ObservationRegistry observationRegistry, Environment environment) {
this(module, observationRegistry, null, environment);
}
/**
@@ -61,26 +64,29 @@ class ModuleEntryInterceptor implements MethodInterceptor {
* @param module must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
* @param custom must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
private ModuleEntryInterceptor(ObservedModule module, ObservationRegistry observationRegistry,
ModulithObservationConvention custom) {
ModulithObservationConvention custom, Environment environment) {
Assert.notNull(module, "ObservedModule must not be null!");
Assert.notNull(observationRegistry, "Tracer must not be null!");
this.module = module; this.observationRegistry = observationRegistry;
this.customModulithObservationConvention = custom;
}
public static ModuleEntryInterceptor of(ObservedModule module, ObservationRegistry observationRegistry) {
return of(module, observationRegistry, null);
this.environment = environment;
}
public static ModuleEntryInterceptor of(ObservedModule module, ObservationRegistry observationRegistry,
ModulithObservationConvention custom) {
Environment environment) {
return of(module, observationRegistry, null, environment);
}
return CACHE.computeIfAbsent(module.getName(), __ -> {
return new ModuleEntryInterceptor(module, observationRegistry, custom);
public static ModuleEntryInterceptor of(ObservedModule module, ObservationRegistry observationRegistry,
ModulithObservationConvention custom, Environment environment) {
return CACHE.computeIfAbsent(module.getIdentifier(), __ -> {
return new ModuleEntryInterceptor(module, observationRegistry, custom, environment);
});
}
@@ -88,18 +94,19 @@ class ModuleEntryInterceptor implements MethodInterceptor {
* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@Override public Object invoke(MethodInvocation invocation) throws Throwable {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
var moduleName = module.getName();
var moduleIdentifier = module.getIdentifier();
var currentObservation = observationRegistry.getCurrentObservation();
String currentModule = null;
if (currentObservation != null) {
KeyValue moduleKey = currentObservation.getContextView().getLowCardinalityKeyValue(MODULE_KEY);
KeyValue moduleKey = currentObservation.getContextView().getLowCardinalityKeyValue(LowKeys.MODULE_KEY.asString());
currentModule = moduleKey != null ? moduleKey.getValue() : null;
}
if (currentObservation != null && moduleName.equals(currentModule)) {
if (currentObservation != null && Objects.equals(moduleIdentifier.toString(), currentModule)) {
// Same module
return invocation.proceed();
}
@@ -108,18 +115,18 @@ class ModuleEntryInterceptor implements MethodInterceptor {
LOGGER.trace("Entering {} via {}.", module.getDisplayName(), invokedMethod);
boolean isEventListener = module.isEventListenerInvocation(invocation);
// TODO: Good name for metrics
ModulithContext modulithContext = new ModulithContext(module, invocation);
ModulithContext modulithContext = new ModulithContext(module, invocation, environment);
var observation = Observation.createNotStarted(customModulithObservationConvention, DEFAULT,
() -> modulithContext, observationRegistry); if (isEventListener) {
observation.lowCardinalityKeyValue(LowKeys.INVOCATION_TYPE.withValue("event-listener"));
} try (Observation.Scope scope = observation.openScope()) {
Object proceed = invocation.proceed(); observation.event(ModulithObservations.Events.EVENT_PUBLICATION_SUCCESS);
() -> modulithContext, observationRegistry);
try (Observation.Scope scope = observation.start().openScope()) {
Object proceed = invocation.proceed();
observation.event(ModulithObservations.Events.EVENT_PUBLICATION_SUCCESS);
return proceed;
} catch (Exception ex) {
observation.error(ex); observation.event(ModulithObservations.Events.EVENT_PUBLICATION_FAILURE); throw ex;
observation.error(ex);
observation.event(ModulithObservations.Events.EVENT_PUBLICATION_FAILURE);
throw ex;
} finally {
LOGGER.trace("Leaving {}", module.getDisplayName()); observation.stop();
}

View File

@@ -34,6 +34,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
import org.springframework.util.Assert;
@@ -43,7 +44,7 @@ import org.springframework.util.Assert;
*
* @author Oliver Drotbohm
*/
public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport implements BeanPostProcessor {
public class ModuleObservabilityBeanPostProcessor extends ModuleObservabilitySupport implements BeanPostProcessor {
public static final String MODULE_BAGGAGE_KEY = "org.springframework.modulith.module";
@@ -51,24 +52,26 @@ public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport impleme
private final Supplier<ObservationRegistry> observationRegistry;
private final Map<String, Advisor> advisors;
private final ConfigurableListableBeanFactory factory;
private final Environment environment;
/**
* Creates a new {@link ModuleTracingBeanPostProcessor} for the given {@link ApplicationModulesRuntime} and
* Creates a new {@link ModuleObservabilityBeanPostProcessor} for the given {@link ApplicationModulesRuntime} and
* {@link Tracer}.
*
* @param runtime must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
*/
public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry,
ConfigurableListableBeanFactory factory) {
public ModuleObservabilityBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry,
ConfigurableListableBeanFactory factory, Environment environment) {
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
Assert.notNull(observationRegistry, "Tracer must not be null!");
Assert.notNull(observationRegistry, "ObservationRegistry must not be null!");
this.runtime = runtime;
this.observationRegistry = observationRegistry;
this.advisors = new HashMap<>();
this.factory = factory;
this.environment = environment;
}
/*
@@ -120,8 +123,8 @@ public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport impleme
private Advisor getOrBuildAdvisor(ObservedModule module, ObservedModuleType type) {
return advisors.computeIfAbsent(module.getName(), __ -> {
return new ApplicationModuleObservingAdvisor(type, ModuleEntryInterceptor.of(module, observationRegistry.get()));
return advisors.computeIfAbsent(module.getIdentifier().toString(), __ -> {
return new ApplicationModuleObservingAdvisor(type, ModuleEntryInterceptor.of(module, observationRegistry.get(), environment));
});
}

View File

@@ -26,7 +26,7 @@ import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
/**
* @author Oliver Drotbohm
*/
class ModuleTracingSupport implements BeanClassLoaderAware {
class ModuleObservabilitySupport implements BeanClassLoaderAware {
private ClassLoader classLoader;

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2022-2024 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.modulith.observability;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationFilter;
/**
* Ensures that {@link ModulithObservations.LowKeys#MODULE_KEY} gets propagated from parent
* to child.
*
* @author Marcin Grzejszczak
* @since 1.3
*/
public class ModulePassingObservationFilter implements ObservationFilter {
@Override
public Observation.Context map(Observation.Context context) {
if (isModuleKeyValueAbsentInCurrent(context) && isModuleKeyValuePresentInParent(context)) {
return context.addLowCardinalityKeyValue(ModulithObservations.LowKeys.MODULE_KEY.withValue(context.getParentObservation().getContextView().getLowCardinalityKeyValue(ModulithObservations.LowKeys.MODULE_KEY.asString()).getValue()));
}
return context;
}
private static boolean isModuleKeyValueAbsentInCurrent(Observation.ContextView context) {
return context.getLowCardinalityKeyValue(ModulithObservations.LowKeys.MODULE_KEY.asString()) == null;
}
private static boolean isModuleKeyValuePresentInParent(Observation.ContextView context) {
return context.getParentObservation() != null && context.getParentObservation().getContextView().getLowCardinalityKeyValue(ModulithObservations.LowKeys.MODULE_KEY.asString()) != null;
}
}

View File

@@ -3,6 +3,8 @@ package org.springframework.modulith.observability;
import io.micrometer.observation.Observation;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.env.Environment;
/**
* A {@link Observation.Context} for Modulithic applications.
*
@@ -15,9 +17,12 @@ public class ModulithContext extends Observation.Context {
private final MethodInvocation invocation;
public ModulithContext(ObservedModule module, MethodInvocation invocation) {
private final String applicationName;
public ModulithContext(ObservedModule module, MethodInvocation invocation, Environment environment) {
this.module = module;
this.invocation = invocation;
this.applicationName = environment.getProperty("spring.application.name");
}
public ObservedModule getModule() {
@@ -27,4 +32,8 @@ public class ModulithContext extends Observation.Context {
public MethodInvocation getInvocation() {
return invocation;
}
public String getApplicationName() {
return applicationName;
}
}

View File

@@ -28,6 +28,7 @@ import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.env.Environment;
import org.springframework.data.rest.webmvc.BasePathAwareController;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.modulith.core.ApplicationModule;
@@ -38,25 +39,28 @@ import org.springframework.util.Assert;
/**
* @author Oliver Drotbohm
*/
public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingSupport implements BeanPostProcessor {
public class SpringDataRestModuleObservabilityBeanPostProcessor extends ModuleObservabilitySupport implements BeanPostProcessor {
private final ApplicationModulesRuntime runtime;
private final Supplier<ObservationRegistry> observationRegistry;
private final Environment environment;
/**
* Creates a new {@link SpringDataRestModuleTracingBeanPostProcessor} for the given {@link ApplicationModulesRuntime}
* Creates a new {@link SpringDataRestModuleObservabilityBeanPostProcessor} for the given {@link ApplicationModulesRuntime}
* and {@link Tracer}.
*
* @param runtime must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
public SpringDataRestModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry) {
public SpringDataRestModuleObservabilityBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry, Environment environment) {
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
Assert.notNull(observationRegistry, "ObservationRegistry must not be null!");
this.runtime = runtime;
this.observationRegistry = observationRegistry;
this.environment = environment;
}
/*
@@ -72,7 +76,7 @@ public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingS
return bean;
}
Advice interceptor = new DataRestControllerInterceptor(runtime, observationRegistry);
Advice interceptor = new DataRestControllerInterceptor(runtime, observationRegistry, environment);
Advisor advisor = new DefaultPointcutAdvisor(interceptor);
return addAdvisor(bean, advisor, it -> it.setProxyTargetClass(true));
@@ -82,20 +86,25 @@ public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingS
private final Supplier<ApplicationModules> modules;
private final Supplier<ObservationRegistry> observationRegistry;
private final Environment environment;
/**
* Creates a new {@link DataRestControllerInterceptor} for the given {@link ApplicationModules} and {@link Tracer}.
*
* @param modules must not be {@literal null}.
* @param modules must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
private DataRestControllerInterceptor(Supplier<ApplicationModules> modules, Supplier<ObservationRegistry> observationRegistry) {
private DataRestControllerInterceptor(Supplier<ApplicationModules> modules, Supplier<ObservationRegistry> observationRegistry,
Environment environment) {
Assert.notNull(modules, "ApplicationModules must not be null!");
Assert.notNull(observationRegistry, "Tracer must not be null!");
Assert.notNull(observationRegistry, "ObservationRegistry must not be null!");
Assert.notNull(environment, "Environment must not be null!");
this.modules = modules;
this.observationRegistry = observationRegistry;
this.environment = environment;
}
/*
@@ -113,7 +122,7 @@ public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingS
var observed = new DefaultObservedModule(module);
return ModuleEntryInterceptor.of(observed, observationRegistry.get()).invoke(invocation);
return ModuleEntryInterceptor.of(observed, observationRegistry.get(), environment).invoke(invocation);
}
private ApplicationModule getModuleFrom(Object[] arguments) {

View File

@@ -15,10 +15,15 @@
*/
package org.springframework.modulith.observability.autoconfigure;
import io.micrometer.common.KeyValue;
import io.micrometer.observation.ObservationFilter;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.exporter.SpanFilter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
import org.springframework.boot.autoconfigure.thread.Threading;
@@ -26,9 +31,12 @@ import org.springframework.boot.task.SimpleAsyncTaskExecutorCustomizer;
import org.springframework.boot.task.ThreadPoolTaskExecutorCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.task.support.ContextPropagatingTaskDecorator;
import org.springframework.modulith.observability.LocalServiceRenamingSpanFilter;
import org.springframework.modulith.observability.ModuleEventListener;
import org.springframework.modulith.observability.ModuleTracingBeanPostProcessor;
import org.springframework.modulith.observability.ModuleObservabilityBeanPostProcessor;
import org.springframework.modulith.observability.ModulePassingObservationFilter;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
/**
@@ -39,9 +47,9 @@ import org.springframework.modulith.runtime.ApplicationModulesRuntime;
class ModuleObservabilityAutoConfiguration {
@Bean
static ModuleTracingBeanPostProcessor moduleTracingBeanPostProcessor(ApplicationModulesRuntime runtime,
ObjectProvider<ObservationRegistry> observationRegistry, ConfigurableListableBeanFactory factory) {
return new ModuleTracingBeanPostProcessor(runtime, observationRegistry::getObject, factory);
static ModuleObservabilityBeanPostProcessor moduleTracingBeanPostProcessor(ApplicationModulesRuntime runtime,
ObjectProvider<ObservationRegistry> observationRegistry, ConfigurableListableBeanFactory factory, Environment environment) {
return new ModuleObservabilityBeanPostProcessor(runtime, observationRegistry::getObject, factory, environment);
}
@Bean
@@ -62,4 +70,20 @@ class ModuleObservabilityAutoConfiguration {
ThreadPoolTaskExecutorCustomizer threadPoolTaskExecutorCustomizer() {
return executor -> executor.setTaskDecorator(new ContextPropagatingTaskDecorator());
}
@Bean
ObservationFilter modulePassingObservationFilter() {
return new ModulePassingObservationFilter();
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Tracer.class)
static class MicrometerTracingConfiguration {
@Bean
SpanFilter localSpanFilter() {
return new LocalServiceRenamingSpanFilter();
}
}
}

View File

@@ -16,14 +16,14 @@
package org.springframework.modulith.observability.autoconfigure;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.rest.webmvc.RepositoryController;
import org.springframework.modulith.observability.SpringDataRestModuleTracingBeanPostProcessor;
import org.springframework.modulith.observability.SpringDataRestModuleObservabilityBeanPostProcessor;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
/**
@@ -34,9 +34,9 @@ import org.springframework.modulith.runtime.ApplicationModulesRuntime;
class SpringDataRestModuleObservabilityAutoConfiguration {
@Bean
static SpringDataRestModuleTracingBeanPostProcessor springDataRestModuleTracingBeanPostProcessor(
ApplicationModulesRuntime runtime, ObjectProvider<ObservationRegistry> observationRegistry) {
static SpringDataRestModuleObservabilityBeanPostProcessor springDataRestModuleTracingBeanPostProcessor(
ApplicationModulesRuntime runtime, ObjectProvider<ObservationRegistry> observationRegistry, Environment environment) {
return new SpringDataRestModuleTracingBeanPostProcessor(runtime, () -> observationRegistry.getObject());
return new SpringDataRestModuleObservabilityBeanPostProcessor(runtime, () -> observationRegistry.getObject(), environment);
}
}

View File

@@ -16,12 +16,10 @@
package org.springframework.modulith.observability;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import example.ExampleApplication;
import example.sample.SampleComponent;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import org.junit.jupiter.api.Test;
import org.springframework.aop.Advisor;
@@ -30,14 +28,14 @@ import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.modulith.observability.ModuleTracingBeanPostProcessor.ApplicationModuleObservingAdvisor;
import org.springframework.modulith.observability.ModuleObservabilityBeanPostProcessor.ApplicationModuleObservingAdvisor;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
import org.springframework.modulith.runtime.ApplicationRuntime;
import org.springframework.modulith.test.TestApplicationModules;
import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
/**
* Integration tests for {@link ModuleTracingBeanPostProcessor}.
* Integration tests for {@link ModuleObservabilityBeanPostProcessor}.
*
* @author Oliver Drotbohm
*/
@@ -64,14 +62,13 @@ class ModuleTracingBeanPostProcessorIntegrationTests {
@Configuration
static class ModuleTracingConfiguration {
@Bean
ModuleTracingBeanPostProcessor foo(ConfigurableApplicationContext context) {
@Bean ModuleObservabilityBeanPostProcessor foo(ConfigurableApplicationContext context) {
var runtime = ApplicationRuntime.of(context);
var modulesRuntime = new ApplicationModulesRuntime(() -> TestApplicationModules.of(ExampleApplication.class),
runtime);
return new ModuleTracingBeanPostProcessor(modulesRuntime, () -> ObservationRegistry.NOOP, context.getBeanFactory());
return new ModuleObservabilityBeanPostProcessor(modulesRuntime, () -> ObservationRegistry.NOOP, context.getBeanFactory(), context.getEnvironment());
}
}

View File

@@ -24,10 +24,11 @@ import example.sample.SampleProperties;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
/**
* Unit tests for {@link ModuleTracingBeanPostProcessor}.
* Unit tests for {@link ModuleObservabilityBeanPostProcessor}.
*
* @author Oliver Drotbohm
*/
@@ -43,7 +44,7 @@ class ModuleTracingBeanPostProcessorUnitTests {
doReturn(SampleProperties.class).when(mock).getUserClass(any(), any());
doReturn(true).when(mock).isApplicationClass(any());
var processor = new ModuleTracingBeanPostProcessor(mock, () -> null, beanFactory);
var processor = new ModuleObservabilityBeanPostProcessor(mock, () -> null, beanFactory, new MockEnvironment());
var bean = new SampleProperties();
var result = processor.postProcessAfterInitialization(bean, "properties");