This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 3975-telemetry
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/3975-telemetry by this push:
new 2ab146d457b CAUSEWAY-3975: adds default
OpenTelemetryServerRequestObservationConvention
2ab146d457b is described below
commit 2ab146d457b3125b2bb314b93bdeef188cdce693
Author: andi-huber <[email protected]>
AuthorDate: Sun Mar 22 10:36:56 2026 +0100
CAUSEWAY-3975: adds default
OpenTelemetryServerRequestObservationConvention
---
commons/src/main/java/module-info.java | 1 +
.../observation/CausewayObservationInternal.java | 11 ++++++--
.../session/InteractionServiceDefault.java | 9 +++++--
.../core/webapp/CausewayModuleCoreWebapp.java | 30 +++++++++++++++++++---
.../viewer/CausewayModuleViewerWicketViewer.java | 4 +--
.../viewer/integration/TelemetryStartHandler.java | 8 +++++-
.../wicketapp/CausewayWicketApplication.java | 4 +--
7 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/commons/src/main/java/module-info.java
b/commons/src/main/java/module-info.java
index a5d7963e405..47a24ab13b0 100644
--- a/commons/src/main/java/module-info.java
+++ b/commons/src/main/java/module-info.java
@@ -68,6 +68,7 @@
requires transitive tools.jackson.core;
requires transitive tools.jackson.databind;
requires transitive tools.jackson.module.jakarta.xmlbind;
+ requires transitive micrometer.commons;
requires transitive micrometer.observation;
requires transitive org.jdom2;
requires transitive org.jspecify;
diff --git
a/commons/src/main/java/org/apache/causeway/commons/internal/observation/CausewayObservationInternal.java
b/commons/src/main/java/org/apache/causeway/commons/internal/observation/CausewayObservationInternal.java
index 2d7ea230a6b..7248a116165 100644
---
a/commons/src/main/java/org/apache/causeway/commons/internal/observation/CausewayObservationInternal.java
+++
b/commons/src/main/java/org/apache/causeway/commons/internal/observation/CausewayObservationInternal.java
@@ -28,6 +28,7 @@
import lombok.Data;
import lombok.experimental.Accessors;
+import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
import io.micrometer.observation.Observation.Scope;
import io.micrometer.observation.ObservationRegistry;
@@ -68,7 +69,7 @@ public boolean isNoop() {
public Observation createNotStarted(final Class<?> bean, final String
name) {
return Observation.createNotStarted(name, observationRegistry)
.lowCardinalityKeyValue("module", module)
- .highCardinalityKeyValue("bean", bean.getSimpleName());
+ .lowCardinalityKeyValue("bean", bean.getSimpleName());
}
@FunctionalInterface
@@ -84,7 +85,7 @@ public ObservationProvider provider(final Class<?> bean) {
* Helps if start and stop of an {@link Observation} happen in different
code locations.
*/
@Data @Accessors(fluent = true)
- public static class ObservationClosure implements AutoCloseable {
+ public static final class ObservationClosure implements AutoCloseable {
private Observation observation;
private Scope scope;
@@ -123,4 +124,10 @@ public ObservationClosure tag(final String key, @Nullable
final Supplier<Object>
}
+ public static KeyValue currentThreadId() {
+ var ct = Thread.currentThread();
+ return KeyValue.of("threadId", "%d [%s]".formatted(ct.getId(),
ct.getName()));
+
+ }
+
}
diff --git
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/session/InteractionServiceDefault.java
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/session/InteractionServiceDefault.java
index 841f5f582db..ca90c91139a 100644
---
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/session/InteractionServiceDefault.java
+++
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/session/InteractionServiceDefault.java
@@ -147,11 +147,16 @@ public InteractionLayer openInteraction(final @NonNull
InteractionContext intera
.map(it->(CausewayInteraction)it)
.orElseGet(()->new
CausewayInteraction(interactionIdGenerator.interactionId()));
- var obs = observationProvider.get("Causeway Layered Interaction")
- .highCardinalityKeyValue("stackSize",
""+getInteractionLayerCount());
+ var obs = observationProvider.get(getInteractionLayerCount()==0
+ ? "Causeway Root Interaction"
+ : "Causeway Nested Interaction");
var newInteractionLayer = layerStack.push(causewayInteraction,
interactionContextToUse, obs);
+ if(getInteractionLayerCount()>0) {
+ obs.highCardinalityKeyValue("stackedLayers",
""+getInteractionLayerCount());
+ }
+
if(isAtTopLevel()) {
transactionServiceSpring.onOpen(causewayInteraction);
interactionScopeLifecycleHandler.onTopLevelInteractionOpened();
diff --git
a/core/webapp/src/main/java/org/apache/causeway/core/webapp/CausewayModuleCoreWebapp.java
b/core/webapp/src/main/java/org/apache/causeway/core/webapp/CausewayModuleCoreWebapp.java
index fa99d8e5de6..6a16a0b7739 100644
---
a/core/webapp/src/main/java/org/apache/causeway/core/webapp/CausewayModuleCoreWebapp.java
+++
b/core/webapp/src/main/java/org/apache/causeway/core/webapp/CausewayModuleCoreWebapp.java
@@ -23,9 +23,12 @@
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
+import
org.springframework.http.server.observation.OpenTelemetryServerRequestObservationConvention;
+import
org.springframework.http.server.observation.ServerRequestObservationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextListener;
+import
org.apache.causeway.commons.internal.observation.CausewayObservationInternal;
import org.apache.causeway.core.interaction.session.MessageBrokerImpl;
import org.apache.causeway.core.metamodel.services.message.MessageBroker;
import org.apache.causeway.core.runtime.CausewayModuleCoreRuntime;
@@ -36,7 +39,9 @@
import
org.apache.causeway.core.webapp.modules.templresources.WebModuleTemplateResources;
import
org.apache.causeway.core.webapp.webappctx.CausewayWebAppContextInitializer;
-@Configuration
+import io.micrometer.common.KeyValues;
+
+@Configuration(proxyBeanMethods = false)
@Import({
// Modules
CausewayModuleCoreRuntime.class,
@@ -61,7 +66,7 @@ public class CausewayModuleCoreWebapp {
@Scope(
value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.TARGET_CLASS)
- public MessageBroker sessionScopedMessageBroker() {
+ MessageBroker sessionScopedMessageBroker() {
return new MessageBrokerImpl();
}
@@ -73,8 +78,27 @@ public MessageBroker sessionScopedMessageBroker() {
* @see <a
href="https://stackoverflow.com/a/61431621/56880">https://stackoverflow.com/a/61431621/56880</a>
*/
@Bean
- public RequestContextListener requestContextListener() {
+ RequestContextListener requestContextListener() {
return new RequestContextListener();
}
+ /**
+ * https://docs.spring.io/spring-boot/reference/actuator/observability.html
+ */
+ @Bean
+ OpenTelemetryServerRequestObservationConvention
openTelemetryServerRequestObservationConvention() {
+ return new OpenTelemetryServerRequestObservationConvention() {
+ @Override
+ public String getContextualName(final
ServerRequestObservationContext context) {
+ return super.getContextualName(context) + " {TODO}";
+ }
+ @Override
+ public KeyValues getHighCardinalityKeyValues(final
ServerRequestObservationContext context) {
+ // Make sure that KeyValues entries are already sorted by name
for better performance
+ return KeyValues.of(methodOriginal(context), httpUrl(context),
+ CausewayObservationInternal.currentThreadId());
+ }
+ };
+ }
+
}
diff --git
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
index 8746f572e7c..b3482c5feb3 100644
---
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
+++
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
@@ -43,7 +43,7 @@
/**
* @since 1.x {@index}
*/
-@Configuration
+@Configuration(proxyBeanMethods = false)
@Import({
// Modules
CausewayModuleViewerWicketUi.class,
@@ -69,9 +69,9 @@
PageClassRegistryDefault.AutoConfiguration.class,
PageNavigationServiceDefault.AutoConfiguration.class,
HintStoreUsingWicketSession.AutoConfiguration.class,
-
})
public class CausewayModuleViewerWicketViewer {
public static final String NAMESPACE = "causeway.viewer.wicket";
+
}
diff --git
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/integration/TelemetryStartHandler.java
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/integration/TelemetryStartHandler.java
index daeef157a43..41504896e40 100644
---
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/integration/TelemetryStartHandler.java
+++
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/integration/TelemetryStartHandler.java
@@ -22,6 +22,7 @@
import org.apache.wicket.request.cycle.IRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
+import
org.apache.causeway.commons.internal.observation.CausewayObservationInternal;
import
org.apache.causeway.commons.internal.observation.CausewayObservationInternal.ObservationProvider;
/**
@@ -31,11 +32,16 @@ public record TelemetryStartHandler(
ObservationProvider observationProvider)
implements IRequestCycleListener {
+ public TelemetryStartHandler(final CausewayObservationInternal
observationInternal) {
+ this(observationInternal.provider(TelemetryStartHandler.class));
+ }
+
@Override
public synchronized void onBeginRequest(final RequestCycle requestCycle) {
if (requestCycle instanceof RequestCycle2 requestCycle2) {
requestCycle2.observationClosure.startAndOpenScope(
- observationProvider.get("Apache Wicket Request Cycle"));
+ observationProvider.get("Apache Wicket Request Cycle")
+ .lowCardinalityKeyValue("ck2", "test2"));
}
}
diff --git
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
index 597e9548e82..36985ca8661 100644
---
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
+++
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
@@ -21,7 +21,6 @@
import java.time.Duration;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
@@ -213,8 +212,7 @@ protected void init() {
getRequestCycleSettings().setRenderStrategy(RequestCycleSettings.RenderStrategy.REDIRECT_TO_RENDER);
getResourceSettings().setParentFolderPlaceholder("$up$");
- getRequestCycleListeners().add(new
TelemetryStartHandler(Objects.requireNonNull(observationInternal)
- .provider(TelemetryStartHandler.class)));
+ getRequestCycleListeners().add(new
TelemetryStartHandler(observationInternal));
getRequestCycleListeners().add(new
WebRequestCycleForCauseway(metaModelContext, getPageClassRegistry()));
getRequestCycleListeners().add(new
TelemetryStopHandler(metricService));
getRequestCycleListeners().add(new RehydrationHandler());