This commit is contained in:
Marcin Grzejszczak
2024-11-08 19:59:08 +01:00
parent d921c717c6
commit e84ca0df72
15 changed files with 339 additions and 130 deletions

View File

@@ -13,7 +13,11 @@
<properties>
<module.name>org.springframework.modulith.observability</module.name>
<spring-cloud.version>2021.0.0</spring-cloud.version>
<micrometer-docs-generator.version>1.0.4</micrometer-docs-generator.version>
<micrometer-docs-generator.inputPath>${project.basedir}/src/main/java/</micrometer-docs-generator.inputPath>
<micrometer-docs-generator.inclusionPattern>.*</micrometer-docs-generator.inclusionPattern>
<micrometer-docs-generator.outputPath>${project.build.directory}/observation-documentation/</micrometer-docs-generator.outputPath>
</properties>
<dependencies>
@@ -79,6 +83,12 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
@@ -95,4 +105,39 @@
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>io.micrometer.docs.DocsGeneratorCommand</mainClass>
<includePluginDependencies>true</includePluginDependencies>
<arguments>
<argument>${micrometer-docs-generator.inputPath}</argument>
<argument>${micrometer-docs-generator.inclusionPattern}</argument>
<argument>${micrometer-docs-generator.outputPath}</argument>
</arguments>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-docs-generator</artifactId>
<version>${micrometer-docs-generator.version}</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,37 @@
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;
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 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) {
// TODO: Change this to application name
return "[" + context.getModule().getDisplayName() + "] " + context.getModule()
.getDisplayName();
}
}

View File

@@ -25,6 +25,7 @@ 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;

View File

