diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultModulithObservationConvention.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultModulithObservationConvention.java index d42bb4b5..0e9b7704 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultModulithObservationConvention.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultModulithObservationConvention.java @@ -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 @@ * 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; - } - private boolean isEventListener(ModulithContext context) { - try { - return context.getModule().isEventListenerInvocation(context.getInvocation()); - } catch (Exception e) { - return false; - } + 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) { - Method method = context.getInvocation().getMethod(); + + 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; + } + } } diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultObservedModule.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultObservedModule.java index e97fc963..f6d53086 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultObservedModule.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultObservedModule.java @@ -25,7 +25,6 @@ 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 @@ private Method findModuleLocalMethod(MethodInvocation invocation) { var targetClass = advised.getTargetClass(); if (module.contains(targetClass)) { - return AopUtils.getMostSpecificMethod(method, targetClass); } diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEntryInterceptor.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEntryInterceptor.java index 8ac94a0a..8dc6645e 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEntryInterceptor.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEntryInterceptor.java @@ -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.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 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 @@ public Object invoke(MethodInvocation invocation) throws Throwable { 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 @@ public Object invoke(MethodInvocation invocation) throws Throwable { 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(); } diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEventListener.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEventListener.java index 4eac054d..1b707dbc 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEventListener.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleEventListener.java @@ -39,13 +39,15 @@ public class ModuleEventListener implements ApplicationListener 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 observationRegistrySupplier, - Supplier meterRegistrySupplier) { + public ModuleEventListener(ApplicationModulesRuntime runtime, + Supplier observationRegistrySupplier, Supplier meterRegistrySupplier) { Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!"); Assert.notNull(observationRegistrySupplier, "ObservationRegistry must not be null!"); @@ -82,8 +84,10 @@ public void onApplicationEvent(ApplicationEvent event) { 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()) // diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulePassingObservationFilter.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulePassingObservationFilter.java index 4e20bd47..c869e7db 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulePassingObservationFilter.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulePassingObservationFilter.java @@ -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; } -} \ No newline at end of file +} diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithContext.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithContext.java index b6a5b189..f593cae7 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithContext.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithContext.java @@ -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; + } } diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithMetrics.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithMetrics.java index 377d5531..73a85e46 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithMetrics.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithMetrics.java @@ -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 LowKeys implements KeyName { * 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 @@ public String asString() { * Name of the module. */ MODULE_NAME { + + /* + * (non-Javadoc) + * @see io.micrometer.common.docs.KeyName#asString() + */ @Override public String asString() { return "module.name"; diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservationConvention.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservationConvention.java index b6df45b4..267e84d4 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservationConvention.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservationConvention.java @@ -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 @@ */ public interface ModulithObservationConvention extends ObservationConvention { - @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; + } } diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservations.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservations.java index bf68bbe2..0ccfc2e9 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservations.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservations.java @@ -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> getDefaultConvention() { + + /* + * (non-Javadoc) + * @see io.micrometer.observation.docs.ObservationDocumentation#getDefaultConvention() + */ + @Override + public Class> 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 LowKeys implements KeyName { * 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 LowKeys implements KeyName { * 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 HighKeys implements KeyName { * 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 Events implements Observation.Event { * 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(); } } diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java index c7c8cdf4..6ab821f2 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java @@ -19,10 +19,8 @@ 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.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 @@ /** * @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; 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, Environment environment) { + public SpringDataRestModuleObservabilityBeanPostProcessor(ApplicationModulesRuntime runtime, + Supplier observationRegistry, Environment environment) { Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!"); Assert.notNull(observationRegistry, "ObservationRegistry must not be null!"); @@ -75,8 +77,8 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw 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 @@ private static class DataRestControllerInterceptor implements MethodInterceptor /** * 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 modules, Supplier observationRegistry, + private DataRestControllerInterceptor(Supplier modules, + Supplier observationRegistry, Environment environment) { Assert.notNull(modules, "ApplicationModules must not be null!"); @@ -124,6 +127,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { return ModuleEntryInterceptor.of(observed, observationRegistry.get(), environment).invoke(invocation); } + @Nullable private ApplicationModule getModuleFrom(Object[] arguments) { for (Object argument : arguments) { diff --git a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorIntegrationTests.java b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorIntegrationTests.java index bc94420b..24b4546d 100644 --- a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorIntegrationTests.java +++ b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorIntegrationTests.java @@ -38,13 +38,14 @@ * 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 @@ void decoratesExposedComponentsWithTracingInterceptor() { @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()); } } diff --git a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorUnitTests.java b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorUnitTests.java index 694839ac..248fd084 100644 --- a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorUnitTests.java +++ b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessorUnitTests.java @@ -32,6 +32,7 @@ * Unit tests for {@link ModuleObservabilityBeanPostProcessor}. * * @author Oliver Drotbohm + * @author Marcin Grzejszczak */ class ModuleObservabilityBeanPostProcessorUnitTests {