diff --git a/spring-modulith-observability/pom.xml b/spring-modulith-observability/pom.xml index e7f4de1c..89e485e5 100644 --- a/spring-modulith-observability/pom.xml +++ b/spring-modulith-observability/pom.xml @@ -13,7 +13,11 @@ org.springframework.modulith.observability - 2021.0.0 + + 1.0.4 + ${project.basedir}/src/main/java/ + .* + ${project.build.directory}/observation-documentation/ @@ -79,6 +83,12 @@ true + + io.opentelemetry + opentelemetry-api + true + + @@ -95,4 +105,39 @@ + + + + org.codehaus.mojo + exec-maven-plugin + + + generate-docs + prepare-package + + java + + + io.micrometer.docs.DocsGeneratorCommand + true + + ${micrometer-docs-generator.inputPath} + ${micrometer-docs-generator.inclusionPattern} + ${micrometer-docs-generator.outputPath} + + + + + + + io.micrometer + micrometer-docs-generator + ${micrometer-docs-generator.version} + jar + + + + + + 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 new file mode 100644 index 00000000..1f1cb5e5 --- /dev/null +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/DefaultModulithObservationConvention.java @@ -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(); + } +} 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 5a54e29a..e97fc963 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,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; 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 ee6ffd74..20c67b49 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,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 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(); } } -} +} \ No newline at end of file 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 64648865..a51ab7e0 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 @@ -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 { private final ApplicationModulesRuntime runtime; - private final Supplier tracer; + private final Supplier 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) { + public ModuleEventListener(ApplicationModulesRuntime runtime, Supplier 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 tracer; + private final Supplier observationRegistry; private final Map 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, + public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier 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())); }); } 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 new file mode 100644 index 00000000..d8cdbf45 --- /dev/null +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithContext.java @@ -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; + } +} 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 new file mode 100644 index 00000000..04185c77 --- /dev/null +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservationConvention.java @@ -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 { + + @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 new file mode 100644 index 00000000..bf68bbe2 --- /dev/null +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModulithObservations.java @@ -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> 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(); + } + } + } +} diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModule.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModule.java index 763c0d8a..096929ac 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModule.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModule.java @@ -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. diff --git a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModuleType.java b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModuleType.java index 357a1cc2..06658cc8 100644 --- a/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModuleType.java +++ b/spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ObservedModuleType.java @@ -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> IGNORED_TYPES = List.of(Advised.class, TargetClassAware.class); private static Predicate IS_USER_METHOD = it -> !Modifier.isPrivate(it.getModifiers()) @@ -115,4 +116,5 @@ class ObservedModuleType { .map(it -> !module.isObservedModule(it)) .orElse(true); } + } 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/SpringDataRestModuleTracingBeanPostProcessor.java index 830baf25..b08a9f93 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/SpringDataRestModuleTracingBeanPostProcessor.java @@ -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; + private final Supplier 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) { + public SpringDataRestModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier 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 modules; - private final Supplier tracer; + private final Supplier 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 modules, Supplier tracer) { + private DataRestControllerInterceptor(Supplier modules, Supplier 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) { 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 2023d3d5..eeeba7fa 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,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, ConfigurableListableBeanFactory factory) { - return new ModuleTracingBeanPostProcessor(runtime, () -> tracer.getObject(), factory); + ObjectProvider observationRegistry, ConfigurableListableBeanFactory factory) { + return new ModuleTracingBeanPostProcessor(runtime, observationRegistry::getObject, factory); } @Bean static ModuleEventListener tracingModuleEventListener(ApplicationModulesRuntime runtime, - ObjectProvider tracer) { - return new ModuleEventListener(runtime, () -> tracer.getObject()); + ObjectProvider 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; - } - }; - } - } } 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 2b71ac46..7b00cad7 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 @@ -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) { + ApplicationModulesRuntime runtime, ObjectProvider observationRegistry) { - return new SpringDataRestModuleTracingBeanPostProcessor(runtime, () -> tracer.getObject()); + return new SpringDataRestModuleTracingBeanPostProcessor(runtime, () -> observationRegistry.getObject()); } } 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 3e12cd76..57202e12 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 @@ -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()); } }