@@ -15,17 +15,21 @@
*/
package org.springframework.modulith.observability;
import io.micrometer.tracing.BaggageInScope;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.Tracer.SpanInScope;
import java.util.HashMap;
import java.util.Map;
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import org.aopalliance.intercept.MethodInterceptor;
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.lang.Nullable;
import org.springframework.modulith.observability.ModulithObservations.LowKeys;
import org.springframework.util.Assert;
class ModuleEntryInterceptor implements MethodInterceptor {
@@ -34,28 +38,49 @@ class ModuleEntryInterceptor implements MethodInterceptor {
private static Map<String, ModuleEntryInterceptor> CACHE = new HashMap<>();
private static final String MODULE_KEY = ModuleTracingBeanPostProcessor.MODULE_BAGGAGE_KEY;
private static final ModulithObservationConvention DEFAULT = new DefaultModulithObservationConvention();
private final ObservedModule module;
private final Tracer tracer;
private final ObservationRegistry observationRegistry;
@Nullable private final ModulithObservationConvention customModulithObservationConvention;
/**
* Creates a new {@link ModuleEntryInterceptor} for the given {@link ObservedModule} and {@link Tracer}.
* Creates a new {@link ModuleEntryInterceptor} for the given {@link ObservedModule} and {@link ObservationRegistry}.
*
* @param module must not be {@literal null}.
* @param tracer must not be {@literal null}.
* @param module must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
*/
private ModuleEntryInterceptor(ObservedModule module, Tracer tracer) {
Assert.notNull(module, "ObservedModule must not be null!");
Assert.notNull(tracer, "Tracer must not be null!");
this.module = module;
this.tracer = tracer;
private ModuleEntryInterceptor(ObservedModule module, ObservationRegistry observationRegistry) {
this(module, observationRegistry, null);
}
public static ModuleEntryInterceptor of(ObservedModule module, Tracer tracer) {
/**
* Creates a new {@link ModuleEntryInterceptor} for the given {@link ObservedModule}, {@link ObservationRegistry}
* and {@link ModulithObservationConvention}.
*
* @param module must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
* @param custom must not be {@literal null}.
*/
private ModuleEntryInterceptor(ObservedModule module, ObservationRegistry observationRegistry,
ModulithObservationConvention custom) {
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);
}
public static ModuleEntryInterceptor of(ObservedModule module, ObservationRegistry observationRegistry,
ModulithObservationConvention custom) {
return CACHE.computeIfAbsent(module.getName(), __ -> {
return new ModuleEntryInterceptor(module, tracer);
return new ModuleEntryInterceptor(module, observationRegistry, custom);
});
}
@@ -63,15 +88,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 currentSpan = tracer.currentSpan();
var currentBaggage = tracer.getBaggage(MODULE_KEY);
var currentModule = currentBaggage != null ? currentBaggage.get() : null;
var currentObservation = observationRegistry.getCurrentObservation();
String currentModule = null;
if (currentSpan != null && moduleName.equals(currentModule)) {
if (currentObservation != null) {
KeyValue moduleKey = currentObservation.getContextView().getLowCardinalityKeyValue(MODULE_KEY);
currentModule = moduleKey != null ? moduleKey.getValue() : null;
}
if (currentObservation != null && moduleName.equals(currentModule)) {
// Same module
return invocation.proceed();
}
@@ -79,21 +108,20 @@ class ModuleEntryInterceptor implements MethodInterceptor {
LOGGER.trace("Entering {} via {}.", module.getDisplayName(), invokedMethod);
var span = tracer.spanBuilder()
.name(moduleName)
.tag("module.method", invokedMethod)
.tag(MODULE_KEY, moduleName)
.start();
try (SpanInScope ws = tracer.withSpan(span);
BaggageInScope baggage = tracer.createBaggageInScope(MODULE_KEY, moduleName)) {
return invocation.proceed();
boolean isEventListener = module.isEventListenerInvocation(invocation);
// TODO: Good name for metrics
ModulithContext modulithContext = new ModulithContext(module, invocation);
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);
return proceed;
} catch (Exception ex) {
observation.error(ex); observation.event(ModulithObservations.Events.EVENT_PUBLICATION_FAILURE); throw ex;
} finally {
LOGGER.trace("Leaving {}", module.getDisplayName());
span.end();
LOGGER.trace("Leaving {}", module.getDisplayName()); observation.stop();
}
}
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.modulith.observability;
import io.micrometer.observation.Observation.Event;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import java.util.function.Supplier;
@@ -22,6 +24,7 @@ import java.util.function.Supplier;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.modulith.observability.ModulithObservations.Events;
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
import org.springframework.util.Assert;
@@ -31,21 +34,21 @@ import org.springframework.util.Assert;
public class ModuleEventListener implements ApplicationListener<ApplicationEvent> {
private final ApplicationModulesRuntime runtime;
private final Supplier<Tracer> tracer;
private final Supplier<ObservationRegistry> observationRegistry;
/**
* Creates a new {@link ModuleEventListener} for the given {@link ApplicationModulesRuntime} and {@link Tracer}.
*
* @param runtime must not be {@literal null}.
* @param tracer must not be {@literal null}.
* @param observationRegistrySupplier must not be {@literal null}.
*/
public ModuleEventListener(ApplicationModulesRuntime runtime, Supplier<Tracer> tracer) {
public ModuleEventListener(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistrySupplier) {
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
Assert.notNull(tracer, "Tracer must not be null!");
Assert.notNull(observationRegistrySupplier, "Tracer must not be null!");
this.runtime = runtime;
this.tracer = tracer;
this.observationRegistry = observationRegistrySupplier;
}
/*
@@ -74,12 +77,12 @@ public class ModuleEventListener implements ApplicationListener<ApplicationEvent
return;
}
var span = tracer.get().currentSpan();
var observation = observationRegistry.get().getCurrentObservation();
if (span == null) {
if (observation == null) {
return;
}
span.event("Published " + payloadType.getName());
observation.event(Event.of(Events.EVENT_PUBLICATION_SUCCESS.getName(), "Published " + payloadType.getName()));
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.modulith.observability;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import java.lang.reflect.Method;
@@ -47,7 +48,7 @@ public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport impleme
public static final String MODULE_BAGGAGE_KEY = "org.springframework.modulith.module";
private final ApplicationModulesRuntime runtime;
private final Supplier<Tracer> tracer;
private final Supplier<ObservationRegistry> observationRegistry;
private final Map<String, Advisor> advisors;
private final ConfigurableListableBeanFactory factory;
@@ -56,16 +57,16 @@ public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport impleme
* {@link Tracer}.
*
* @param runtime must not be {@literal null}.
* @param tracer must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
*/
public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<Tracer> tracer,
public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry,
ConfigurableListableBeanFactory factory) {
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
Assert.notNull(tracer, "Tracer must not be null!");
Assert.notNull(observationRegistry, "Tracer must not be null!");
this.runtime = runtime;
this.tracer = tracer;
this.observationRegistry = observationRegistry;
this.advisors = new HashMap<>();
this.factory = factory;
}
@@ -120,7 +121,7 @@ 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, tracer.get()));
return new ApplicationModuleObservingAdvisor(type, ModuleEntryInterceptor.of(module, observationRegistry.get()));
});
}

