diff --git a/pom.xml b/pom.xml
index 109eb6f3..d7d670bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,8 @@
6.2.0-RC3
3.1.1
1.17.6
+
+ 1.5.0-SNAPSHOT
@@ -96,6 +98,14 @@ limitations under the License.
pom
import
+
+
+ io.micrometer
+ micrometer-tracing-bom
+ ${micrometer-tracing.version}
+ pom
+ import
+
org.springframework.boot
spring-boot-dependencies
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 1f1cb5e5..e92e7df0 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
@@ -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();
+ }
}
diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/LocalServiceRenamingSpanFilter.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/LocalServiceRenamingSpanFilter.java
new file mode 100644
index 00000000..919536e6
--- /dev/null
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/LocalServiceRenamingSpanFilter.java
@@ -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;
+ }
+}
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 20c67b49..d93086c6 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
@@ -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 CACHE = new HashMap<>();
- private static final String MODULE_KEY = ModuleTracingBeanPostProcessor.MODULE_BAGGAGE_KEY;
+ 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;
+ @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();
}
diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessor.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessor.java
similarity index 86%
rename from spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessor.java
rename to spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessor.java
index 5aedc988..88f50677 100644
--- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessor.java
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleObservabilityBeanPostProcessor.java
@@ -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;
private final Map 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,
- ConfigurableListableBeanFactory factory) {
+ public ModuleObservabilityBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier 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));
});
}
diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingSupport.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleObservabilitySupport.java
similarity index 96%
rename from spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingSupport.java
rename to spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleObservabilitySupport.java
index c951d51e..5a68d7ea 100644
--- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingSupport.java
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleObservabilitySupport.java
@@ -26,7 +26,7 @@ import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
/**
* @author Oliver Drotbohm
*/
-class ModuleTracingSupport implements BeanClassLoaderAware {
+class ModuleObservabilitySupport implements BeanClassLoaderAware {
private ClassLoader classLoader;
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
new file mode 100644
index 00000000..18122f48
--- /dev/null
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulePassingObservationFilter.java
@@ -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;
+ }
+}
\ 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 d8cdbf45..ddd33246 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
@@ -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;
+ }
}
diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleTracingBeanPostProcessor.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java
similarity index 78%
rename from spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleTracingBeanPostProcessor.java
rename to spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java
index b08a9f93..da7623dd 100644
--- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleTracingBeanPostProcessor.java
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/SpringDataRestModuleObservabilityBeanPostProcessor.java
@@ -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;
+ 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) {
+ public SpringDataRestModuleObservabilityBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier 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 modules;
private final Supplier 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 modules, Supplier observationRegistry) {
+ private DataRestControllerInterceptor(Supplier modules, Supplier 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) {
diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/ModuleObservabilityAutoConfiguration.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/ModuleObservabilityAutoConfiguration.java
index eeeba7fa..bf453db6 100644
--- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/ModuleObservabilityAutoConfiguration.java
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/ModuleObservabilityAutoConfiguration.java
@@ -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, ConfigurableListableBeanFactory factory) {
- return new ModuleTracingBeanPostProcessor(runtime, observationRegistry::getObject, factory);
+ static ModuleObservabilityBeanPostProcessor moduleTracingBeanPostProcessor(ApplicationModulesRuntime runtime,
+ ObjectProvider 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();
+ }
+ }
}
diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/SpringDataRestModuleObservabilityAutoConfiguration.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/SpringDataRestModuleObservabilityAutoConfiguration.java
index 7b00cad7..8ef88e5c 100644
--- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/SpringDataRestModuleObservabilityAutoConfiguration.java
+++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/SpringDataRestModuleObservabilityAutoConfiguration.java
@@ -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) {
+ static SpringDataRestModuleObservabilityBeanPostProcessor springDataRestModuleTracingBeanPostProcessor(
+ ApplicationModulesRuntime runtime, ObjectProvider observationRegistry, Environment environment) {
- return new SpringDataRestModuleTracingBeanPostProcessor(runtime, () -> observationRegistry.getObject());
+ return new SpringDataRestModuleObservabilityBeanPostProcessor(runtime, () -> observationRegistry.getObject(), environment);
}
}
diff --git a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorIntegrationTests.java b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorIntegrationTests.java
index 57202e12..e57dda43 100644
--- a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorIntegrationTests.java
+++ b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorIntegrationTests.java
@@ -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());
}
}
diff --git a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorUnitTests.java b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorUnitTests.java
index 42fe2745..e8da23b3 100644
--- a/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorUnitTests.java
+++ b/spring-modulith-observability/src/test/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessorUnitTests.java
@@ -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");