GH-928 - Polishing.

License headers, formatting, null checks.
This commit is contained in:
Oliver Drotbohm
2024-11-21 12:24:58 +01:00
parent 738ad3f14b
commit 3b608e9bc9
12 changed files with 336 additions and 98 deletions

View File

@@ -1,7 +1,20 @@
/*
* Copyright 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 java.lang.reflect.Method;
import io.micrometer.common.KeyValues;
import org.springframework.modulith.observability.ModulithObservations.HighKeys;
@@ -11,40 +24,62 @@ import org.springframework.modulith.observability.ModulithObservations.LowKeys;
* Default implementation of {@link ModulithObservationConvention}.
*
* @author Marcin Grzejszczak
* @author Oliver Drotbohm
* @since 1.4
*/
public class DefaultModulithObservationConvention implements ModulithObservationConvention {
class DefaultModulithObservationConvention implements ModulithObservationConvention {
/*
* (non-Javadoc)
* @see io.micrometer.observation.ObservationConvention#getLowCardinalityKeyValues(io.micrometer.observation.Observation.Context)
*/
@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;
var keyValues = KeyValues.of(LowKeys.MODULE_KEY.withValue(context.getModule().getIdentifier().toString()));
return isEventListener(context)
? keyValues.and(LowKeys.INVOCATION_TYPE.withValue("event-listener"))
: keyValues;
}
/*
*
* (non-Javadoc)
* @see io.micrometer.observation.ObservationConvention#getHighCardinalityKeyValues(io.micrometer.observation.Observation.Context)
*/
@Override
public KeyValues getHighCardinalityKeyValues(ModulithContext context) {
var method = context.getInvocation().getMethod();
return KeyValues.of(HighKeys.MODULE_METHOD.withValue(method.getName()));
}
/*
* (non-Javadoc)
* @see io.micrometer.observation.ObservationConvention#getName()
*/
@Override
public String getName() {
return "module.requests";
}
/*
* (non-Javadoc)
* @see io.micrometer.observation.ObservationConvention#getContextualName(io.micrometer.observation.Observation.Context)
*/
@Override
public String getContextualName(ModulithContext context) {
return "[" + context.getApplicationName() + "] " + context.getModule().getDisplayName();
}
private boolean isEventListener(ModulithContext context) {
try {
return context.getModule().isEventListenerInvocation(context.getInvocation());
} catch (Exception e) {
return false;
}
}
@Override
public KeyValues getHighCardinalityKeyValues(ModulithContext context) {
Method method = context.getInvocation().getMethod();
return KeyValues.of(HighKeys.MODULE_METHOD.withValue(method.getName()));
}
@Override
public String getName() {
return "module.requests";
}
@Override
public String getContextualName(ModulithContext context) {
return "[" + context.getApplicationName() + "] " + context.getModule().getDisplayName();
}
}

View File