View File

@@ -0,0 +1,30 @@
package org.springframework.modulith.observability;
import io.micrometer.observation.Observation;
import org.aopalliance.intercept.MethodInvocation;
/**
* A {@link Observation.Context} for Modulithic applications.
*
* @author Marcin Grzejsczak
* @since 1.3
*/
public class ModulithContext extends Observation.Context {
private final ObservedModule module;
private final MethodInvocation invocation;
public ModulithContext(ObservedModule module, MethodInvocation invocation) {
this.module = module;
this.invocation = invocation;
}
public ObservedModule getModule() {
return module;
}
public MethodInvocation getInvocation() {
return invocation;
}
}

View File

@@ -0,0 +1,18 @@
package org.springframework.modulith.observability;
import io.micrometer.observation.Observation.Context;
import io.micrometer.observation.ObservationConvention;
/**
* {@link ObservationConvention} for {@link ModulithContext}.
*
* @author Marcin Grzejszczak
* @since 1.3
*/
public interface ModulithObservationConvention extends ObservationConvention<ModulithContext> {
@Override
default boolean supportsContext(Context context) {
return context instanceof ModulithContext;
}
}

View File

@@ -0,0 +1,92 @@
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.ObservationConvention;
import io.micrometer.observation.docs.ObservationDocumentation;
enum ModulithObservations implements ObservationDocumentation {
/**
* Observation related to entering a module.
*/
MODULE_ENTRY {
@Override public Class<? extends ObservationConvention<? extends Context>> getDefaultConvention() {
return DefaultModulithObservationConvention.class;
}
@Override public KeyName[] getLowCardinalityKeyNames() {
return LowKeys.values();
}
@Override public KeyName[] getHighCardinalityKeyNames() {
return HighKeys.values();
}
@Override public Observation.Event[] getEvents() {
return Events.values();
}
};
enum LowKeys implements KeyName {
/**
* Name of the module.
*/
MODULE_KEY {
@Override public String asString() {
return "module.key";
}
},
/**
* Type of invocation (e.g. event listener).
*/
INVOCATION_TYPE {
@Override public String asString() {
return "module.invocation-type";
}
}
}
enum HighKeys implements KeyName {
/**
* Method executed on a module.
*/
MODULE_METHOD {
@Override public String asString() {
return "module.method";
}
}
}
enum Events implements Observation.Event {
/**
* Published when an event is sent successfully.
*/
EVENT_PUBLICATION_SUCCESS {
@Override public String getName() {
return "event.publication.success";
}
@Override public String getContextualName() {
return getName();
}
},
/**
* Published when an event is sent with a failure.
*/
EVENT_PUBLICATION_FAILURE {
@Override public String getName() {
return "event.publication.failure";
}
@Override public String getContextualName() {
return getName();
}
}
}
}

View File