@@ -25,7 +25,6 @@ import org.springframework.aop.support.AopUtils;
import org.springframework.modulith.core.ApplicationModule;
import org.springframework.modulith.core.ApplicationModuleIdentifier;
import org.springframework.modulith.core.ApplicationModules;
import org.springframework.modulith.core.ArchitecturallyEvidentType;
import org.springframework.modulith.core.ArchitecturallyEvidentType.ReferenceMethod;
import org.springframework.modulith.core.FormattableType;
import org.springframework.modulith.core.SpringBean;
@@ -163,7 +162,6 @@ class DefaultObservedModule implements ObservedModule {
var targetClass = advised.getTargetClass();
if (module.contains(targetClass)) {
return AopUtils.getMostSpecificMethod(method, targetClass);
}

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.modulith.observability;
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
import io.micrometer.observation.Observation.Scope;
import io.micrometer.observation.ObservationRegistry;
import java.util.HashMap;
@@ -33,16 +33,22 @@ import org.springframework.modulith.core.ApplicationModuleIdentifier;
import org.springframework.modulith.observability.ModulithObservations.LowKeys;
import org.springframework.util.Assert;
/**
* {@link MethodInterceptor} to create {@link Observation}s.
*
* @author Marcin Grzejszczak
* @author Oliver Drotbohm
*/
class ModuleEntryInterceptor implements MethodInterceptor {
private static Logger LOGGER = LoggerFactory.getLogger(ModuleEntryInterceptor.class);
private static final Logger LOGGER = LoggerFactory.getLogger(ModuleEntryInterceptor.class);
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;
private final @Nullable ModulithObservationConvention customModulithObservationConvention;
private final Environment environment;
/**
@@ -103,7 +109,8 @@ class ModuleEntryInterceptor implements MethodInterceptor {
String currentModule = null;
if (currentObservation != null) {
KeyValue moduleKey = currentObservation.getContextView().getLowCardinalityKeyValue(LowKeys.MODULE_KEY.asString());
var moduleKey = currentObservation.getContextView().getLowCardinalityKeyValue(LowKeys.MODULE_KEY.asString());
currentModule = moduleKey != null ? moduleKey.getValue() : null;
}
@@ -116,18 +123,26 @@ class ModuleEntryInterceptor implements MethodInterceptor {
LOGGER.trace("Entering {} via {}.", module.getDisplayName(), invokedMethod);
ModulithContext modulithContext = new ModulithContext(module, invocation, environment);
var modulithContext = new ModulithContext(module, invocation, environment);
var observation = Observation.createNotStarted(customModulithObservationConvention, DEFAULT,
() -> modulithContext, observationRegistry);
try (Observation.Scope scope = observation.start().openScope()) {
Object proceed = invocation.proceed();
try (Scope scope = observation.start().openScope()) {
var 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;
} finally {
LOGGER.trace("Leaving {}", module.getDisplayName());
observation.stop();
}

View File

@@ -39,13 +39,15 @@ public class ModuleEventListener implements ApplicationListener<ApplicationEvent
private final Supplier<MeterRegistry> meterRegistry;
/**
* Creates a new {@link ModuleEventListener} for the given {@link ApplicationModulesRuntime} and {@link ObservationRegistry} and {@link MeterRegistry}.
* Creates a new {@link ModuleEventListener} for the given {@link ApplicationModulesRuntime} and
* {@link ObservationRegistry} and {@link MeterRegistry}.
*
* @param runtime must not be {@literal null}.
* @param observationRegistrySupplier must not be {@literal null}.
* @param meterRegistrySupplier must not be {@literal null}.
*/
public ModuleEventListener(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistrySupplier,
Supplier<MeterRegistry> meterRegistrySupplier) {
public ModuleEventListener(ApplicationModulesRuntime runtime,
Supplier<ObservationRegistry> observationRegistrySupplier, Supplier<MeterRegistry> meterRegistrySupplier) {
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
Assert.notNull(observationRegistrySupplier, "ObservationRegistry must not be null!");
@@ -82,8 +84,10 @@ public class ModuleEventListener implements ApplicationListener<ApplicationEvent
return;
}
MeterRegistry registry = meterRegistry.get();
var registry = meterRegistry.get();
if (registry != null) {
Counter.builder(ModulithMetrics.EVENTS.getName()) //
.tags(ModulithMetrics.LowKeys.EVENT_TYPE.name().toLowerCase(), event.getClass().getSimpleName()) //
.tags(ModulithMetrics.LowKeys.MODULE_NAME.name().toLowerCase(), moduleByType.getDisplayName()) //

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022-2024 the original author or authors.
* Copyright 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.
@@ -16,30 +16,46 @@
package org.springframework.modulith.observability;
import io.micrometer.observation.Observation;
import io.micrometer.observation.Observation.ContextView;
import io.micrometer.observation.ObservationFilter;
/**
* Ensures that {@link ModulithObservations.LowKeys#MODULE_KEY} gets propagated from parent
* to child.
*
* Ensures that {@link ModulithObservations.LowKeys#MODULE_KEY} gets propagated from parent to child.
*
* @author Marcin Grzejszczak
* @author Oliver Drotbohm
* @since 1.4
*/
public class ModulePassingObservationFilter implements ObservationFilter {
@Override
/*
* (non-Javadoc)
* @see io.micrometer.observation.ObservationFilter#map(io.micrometer.observation.Observation.Context)
*/
@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()));
var moduleKey = ModulithObservations.LowKeys.MODULE_KEY;
return context.addLowCardinalityKeyValue(moduleKey.withValue(context.getParentObservation().getContextView()
.getLowCardinalityKeyValue(moduleKey.asString()).getValue()));
}
return context;
}
private static boolean isModuleKeyValueAbsentInCurrent(Observation.ContextView context) {
private static boolean isModuleKeyValueAbsentInCurrent(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;
private static boolean isModuleKeyValuePresentInParent(ContextView context) {
var parentObservation = context.getParentObservation();
return parentObservation != null
&& parentObservation.getContextView()
.getLowCardinalityKeyValue(ModulithObservations.LowKeys.MODULE_KEY.asString()) != null;
}
}
}

View File

@@ -1,39 +1,67 @@
/*
* Copyright 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 org.aopalliance.intercept.MethodInvocation;
import io.micrometer.observation.Observation.Context;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
/**
* A {@link Observation.Context} for Modulithic applications.
* A {@link Context} for Modulithic applications.
*
* @author Marcin Grzejsczak
* @author Oliver Drotbohm
* @since 1.4
*/
public class ModulithContext extends Observation.Context {
public class ModulithContext extends Context {
private final ObservedModule module;
private final ObservedModule module;
private final MethodInvocation invocation;
private final String applicationName;
private final MethodInvocation invocation;
/**
* Creates a new {@link ModulithContext} for the given {@link ObservedModule}, {@link MethodInvocation} and
* {@link Environment}.
*
* @param module must not be {@literal null}.
* @param invocation must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
public ModulithContext(ObservedModule module, MethodInvocation invocation, Environment environment) {
private final String applicationName;
Assert.notNull(module, "ObservedModule must not be null!");
Assert.notNull(invocation, "MethodInvocation must not be null!");
Assert.notNull(environment, "Environment must not be null!");
public ModulithContext(ObservedModule module, MethodInvocation invocation, Environment environment) {
this.module = module;
this.invocation = invocation;
this.applicationName = environment.getProperty("spring.application.name");
}
this.module = module;
this.invocation = invocation;
this.applicationName = environment.getProperty("spring.application.name");
}
public ObservedModule getModule() {
return module;
}
public ObservedModule getModule() {
return module;
}
public MethodInvocation getInvocation() {
return invocation;
}
public MethodInvocation getInvocation() {
return invocation;
}
public String getApplicationName() {
return applicationName;
}
public String getApplicationName() {
return applicationName;
}
}

View File

@@ -1,25 +1,58 @@
/*
* Copyright 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.common.docs.KeyName;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.docs.MeterDocumentation;
/**
* @author Marcin Grzejszczak
* @author Oliver Drotbohm
* @since 1.4
*/
enum ModulithMetrics implements MeterDocumentation {
/**
* Counter for the events.
*/
EVENTS {
/*
* (non-Javadoc)
* @see io.micrometer.core.instrument.docs.MeterDocumentation#getName()
*/
@Override
public String getName() {
return "modulith.events.processed";
}
/*
* (non-Javadoc)
* @see io.micrometer.core.instrument.docs.MeterDocumentation#getType()
*/
@Override
public Meter.Type getType() {
return Meter.Type.COUNTER;
}
/*
* (non-Javadoc)
* @see io.micrometer.core.instrument.docs.MeterDocumentation#getKeyNames()
*/
@Override
public KeyName[] getKeyNames() {
return LowKeys.values();
@@ -31,6 +64,11 @@ enum ModulithMetrics implements MeterDocumentation {
* Type of the emitted event.
*/
EVENT_TYPE {
/*
* (non-Javadoc)
* @see io.micrometer.common.docs.KeyName#asString()
*/
@Override
public String asString() {
return "event.type";
@@ -41,6 +79,11 @@ enum ModulithMetrics implements MeterDocumentation {
* Name of the module.
*/
MODULE_NAME {
/*
* (non-Javadoc)
* @see io.micrometer.common.docs.KeyName#asString()
*/
@Override
public String asString() {
return "module.name";

View File

@@ -1,3 +1,18 @@
/*
* Copyright 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.Context;
@@ -11,8 +26,12 @@ import io.micrometer.observation.ObservationConvention;
*/
public interface ModulithObservationConvention extends ObservationConvention<ModulithContext> {
@Override
default boolean supportsContext(Context context) {
return context instanceof ModulithContext;
}
/*
* (non-Javadoc)
* @see io.micrometer.observation.ObservationConvention#supportsContext(io.micrometer.observation.Observation.Context)
*/
@Override
default boolean supportsContext(Context context) {
return context instanceof ModulithContext;
}
}

View File

@@ -1,8 +1,24 @@
/*
* Copyright 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.common.docs.KeyName;
import io.micrometer.observation.Observation;
import io.micrometer.observation.Observation.Context;
import io.micrometer.observation.Observation.Event;
import io.micrometer.observation.ObservationConvention;
import io.micrometer.observation.docs.ObservationDocumentation;
@@ -12,19 +28,40 @@ enum ModulithObservations implements ObservationDocumentation {
* Observation related to entering a module.
*/
MODULE_ENTRY {
@Override public Class<? extends ObservationConvention<? extends Context>> getDefaultConvention() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.docs.ObservationDocumentation#getDefaultConvention()
*/
@Override
public Class<? extends ObservationConvention<? extends Context>> getDefaultConvention() {
return DefaultModulithObservationConvention.class;
}
@Override public KeyName[] getLowCardinalityKeyNames() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.docs.ObservationDocumentation#getLowCardinalityKeyNames()
*/
@Override
public KeyName[] getLowCardinalityKeyNames() {
return LowKeys.values();
}
@Override public KeyName[] getHighCardinalityKeyNames() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.docs.ObservationDocumentation#getHighCardinalityKeyNames()
*/
@Override
public KeyName[] getHighCardinalityKeyNames() {
return HighKeys.values();
}
@Override public Observation.Event[] getEvents() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.docs.ObservationDocumentation#getEvents()
*/
@Override
public Observation.Event[] getEvents() {
return Events.values();
}
};
@@ -35,7 +72,13 @@ enum ModulithObservations implements ObservationDocumentation {
* Name of the module.
*/
MODULE_KEY {
@Override public String asString() {
/*
* (non-Javadoc)
* @see io.micrometer.common.docs.KeyName#asString()
*/
@Override
public String asString() {
return "module.key";
}
},
@@ -44,7 +87,13 @@ enum ModulithObservations implements ObservationDocumentation {
* Type of invocation (e.g. event listener).
*/
INVOCATION_TYPE {
@Override public String asString() {
/*
* (non-Javadoc)
* @see io.micrometer.common.docs.KeyName#asString()
*/
@Override
public String asString() {
return "module.invocation-type";
}
}
@@ -55,23 +104,35 @@ enum ModulithObservations implements ObservationDocumentation {
* Method executed on a module.
*/
MODULE_METHOD {
@Override public String asString() {
@Override
public String asString() {
return "module.method";
}
}
}
enum Events implements Observation.Event {
enum Events implements Event {
/**
* Published when an event is sent successfully.
*/
EVENT_PUBLICATION_SUCCESS {
@Override public String getName() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.Observation.Event#getName()
*/
@Override
public String getName() {
return "event.publication.success";
}
@Override public String getContextualName() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.Observation.Event#getContextualName()
*/
@Override
public String getContextualName() {
return getName();
}
},
@@ -80,11 +141,22 @@ enum ModulithObservations implements ObservationDocumentation {
* Published when an event is sent with a failure.
*/
EVENT_PUBLICATION_FAILURE {
@Override public String getName() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.Observation.Event#getName()
*/
@Override
public String getName() {
return "event.publication.failure";
}
@Override public String getContextualName() {
/*
* (non-Javadoc)
* @see io.micrometer.observation.Observation.Event#getContextualName()
*/
@Override
public String getContextualName() {
return getName();
}
}

View File

@@ -19,10 +19,8 @@ import io.micrometer.observation.ObservationRegistry;
import java.util.function.Supplier;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
@@ -30,6 +28,7 @@ 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.lang.Nullable;
import org.springframework.modulith.core.ApplicationModule;
import org.springframework.modulith.core.ApplicationModules;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
@@ -37,22 +36,25 @@ import org.springframework.util.Assert;
/**
* @author Oliver Drotbohm
* @author Marcin Grzejszczak
*/
public class SpringDataRestModuleObservabilityBeanPostProcessor extends ModuleObservabilitySupport 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 SpringDataRestModuleObservabilityBeanPostProcessor} for the given {@link ApplicationModulesRuntime}
* and {@link ObservationRegistry}.
* Creates a new {@link SpringDataRestModuleObservabilityBeanPostProcessor} for the given
* {@link ApplicationModulesRuntime} and {@link ObservationRegistry}.
*
* @param runtime must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
public SpringDataRestModuleObservabilityBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry, Environment environment) {
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!");
@@ -75,8 +77,8 @@ public class SpringDataRestModuleObservabilityBeanPostProcessor extends ModuleOb
return bean;
}
Advice interceptor = new DataRestControllerInterceptor(runtime, observationRegistry, environment);
Advisor advisor = new DefaultPointcutAdvisor(interceptor);
var interceptor = new DataRestControllerInterceptor(runtime, observationRegistry, environment);
var advisor = new DefaultPointcutAdvisor(interceptor);
return addAdvisor(bean, advisor, it -> it.setProxyTargetClass(true));
}
@@ -90,11 +92,12 @@ public class SpringDataRestModuleObservabilityBeanPostProcessor extends ModuleOb
/**
* 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}.
* @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!");
@@ -124,6 +127,7 @@ public class SpringDataRestModuleObservabilityBeanPostProcessor extends ModuleOb
return ModuleEntryInterceptor.of(observed, observationRegistry.get(), environment).invoke(invocation);
}
@Nullable
private ApplicationModule getModuleFrom(Object[] arguments) {
for (Object argument : arguments) {

View File

@@ -38,13 +38,14 @@ import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
* Integration tests for {@link ModuleObservabilityBeanPostProcessor}.
*
* @author Oliver Drotbohm
* @author Marcin Grzejszczak
*/
class ModuleObservabilityBeanPostProcessorIntegrationTests {
@Test
void decoratesExposedComponentsWithTracingInterceptor() {
SampleComponent bean = SpringApplication
var bean = SpringApplication
.run(new Class<?>[] { ExampleApplication.class, ModuleObservabilityConfiguration.class }, new String[] {})
.getBean(SampleComponent.class);
@@ -62,13 +63,15 @@ class ModuleObservabilityBeanPostProcessorIntegrationTests {
@Configuration
static class ModuleObservabilityConfiguration {
@Bean ModuleObservabilityBeanPostProcessor foo(ConfigurableApplicationContext context) {
@Bean
ModuleObservabilityBeanPostProcessor foo(ConfigurableApplicationContext context) {
var runtime = ApplicationRuntime.of(context);
var modulesRuntime = new ApplicationModulesRuntime(() -> TestApplicationModules.of(ExampleApplication.class),
runtime);
return new ModuleObservabilityBeanPostProcessor(modulesRuntime, () -> ObservationRegistry.NOOP, context.getBeanFactory(), context.getEnvironment());
return new ModuleObservabilityBeanPostProcessor(modulesRuntime, () -> ObservationRegistry.NOOP,
context.getBeanFactory(), context.getEnvironment());
}
}

View File

@@ -32,6 +32,7 @@ import org.springframework.modulith.runtime.ApplicationModulesRuntime;
* Unit tests for {@link ModuleObservabilityBeanPostProcessor}.
*
* @author Oliver Drotbohm
* @author Marcin Grzejszczak
*/
class ModuleObservabilityBeanPostProcessorUnitTests {