@@ -24,11 +24,15 @@ import org.springframework.modulith.core.ApplicationModuleIdentifier;
import org.springframework.modulith.core.ApplicationModules;
import com.tngtech.archunit.core.domain.JavaClass;
import org.springframework.modulith.core.ArchitecturallyEvidentType;
/**
* Information about observed module.
*
* @author Oliver Drotbohm
* @since 1.3
*/
interface ObservedModule {
public interface ObservedModule {
/**
* Returns the name of the application module.

View File

@@ -35,8 +35,9 @@ import org.springframework.util.ReflectionUtils;
* Represents a type in an {@link ObservedModule}.
*
* @author Oliver Drotbohm
* @since 1.3
*/
class ObservedModuleType {
public class ObservedModuleType {
private static Collection<Class<?>> IGNORED_TYPES = List.of(Advised.class, TargetClassAware.class);
private static Predicate<Method> IS_USER_METHOD = it -> !Modifier.isPrivate(it.getModifiers())
@@ -115,4 +116,5 @@ class ObservedModuleType {
.map(it -> !module.isObservedModule(it))
.orElse(true);
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.modulith.observability;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import java.util.function.Supplier;
@@ -40,22 +41,22 @@ import org.springframework.util.Assert;
public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingSupport implements BeanPostProcessor {
private final ApplicationModulesRuntime runtime;
private final Supplier<Tracer> tracer;
private final Supplier<ObservationRegistry> observationRegistry;
/**
* Creates a new {@link SpringDataRestModuleTracingBeanPostProcessor} for the given {@link ApplicationModulesRuntime}
* and {@link Tracer}.
*
* @param runtime must not be {@literal null}.
* @param tracer must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
*/
public SpringDataRestModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<Tracer> tracer) {
public SpringDataRestModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<ObservationRegistry> observationRegistry) {
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
Assert.notNull(tracer, "Tracer must not be null!");
Assert.notNull(observationRegistry, "ObservationRegistry must not be null!");
this.runtime = runtime;
this.tracer = tracer;
this.observationRegistry = observationRegistry;
}
/*
@@ -71,7 +72,7 @@ public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingS
return bean;
}
Advice interceptor = new DataRestControllerInterceptor(runtime, tracer);
Advice interceptor = new DataRestControllerInterceptor(runtime, observationRegistry);
Advisor advisor = new DefaultPointcutAdvisor(interceptor);
return addAdvisor(bean, advisor, it -> it.setProxyTargetClass(true));
@@ -80,21 +81,21 @@ public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingS
private static class DataRestControllerInterceptor implements MethodInterceptor {
private final Supplier<ApplicationModules> modules;
private final Supplier<Tracer> tracer;
private final Supplier<ObservationRegistry> observationRegistry;
/**
* Creates a new {@link DataRestControllerInterceptor} for the given {@link ApplicationModules} and {@link Tracer}.
*
* @param modules must not be {@literal null}.
* @param tracer must not be {@literal null}.
* @param observationRegistry must not be {@literal null}.
*/
private DataRestControllerInterceptor(Supplier<ApplicationModules> modules, Supplier<Tracer> tracer) {
private DataRestControllerInterceptor(Supplier<ApplicationModules> modules, Supplier<ObservationRegistry> observationRegistry) {
Assert.notNull(modules, "ApplicationModules must not be null!");
Assert.notNull(tracer, "Tracer must not be null!");
Assert.notNull(observationRegistry, "Tracer must not be null!");
this.modules = modules;
this.tracer = tracer;
this.observationRegistry = observationRegistry;
}
/*
@@ -112,7 +113,7 @@ public class SpringDataRestModuleTracingBeanPostProcessor extends ModuleTracingS
var observed = new DefaultObservedModule(module);
return ModuleEntryInterceptor.of(observed, tracer.get()).invoke(invocation);
return ModuleEntryInterceptor.of(observed, observationRegistry.get()).invoke(invocation);
}
private ApplicationModule getModuleFrom(Object[] arguments) {

View File

@@ -15,18 +15,10 @@
*/
package org.springframework.modulith.observability.autoconfigure;
import brave.TracingCustomizer;
import brave.baggage.BaggageField;
import brave.baggage.BaggagePropagationConfig;
import brave.baggage.BaggagePropagationCustomizer;
import brave.handler.MutableSpan;
import brave.handler.SpanHandler;
import brave.propagation.TraceContext;
import io.micrometer.tracing.Tracer;
import io.micrometer.observation.ObservationRegistry;
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;
@@ -48,16 +40,17 @@ class ModuleObservabilityAutoConfiguration {
@Bean
static ModuleTracingBeanPostProcessor moduleTracingBeanPostProcessor(ApplicationModulesRuntime runtime,
ObjectProvider<Tracer> tracer, ConfigurableListableBeanFactory factory) {
return new ModuleTracingBeanPostProcessor(runtime, () -> tracer.getObject(), factory);
ObjectProvider<ObservationRegistry> observationRegistry, ConfigurableListableBeanFactory factory) {
return new ModuleTracingBeanPostProcessor(runtime, observationRegistry::getObject, factory);
}
@Bean
static ModuleEventListener tracingModuleEventListener(ApplicationModulesRuntime runtime,
ObjectProvider<Tracer> tracer) {
return new ModuleEventListener(runtime, () -> tracer.getObject());
ObjectProvider<ObservationRegistry> observationRegistry) {
return new ModuleEventListener(runtime, observationRegistry::getObject);
}
// TODO: Have a custom thread pool for modulith
@Bean
@ConditionalOnThreading(Threading.VIRTUAL)
SimpleAsyncTaskExecutorCustomizer simpleAsyncTaskExecutorCustomizer() {
@@ -69,52 +62,4 @@ class ModuleObservabilityAutoConfiguration {
ThreadPoolTaskExecutorCustomizer threadPoolTaskExecutorCustomizer() {
return executor -> executor.setTaskDecorator(new ContextPropagatingTaskDecorator());
}
/**
* Brave-specific auto configuration.
*
* @author Oliver Drotbohm
*/
@ConditionalOnClass(TracingCustomizer.class)
static class ModulithsBraveIntegrationAutoConfiguration {
@Bean
BaggagePropagationCustomizer moduleBaggagePropagationCustomizer() {
return builder -> builder
.add(BaggagePropagationConfig.SingleBaggageField
.local(BaggageField.create(ModuleTracingBeanPostProcessor.MODULE_BAGGAGE_KEY)));
}
@Bean
SpanHandler spanHandler() {
return new SpanHandler() {
/*
* (non-Javadoc)
* @see brave.handler.SpanHandler#end(brave.propagation.TraceContext, brave.handler.MutableSpan, brave.handler.SpanHandler.Cause)
*/
@Override
public boolean end(TraceContext context, MutableSpan span, Cause cause) {
String value = span.tag(ModuleTracingBeanPostProcessor.MODULE_BAGGAGE_KEY);
if (value != null) {
span.localServiceName(value);
return true;
}
BaggageField field = BaggageField.getByName(context, ModuleTracingBeanPostProcessor.MODULE_BAGGAGE_KEY);
value = field.getValue();
if (value != null) {
span.localServiceName(value);
}
return true;
}
};
}
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.modulith.observability.autoconfigure;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import org.springframework.beans.factory.ObjectProvider;
@@ -34,8 +35,8 @@ class SpringDataRestModuleObservabilityAutoConfiguration {
@Bean
static SpringDataRestModuleTracingBeanPostProcessor springDataRestModuleTracingBeanPostProcessor(
ApplicationModulesRuntime runtime, ObjectProvider<Tracer> tracer) {
ApplicationModulesRuntime runtime, ObjectProvider<ObservationRegistry> observationRegistry) {
return new SpringDataRestModuleTracingBeanPostProcessor(runtime, () -> tracer.getObject());
return new SpringDataRestModuleTracingBeanPostProcessor(runtime, () -> observationRegistry.getObject());
}
}

View File

@@ -20,6 +20,7 @@ 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;
@@ -70,7 +71,7 @@ class ModuleTracingBeanPostProcessorIntegrationTests {
var modulesRuntime = new ApplicationModulesRuntime(() -> TestApplicationModules.of(ExampleApplication.class),
runtime);
return new ModuleTracingBeanPostProcessor(modulesRuntime, () -> mock(Tracer.class), context.getBeanFactory());
return new ModuleTracingBeanPostProcessor(modulesRuntime, () -> ObservationRegistry.NOOP, context.getBeanFactory());
}
}