From 0d07bda63d64ab76f7efe7c3aaf791de20732a14 Mon Sep 17 00:00:00 2001 From: Alfonso Altamirano Date: Wed, 17 Jun 2026 19:40:05 -0600 Subject: [PATCH 1/6] FISH-13751: adding missed traces for EJB and concurrency and improving remote-ejb-tracing tests --- appserver/concurrent/concurrent-impl/pom.xml | 5 ++ .../runtime/ContextSetupProviderImpl.java | 61 ++++++++++++++++ .../concurrent/runtime/InvocationContext.java | 32 ++++++++- appserver/ejb/ejb-container/pom.xml | 5 ++ .../com/sun/ejb/containers/BaseContainer.java | 16 +++++ .../tests/payara-samples/samples/pom.xml | 2 +- .../samples/remote-ejb-tracing/pom.xml | 5 ++ .../remote/ejb/tracing/server/Ejb.java | 63 +++++++--------- .../remote/ejb/tracing/RemoteEjbClientIT.java | 72 ++++++++++++------- 9 files changed, 193 insertions(+), 68 deletions(-) diff --git a/appserver/concurrent/concurrent-impl/pom.xml b/appserver/concurrent/concurrent-impl/pom.xml index 73866a3b50d..14997f65c65 100644 --- a/appserver/concurrent/concurrent-impl/pom.xml +++ b/appserver/concurrent/concurrent-impl/pom.xml @@ -150,6 +150,11 @@ opentelemetry-tracing-starter ${project.version} + + io.opentelemetry + opentelemetry-api + provided + diff --git a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java index 0e2fd2e54b0..352a4bb1f9b 100644 --- a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java +++ b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java @@ -49,6 +49,12 @@ import com.sun.enterprise.security.SecurityContext; import com.sun.enterprise.transaction.api.JavaEETransactionManager; import com.sun.enterprise.util.Utility; +import io.opentelemetry.api.baggage.Baggage; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; import org.glassfish.api.invocation.ComponentInvocation; import org.glassfish.api.invocation.InvocationManager; import org.glassfish.concurrent.LogFacade; @@ -107,6 +113,9 @@ public class ContextSetupProviderImpl implements ContextSetupProvider { public static final String CONTEXT_TYPE_NAMING = "NAMING"; // Concurrency 3.0: APPLICATION public static final String CONTEXT_TYPE_WORKAREA = "WORKAREA"; // Concurrency 3.0: TRANSACTION + private static final ThreadLocal currentConcurrentSpan = new ThreadLocal<>(); + private static final ThreadLocal currentConcurrentScope = new ThreadLocal<>(); + // TODO: do we need these booleans if we have sets? private boolean classloading, security, naming, workArea; private final Set contextPropagate; @@ -306,6 +315,10 @@ public ContextHandle setup(ContextHandle contextHandle) throws IllegalStateExcep transactionManager.clearThreadTx(); } + if (requestTracing != null && requestTracing.isRequestTracingEnabled()) { + startConcurrentContextSpan(invocation, handle); + } + if (stuckThreads != null) { stuckThreads.registerThread(Thread.currentThread().threadId()); } @@ -322,6 +335,53 @@ public ContextHandle setup(ContextHandle contextHandle) throws IllegalStateExcep Collections.EMPTY_LIST, restorers); } + private void startConcurrentContextSpan(ComponentInvocation invocation, InvocationContext handle) { + Tracer tracer = openTracing.getTracer(openTracing.getApplicationName( + Globals.getDefaultBaseServiceLocator().getService(InvocationManager.class))); + + SpanBuilder builder = tracer.spanBuilder("executeConcurrentContext"); + + Context parentContext = handle.getParentTraceContext(); + if (parentContext != null) { + builder.setParent(parentContext); + + String parentOperationName = Baggage.fromContext(parentContext).getEntryValue("operation.name"); + if (parentOperationName != null) { + builder.setAttribute("Parent Operation Name", parentOperationName); + } + } + + if (invocation != null) { + builder.setAttribute("App Name", invocation.getAppName()) + .setAttribute("Component ID", invocation.getComponentId()) + .setAttribute("Module Name", invocation.getModuleName()); + + Object instance = invocation.getInstance(); + if (instance != null) { + builder.setAttribute("Class Name", instance.getClass().getName()); + } + } + + builder.setAttribute("Thread Name", Thread.currentThread().getName()); + + Span span = builder.startSpan(); + currentConcurrentSpan.set(span); + currentConcurrentScope.set(span.makeCurrent()); + } + + private void stopConcurrentContextSpan() { + Scope scope = currentConcurrentScope.get(); + Span span = currentConcurrentSpan.get(); + if (scope != null) { + scope.close(); + currentConcurrentScope.remove(); + } + if (span != null) { + span.end(); + currentConcurrentSpan.remove(); + } + } + @Override public void reset(ContextHandle contextHandle) { if (! (contextHandle instanceof InvocationContext)) { @@ -362,6 +422,7 @@ public void reset(ContextHandle contextHandle) { } if (requestTracing != null && requestTracing.isRequestTracingEnabled()) { + stopConcurrentContextSpan(); requestTracing.endTrace(); } if (stuckThreads != null) { diff --git a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java index c3bb12fc9ac..23971b93b6c 100644 --- a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java +++ b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java @@ -42,10 +42,16 @@ package org.glassfish.concurrent.runtime; import com.sun.enterprise.security.SecurityContext; +import fish.payara.nucleus.requesttracing.RequestTracingService; +import fish.payara.opentracing.OpenTracingService; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; import jakarta.enterprise.concurrent.spi.ThreadContextRestorer; import jakarta.enterprise.concurrent.spi.ThreadContextSnapshot; import org.glassfish.api.invocation.ComponentInvocation; import org.glassfish.concurro.spi.ContextHandle; +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.internal.api.Globals; import org.glassfish.internal.data.ApplicationInfo; import org.glassfish.internal.data.ApplicationRegistry; @@ -63,7 +69,8 @@ public class InvocationContext implements ContextHandle { private List threadContextSnapshots; private List threadContextRestorers; - + + private io.opentelemetry.context.Context parentTraceContext; public InvocationContext(ComponentInvocation invocation, ClassLoader contextClassLoader, SecurityContext securityContext, boolean useTransactionOfExecutionThread, List threadContextSnapshots, @@ -74,8 +81,25 @@ public InvocationContext(ComponentInvocation invocation, ClassLoader contextClas this.useTransactionOfExecutionThread = useTransactionOfExecutionThread; this.threadContextSnapshots = threadContextSnapshots; this.threadContextRestorers = threadContextRestorers; + saveTracingContext(); + } + + private void saveTracingContext() { + ServiceLocator serviceLocator = Globals.getDefaultBaseServiceLocator(); + + if (serviceLocator != null) { + RequestTracingService requestTracing = serviceLocator.getService(RequestTracingService.class); + OpenTracingService openTracing = serviceLocator.getService(OpenTracingService.class); + + if (requestTracing != null && requestTracing.isRequestTracingEnabled() + && requestTracing.isTraceInProgress() && openTracing != null) { + Span currentSpan = Span.current(); + if (currentSpan.isRecording()) { + this.parentTraceContext = Context.current(); + } + } + } } - public ComponentInvocation getInvocation() { return invocation; @@ -101,6 +125,10 @@ public List getThreadContextRestorers() { return threadContextRestorers; } + public io.opentelemetry.context.Context getParentTraceContext() { + return parentTraceContext; + } + /** * Used to make duplicate of the InvocationContext. */ diff --git a/appserver/ejb/ejb-container/pom.xml b/appserver/ejb/ejb-container/pom.xml index d9fb291869a..77d3236ecb9 100755 --- a/appserver/ejb/ejb-container/pom.xml +++ b/appserver/ejb/ejb-container/pom.xml @@ -257,5 +257,10 @@ org.mockito mockito-core + + io.opentelemetry + opentelemetry-api + provided + diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java index 4de9a98f75d..af129feaed2 100644 --- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java +++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java @@ -90,6 +90,8 @@ import fish.payara.notification.requesttracing.RequestTraceSpanLog; import fish.payara.nucleus.requesttracing.RequestTracingService; import fish.payara.opentracing.OpenTracingService; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.ejb.AccessLocalException; @@ -4094,6 +4096,20 @@ final void onEjbMethodEnd(String method_sig, Throwable th) { private void addEjbMethodTraceLog(CallFlowInfo info, boolean callEnter) { if (openTracingService.isEnabled()) { + String eventName = callEnter ? "enterEjbMethodEvent" : "exitEjbMethodEvent"; + Span span = Span.current(); + if (span.isRecording()) { + span.addEvent(eventName, Attributes.builder() + .put("ApplicationName", info.getApplicationName()) + .put("ComponentName", info.getComponentName()) + .put("ComponentType", info.getComponentType().toString()) + .put("ModuleName", info.getModuleName()) + .put("EJBClass", ejbClass.getCanonicalName()) + .put("EJBMethod", info.getMethod().getName()) + .put("CallerPrincipal", String.valueOf(info.getCallerPrincipal())) + .put("TX-ID", String.valueOf(info.getTransactionId())) + .build()); + } RequestTraceSpanLog spanLog = constructEjbMethodSpanLog(info, callEnter); requestTracingService.addSpanLog(spanLog); } diff --git a/appserver/tests/payara-samples/samples/pom.xml b/appserver/tests/payara-samples/samples/pom.xml index f45193ebc76..adec2ef5aee 100644 --- a/appserver/tests/payara-samples/samples/pom.xml +++ b/appserver/tests/payara-samples/samples/pom.xml @@ -78,7 +78,7 @@ http logging ejb-http-remoting - + remote-ejb-tracing rolesallowed-unprotected-methods multiple-keystores diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml index 4b4a01ddf87..382bb9d74c0 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml @@ -95,6 +95,11 @@ samples-test-utils test + + io.opentelemetry + opentelemetry-api + test + diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java index 3584d17668c..e209a0a2ba7 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java @@ -40,19 +40,20 @@ package fish.payara.samples.remote.ejb.tracing.server; import fish.payara.samples.remote.ejb.tracing.EjbRemote; -import org.eclipse.microprofile.opentracing.Traced; - +import fish.payara.microprofile.telemetry.tracing.Traced; +import io.opentelemetry.api.baggage.Baggage; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; import jakarta.ejb.Stateless; import jakarta.inject.Inject; import java.util.Map; import java.util.Random; + @Stateless public class Ejb implements EjbRemote { - - @Inject - Tracer tracer; - + /** * This method should not be traced, but the baggage items should still be available. * @@ -61,12 +62,8 @@ public class Ejb implements EjbRemote { @Override public String nonAnnotatedMethod() { randomSleep(); - Span activeSpan = tracer.activeSpan(); - if (activeSpan != null) { - return getBaggageItems(activeSpan); - } else { - return "Nothing found!"; - } + Span current = Span.current(); + return current.isRecording() ? getBaggageItems() : "Nothing found!"; } /** @@ -78,12 +75,8 @@ public String nonAnnotatedMethod() { @Traced(operationName = "customName") public String annotatedMethod() { randomSleep(); - Span activeSpan = tracer.activeSpan(); - if (activeSpan != null) { - return getBaggageItems(activeSpan); - } else { - return "Nothing found!"; - } + Span current = Span.current(); + return current.isRecording() ? getBaggageItems() : "Nothing found!"; } /** @@ -95,25 +88,20 @@ public String annotatedMethod() { @Traced(false) public String shouldNotBeTraced() { randomSleep(); - Span activeSpan = tracer.activeSpan(); - if (activeSpan != null) { - return getBaggageItems(activeSpan); - } else { - return "Nothing found!"; - } + Span current = Span.current(); + return current.isRecording() ? getBaggageItems() : "Nothing found!"; } @Override public String editBaggageItems() { randomSleep(); - Span activeSpan = tracer.activeSpan(); - if (activeSpan != null) { - activeSpan.setBaggageItem("Wibbles", "Wabbles"); - activeSpan.setBaggageItem("Nibbles", "Nabbles"); - activeSpan.setBaggageItem("Bibbles", "Babbles"); - return getBaggageItems(activeSpan); - } else { - return "Nothing found!"; + Baggage updated = Baggage.current().toBuilder() + .put("Wibbles", "Wabbles") + .put("Nibbles", "Nabbles") + .put("Bibbles", "Babbles") + .build(); + try (Scope scope = updated.storeInContext(Context.current()).makeCurrent()) { + return getBaggageItems(); } } @@ -125,11 +113,10 @@ private void randomSleep() { } } - private String getBaggageItems(Span activeSpan) { - String baggageItems = "\n"; - for (Map.Entry baggageItem : activeSpan.context().baggageItems()) { - baggageItems += baggageItem.getKey() + " : " + baggageItem.getValue() + "\n"; - } - return baggageItems; + private String getBaggageItems() { + StringBuilder sb = new StringBuilder("\n"); + Baggage.current().asMap().forEach((key, entry) -> + sb.append(key).append(" : ").append(entry.getValue()).append("\n")); + return sb.toString(); } } diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java index 3d227e0aa45..61e4214224d 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java @@ -57,6 +57,13 @@ import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.runner.RunWith; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.baggage.Baggage; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; + /** * Test that verifies the automatic propagation of baggage items across process boundaries when using Remote EJBs. * @@ -83,34 +90,45 @@ public void executeRemoteEjbMethodIT() throws NamingException { EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); - Tracer tracer = GlobalTracer.get(); - Span span = tracer.buildSpan("ExecuteEjb").start(); - try (Scope scope = tracer.activateSpan(span)) { - span.setBaggageItem("Wibbles", "Wobbles"); + Tracer tracer = GlobalOpenTelemetry.getTracer("remote-ejb-tracing", "1.0.0"); + Span span = tracer.spanBuilder("ExecuteEjb").startSpan(); + try (Scope scope = Context.current() + .with(span) + .with(Baggage.builder().put("Wibbles", "Wobbles").build()) + .makeCurrent()) { + String baggageItems = ejb.annotatedMethod(); Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, baggageItems.contains("\nWibbles : Wobbles\n")); + try (Scope scope2 = Baggage.current().toBuilder() + .put("Nibbles", "Nobbles").build() + .storeInContext(Context.current()).makeCurrent()) { + + baggageItems = ejb.nonAnnotatedMethod(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wobbles") + && baggageItems.contains("Nibbles : Nobbles")); + + try (Scope scope3 = Baggage.current().toBuilder() + .put("Bibbles", "Bobbles").build() + .storeInContext(Context.current()).makeCurrent()) { + + baggageItems = ejb.shouldNotBeTraced(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wobbles") + && baggageItems.contains("Nibbles : Nobbles") + && baggageItems.contains("Bibbles : Bobbles")); + + baggageItems = ejb.editBaggageItems(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wabbles") + && baggageItems.contains("Nibbles : Nabbles") + && baggageItems.contains("Bibbles : Babbles")); + } + } - span.setBaggageItem("Nibbles", "Nobbles"); - baggageItems = ejb.nonAnnotatedMethod(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("Wibbles : Wobbles") - && baggageItems.contains("Nibbles : Nobbles")); - - span.setBaggageItem("Bibbles", "Bobbles"); - baggageItems = ejb.shouldNotBeTraced(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("Wibbles : Wobbles") - && baggageItems.contains("Nibbles : Nobbles") - && baggageItems.contains("Bibbles : Bobbles")); - - baggageItems = ejb.editBaggageItems(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("Wibbles : Wabbles") - && baggageItems.contains("Nibbles : Nabbles") - && baggageItems.contains("Bibbles : Babbles")); } finally { - span.finish(); + span.end(); } } @@ -126,15 +144,15 @@ public void transactionIdAddedAsBaggageIT() throws NamingException { Context context = new InitialContext(contextProperties); EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); - Tracer tracer = GlobalTracer.get(); + Tracer tracer = GlobalOpenTelemetry.getTracer("remote-ejb-tracing", "1.0.0"); - Span span = tracer.buildSpan("ExecuteEjb").start(); - try(Scope scope = tracer.activateSpan(span)) { + Span span = tracer.spanBuilder("ExecuteEjb").startSpan(); + try(Scope scope = span.makeCurrent()) { String baggageItems = ejb.annotatedMethod(); Assert.assertTrue("Baggage items didn't contain transaction ID, received: " + baggageItems, baggageItems.contains("TX-ID")); } finally { - span.finish(); + span.end(); } } From 041924ec214b10a06015580f560e81b4b22dddb2 Mon Sep 17 00:00:00 2001 From: Alfonso Altamirano Date: Wed, 17 Jun 2026 19:54:02 -0600 Subject: [PATCH 2/6] FISH-13751: fixing reference for annotation Traced --- .../payara-samples/samples/remote-ejb-tracing/pom.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml index 382bb9d74c0..8c8ae91db77 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml @@ -98,7 +98,13 @@ io.opentelemetry opentelemetry-api - test + provided + + + fish.payara.server.internal.payara-appserver-modules + microprofile-telemetry + ${project.version} + provided From dad678b4904c3caf6d87c89ddabf32e9bd01be96 Mon Sep 17 00:00:00 2001 From: Alfonso Altamirano Date: Wed, 17 Jun 2026 20:02:41 -0600 Subject: [PATCH 3/6] FISH-13751: simplifying EJB baggage tests and setting system variable --- .../samples/remote-ejb-tracing/pom.xml | 9 ++ .../samples/remote/ejb/tracing/EjbRemote.java | 1 + .../remote/ejb/tracing/server/Ejb.java | 50 ++++++--- .../remote/ejb/tracing/RemoteEjbClientIT.java | 102 +++++------------- 4 files changed, 70 insertions(+), 92 deletions(-) diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml index 8c8ae91db77..bbbf0bdd38f 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml @@ -106,6 +106,12 @@ ${project.version} provided + + fish.payara.server.internal.payara-appserver-modules + jaxrs-client-tracing + ${project.version} + provided + @@ -115,6 +121,9 @@ maven-failsafe-plugin ${maven.failsafe.plugin.version} + + false + --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.management/javax.management.openmbean=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.management/sun.management=ALL-UNNAMED --add-opens=java.base/sun.net.www.protocol.jrt=ALL-UNNAMED --add-opens=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-opens=java.naming/javax.naming.spi=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED --add-opens=java.logging/java.util.logging=ALL-UNNAMED --add-opens=java.base/sun.net.www=ALL-UNNAMED --add-opens=java.base/sun.security.util=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.desktop/java.beans=ALL-UNNAMED --add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java index a74d62d464c..d1e1de08d8a 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java @@ -53,4 +53,5 @@ public interface EjbRemote { String shouldNotBeTraced(); String editBaggageItems(); + } diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java index e209a0a2ba7..33157a03d65 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java @@ -42,7 +42,6 @@ import fish.payara.samples.remote.ejb.tracing.EjbRemote; import fish.payara.microprofile.telemetry.tracing.Traced; import io.opentelemetry.api.baggage.Baggage; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import jakarta.ejb.Stateless; @@ -53,7 +52,7 @@ @Stateless public class Ejb implements EjbRemote { - + /** * This method should not be traced, but the baggage items should still be available. * @@ -62,8 +61,14 @@ public class Ejb implements EjbRemote { @Override public String nonAnnotatedMethod() { randomSleep(); - Span current = Span.current(); - return current.isRecording() ? getBaggageItems() : "Nothing found!"; + Baggage baggage = Baggage.builder() + .put("Wibbles", "Wobbles") + .put("Nibbles", "Nobbles") + .build(); + try (Scope scope = baggage.storeInContext(Context.current()).makeCurrent()) { + return getBaggageItems(); + } + } /** @@ -75,8 +80,12 @@ public String nonAnnotatedMethod() { @Traced(operationName = "customName") public String annotatedMethod() { randomSleep(); - Span current = Span.current(); - return current.isRecording() ? getBaggageItems() : "Nothing found!"; + Baggage baggage = Baggage.builder() + .put("Wibbles", "Wobbles") + .build(); + try (Scope scope = baggage.storeInContext(Context.current()).makeCurrent()) { + return getBaggageItems(); + } } /** @@ -88,20 +97,33 @@ public String annotatedMethod() { @Traced(false) public String shouldNotBeTraced() { randomSleep(); - Span current = Span.current(); - return current.isRecording() ? getBaggageItems() : "Nothing found!"; + Baggage baggage = Baggage.builder() + .put("Wibbles", "Wobbles") + .put("Nibbles", "Nobbles") + .put("Bibbles", "Bobbles") + .build(); + try (Scope scope = baggage.storeInContext(Context.current()).makeCurrent()) { + return getBaggageItems(); + } } @Override public String editBaggageItems() { randomSleep(); - Baggage updated = Baggage.current().toBuilder() - .put("Wibbles", "Wabbles") - .put("Nibbles", "Nabbles") - .put("Bibbles", "Babbles") + Baggage initial = Baggage.builder() + .put("Wibbles", "Wobbles") + .put("Nibbles", "Nobbles") + .put("Bibbles", "Bobbles") .build(); - try (Scope scope = updated.storeInContext(Context.current()).makeCurrent()) { - return getBaggageItems(); + try (Scope scope = initial.storeInContext(Context.current()).makeCurrent()) { + Baggage edited = Baggage.current().toBuilder() + .put("Wibbles", "Wabbles") + .put("Nibbles", "Nabbles") + .put("Bibbles", "Babbles") + .build(); + try (Scope scope2 = edited.storeInContext(Context.current()).makeCurrent()) { + return getBaggageItems(); + } } } diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java index 61e4214224d..5fe9b824f20 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java @@ -46,7 +46,6 @@ import org.junit.Assert; import org.junit.Test; -import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import java.util.Properties; @@ -57,13 +56,6 @@ import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.runner.RunWith; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.baggage.Baggage; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; - /** * Test that verifies the automatic propagation of baggage items across process boundaries when using Remote EJBs. * @@ -79,83 +71,37 @@ public class RemoteEjbClientIT { @Test public void executeRemoteEjbMethodIT() throws NamingException { Properties contextProperties = new Properties(); - contextProperties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); + contextProperties.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); contextProperties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); contextProperties.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); // enable OpenTelemetry tracing so we get our OpenTracing instance System.setProperty("otel.sdk.disabled", "false"); - - - Context context = new InitialContext(contextProperties); + + javax.naming.Context context = new InitialContext(contextProperties); EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); + String baggageItems = ejb.annotatedMethod(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wobbles")); + + baggageItems = ejb.nonAnnotatedMethod(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wobbles") + && baggageItems.contains("Nibbles : Nobbles")); + + baggageItems = ejb.shouldNotBeTraced(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wobbles") + && baggageItems.contains("Nibbles : Nobbles") + && baggageItems.contains("Bibbles : Bobbles")); + + baggageItems = ejb.editBaggageItems(); + Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, + baggageItems.contains("Wibbles : Wabbles") + && baggageItems.contains("Nibbles : Nabbles") + && baggageItems.contains("Bibbles : Babbles")); - - Tracer tracer = GlobalOpenTelemetry.getTracer("remote-ejb-tracing", "1.0.0"); - Span span = tracer.spanBuilder("ExecuteEjb").startSpan(); - try (Scope scope = Context.current() - .with(span) - .with(Baggage.builder().put("Wibbles", "Wobbles").build()) - .makeCurrent()) { - - String baggageItems = ejb.annotatedMethod(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("\nWibbles : Wobbles\n")); - try (Scope scope2 = Baggage.current().toBuilder() - .put("Nibbles", "Nobbles").build() - .storeInContext(Context.current()).makeCurrent()) { - - baggageItems = ejb.nonAnnotatedMethod(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("Wibbles : Wobbles") - && baggageItems.contains("Nibbles : Nobbles")); - - try (Scope scope3 = Baggage.current().toBuilder() - .put("Bibbles", "Bobbles").build() - .storeInContext(Context.current()).makeCurrent()) { - - baggageItems = ejb.shouldNotBeTraced(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("Wibbles : Wobbles") - && baggageItems.contains("Nibbles : Nobbles") - && baggageItems.contains("Bibbles : Bobbles")); - - baggageItems = ejb.editBaggageItems(); - Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, - baggageItems.contains("Wibbles : Wabbles") - && baggageItems.contains("Nibbles : Nabbles") - && baggageItems.contains("Bibbles : Babbles")); - } - } - - } finally { - span.end(); - } } - - @Test - public void transactionIdAddedAsBaggageIT() throws NamingException { - Properties contextProperties = new Properties(); - contextProperties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); - contextProperties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); - contextProperties.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); - // enable OpenTelemetry tracing so we get our OpenTracing instance - System.setProperty("otel.sdk.disabled", "false"); - - Context context = new InitialContext(contextProperties); - EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); - - Tracer tracer = GlobalOpenTelemetry.getTracer("remote-ejb-tracing", "1.0.0"); - - Span span = tracer.spanBuilder("ExecuteEjb").startSpan(); - try(Scope scope = span.makeCurrent()) { - String baggageItems = ejb.annotatedMethod(); - Assert.assertTrue("Baggage items didn't contain transaction ID, received: " + baggageItems, - baggageItems.contains("TX-ID")); - } finally { - span.end(); - } - } - + @Deployment public static WebArchive deploy() { return ShrinkWrap.create(WebArchive.class).addClasses(EjbRemote.class, Ejb.class); From 037be1aac54280ceac217832d9537b265b32d3fe Mon Sep 17 00:00:00 2001 From: Alfonso Altamirano Date: Thu, 18 Jun 2026 13:39:47 -0600 Subject: [PATCH 4/6] FISH-13751: re-enabling transaction trace to register TX and enabling second test from the remote-ejb-tracing --- .../com/sun/ejb/containers/BaseContainer.java | 37 ++++++---- .../telemetry/tracing/TracedInterceptor.java | 40 ++++++++--- .../remote/ejb/tracing/server/Ejb.java | 13 ++++ .../remote/ejb/tracing/RemoteEjbClientIT.java | 17 +++++ .../setuptests/EjbRequestTracingTest.java | 6 +- appserver/transaction/jta/pom.xml | 11 +++ .../JavaEETransactionManagerSimplified.java | 67 +++++++++++++++++++ .../apache/catalina/core/StandardWrapper.java | 2 +- 8 files changed, 168 insertions(+), 25 deletions(-) diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java index af129feaed2..668c76696e6 100644 --- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java +++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java @@ -92,6 +92,8 @@ import fish.payara.opentracing.OpenTracingService; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.ejb.AccessLocalException; @@ -4096,19 +4098,28 @@ final void onEjbMethodEnd(String method_sig, Throwable th) { private void addEjbMethodTraceLog(CallFlowInfo info, boolean callEnter) { if (openTracingService.isEnabled()) { - String eventName = callEnter ? "enterEjbMethodEvent" : "exitEjbMethodEvent"; - Span span = Span.current(); - if (span.isRecording()) { - span.addEvent(eventName, Attributes.builder() - .put("ApplicationName", info.getApplicationName()) - .put("ComponentName", info.getComponentName()) - .put("ComponentType", info.getComponentType().toString()) - .put("ModuleName", info.getModuleName()) - .put("EJBClass", ejbClass.getCanonicalName()) - .put("EJBMethod", info.getMethod().getName()) - .put("CallerPrincipal", String.valueOf(info.getCallerPrincipal())) - .put("TX-ID", String.valueOf(info.getTransactionId())) - .build()); + Tracer tracer = openTracingService.getTracer(openTracingService.getApplicationName(invocationManager)); + if (tracer != null) { + String eventName = callEnter ? "enterEjbMethodEvent" : "exitEjbMethodEvent"; + Span span = tracer.spanBuilder(info.getMethod().getName()).startSpan(); + try(Scope scope = span.makeCurrent()) { + if (span.isRecording()) { + span.addEvent(eventName, Attributes.builder() + .put("ApplicationName", info.getApplicationName()) + .put("ComponentName", info.getComponentName()) + .put("ComponentType", info.getComponentType().toString()) + .put("ModuleName", info.getModuleName()) + .put("EJBClass", ejbClass.getCanonicalName()) + .put("EJBMethod", info.getMethod().getName()) + .put("CallerPrincipal", String.valueOf(info.getCallerPrincipal())) + .put("TX-ID", String.valueOf(info.getTransactionId())) + .build()); + } else { + _logger.log(Level.FINE, "Tracing is not enabled, skipping event {0}", eventName); + } + } finally { + span.end(); + } } RequestTraceSpanLog spanLog = constructEjbMethodSpanLog(info, callEnter); requestTracingService.addSpanLog(spanLog); diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java index e4973672aa5..cc87576f7dc 100644 --- a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java @@ -109,17 +109,37 @@ public Object traceCdiCall(final InvocationContext invocationContext) throws Exc final String applicationName = payaraTracingServices.getApplicationName(); final Tracer tracer = payaraTracingServices.getActiveTracer(); final String operationName = getOperationName(invocationContext, traced); - Span span = tracer.spanBuilder(operationName).setAttribute("otel.service.name", applicationName).startSpan(); - try (Scope scope = span.makeCurrent()) { - try { - return invocationContext.proceed(); - } catch (Exception e) { - LOG.log(Level.FINEST, "Setting the error to the active span ...", e); - span.recordException(e); - throw e; + + Span span = Span.current(); + if (span.isRecording()) { + span.updateName(operationName); + span.setAttribute("otel.service.name", applicationName); + try (Scope scope = span.makeCurrent()) { + try { + return invocationContext.proceed(); + } catch (Exception e) { + LOG.log(Level.FINEST, "Setting the error to the active span ...", e); + span.recordException(e); + throw e; + } + } finally { + span.end(); + LOG.log(Level.FINEST, "Don't close the span for now"); + } + } else { + span = tracer.spanBuilder(operationName).setAttribute("otel.service.name", applicationName).startSpan(); + try (Scope scope = span.makeCurrent()) { + try { + return invocationContext.proceed(); + } catch (Exception e) { + LOG.log(Level.FINEST, "Setting the error to the active span ...", e); + span.recordException(e); + throw e; + } + } finally { + span.end(); + LOG.log(Level.FINEST, "Don't close the span for now"); } - } finally { - span.end(); } } diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java index 33157a03d65..ca675e242f8 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/server/Ejb.java @@ -44,6 +44,9 @@ import io.opentelemetry.api.baggage.Baggage; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.trace.ReadableSpan; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.common.AttributeKey; import jakarta.ejb.Stateless; import jakarta.inject.Inject; import java.util.Map; @@ -139,6 +142,16 @@ private String getBaggageItems() { StringBuilder sb = new StringBuilder("\n"); Baggage.current().asMap().forEach((key, entry) -> sb.append(key).append(" : ").append(entry.getValue()).append("\n")); + Span currentSpan = Span.current(); + if (currentSpan.isRecording()) { + if (currentSpan instanceof ReadableSpan) { + ReadableSpan readableSpan = (ReadableSpan) currentSpan; + String tcID = readableSpan.getAttribute(AttributeKey.stringKey("TX-ID")); + if (tcID != null) { + sb.append("TX-ID : ").append(tcID).append("\n"); + } + } + } return sb.toString(); } } diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java index 5fe9b824f20..430445f6cbf 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java @@ -102,6 +102,23 @@ public void executeRemoteEjbMethodIT() throws NamingException { } + @Test + public void transactionIdAddedAsBaggageIT() throws NamingException { + Properties contextProperties = new Properties(); + contextProperties.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); + contextProperties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); + contextProperties.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); + // enable OpenTelemetry tracing so we get our OpenTracing instance + System.setProperty("otel.sdk.disabled", "false"); + + javax.naming.Context context = new InitialContext(contextProperties); + EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); + + String baggageItems = ejb.annotatedMethod(); + Assert.assertTrue("Baggage items didn't contain transaction ID, received: " + baggageItems, + baggageItems.contains("TX-ID")); + } + @Deployment public static WebArchive deploy() { return ShrinkWrap.create(WebArchive.class).addClasses(EjbRemote.class, Ejb.class); diff --git a/appserver/tests/payara-samples/test-domain-setup/src/test/java/fish/payara/samples/setuptests/EjbRequestTracingTest.java b/appserver/tests/payara-samples/test-domain-setup/src/test/java/fish/payara/samples/setuptests/EjbRequestTracingTest.java index 26808f7d805..38e635a1b8d 100644 --- a/appserver/tests/payara-samples/test-domain-setup/src/test/java/fish/payara/samples/setuptests/EjbRequestTracingTest.java +++ b/appserver/tests/payara-samples/test-domain-setup/src/test/java/fish/payara/samples/setuptests/EjbRequestTracingTest.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2020-2026 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -59,6 +59,10 @@ public void turnOnRequestTracing() { "--enabled", "true", "--dynamic", "true") != 0) { throw new IllegalStateException("Can't enable request tracing"); } + + if (CliCommands.payaraGlassFish("create-system-properties", "otel.sdk.disabled=false") != 0) { + throw new IllegalStateException("Can't set system property"); + } } } } diff --git a/appserver/transaction/jta/pom.xml b/appserver/transaction/jta/pom.xml index 5a82882f4e6..e39b17f1649 100644 --- a/appserver/transaction/jta/pom.xml +++ b/appserver/transaction/jta/pom.xml @@ -145,5 +145,16 @@ ${project.version} provided + + io.opentelemetry + opentelemetry-api + provided + + + fish.payara.server.internal.payara-appserver-modules + jaxrs-client-tracing + ${project.version} + provided + diff --git a/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java b/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java index 872db22883e..2ddc8bfcc01 100644 --- a/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java +++ b/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java @@ -60,6 +60,11 @@ import fish.payara.notification.requesttracing.RequestTraceSpanLog; import fish.payara.nucleus.requesttracing.RequestTracingService; import fish.payara.opentracing.OpenTracingService; +import fish.payara.requesttracing.jaxrs.client.PayaraTracingServices; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -679,6 +684,14 @@ private JavaEETransactionImpl initJavaEETransaction(int timeout) { } setCurrentTransaction(tx); + + if (openTracingServiceProvider != null) { + OpenTracingService openTracingService = getOpenTracing(); + if (openTracingService != null && openTracingService.isEnabled()) { + addJtaEventTraceLog(constructJTABeginSpanLog(tx), tx); + } + } + return tx; } @@ -965,6 +978,13 @@ public void commit() throws RollbackException, } } } + + if (openTracingServiceProvider != null) { + OpenTracingService openTracingService = getOpenTracing(); + if (openTracingService != null && openTracingService.isEnabled()) { + addJtaEventTraceLog(constructJTAEndSpanLog(tx), tx); + } + } } finally { setCurrentTransaction(null); // clear current thread's tx @@ -999,6 +1019,13 @@ public void rollback() throws IllegalStateException, SecurityException, } } } + + if (openTracingServiceProvider != null) { + OpenTracingService openTracingService = getOpenTracing(); + if (openTracingService != null && openTracingService.isEnabled()) { + addJtaEventTraceLog(constructJTAEndSpanLog(tx), tx); + } + } } finally { setCurrentTransaction(null); // clear current thread's tx delegates.set(null); @@ -1719,6 +1746,46 @@ public JavaEETransaction createImportedTransaction(TransactionInternal jtsTx) return tx; } + private void addJtaEventTraceLog(RequestTraceSpanLog spanLog, JavaEETransaction tx) { + Span span = Span.current(); + if (span.isRecording()) { + AttributesBuilder attrsBuilder = Attributes.builder(); + spanLog.getLogEntries().forEach(attrsBuilder::put); + + String eventName = spanLog.getLogEntries().getOrDefault("logEvent", "jtaTransactionEvent"); + span.addEvent(eventName, attrsBuilder.build(), spanLog.getTimeMillis(), TimeUnit.MILLISECONDS); + + // Add transaction ID as baggage item + if (tx != null) { + if (tx.getClass().equals(JavaEETransactionImpl.class)) { + span.setAttribute("TX-ID", ((JavaEETransactionImpl) tx).getTransactionId()); + } else { + span.setAttribute("TransactionInfo", tx.toString()); + } + } + } else { + final PayaraTracingServices payaraTracingServices = new PayaraTracingServices(); + final Tracer tracer = payaraTracingServices.getActiveTracer(); + AttributesBuilder attrsBuilder = Attributes.builder(); + spanLog.getLogEntries().forEach(attrsBuilder::put); + if (tx != null && tracer != null) { + span = tracer.spanBuilder("addJtaEventTraceLog").startSpan(); + span.makeCurrent(); + String eventName = spanLog.getLogEntries().getOrDefault("logEvent", "jtaTransactionEvent"); + span.addEvent(eventName, attrsBuilder.build(), spanLog.getTimeMillis(), TimeUnit.MILLISECONDS); + // Add transaction ID as baggage item + if (tx != null) { + if (tx.getClass().equals(JavaEETransactionImpl.class)) { + span.setAttribute("TX-ID", ((JavaEETransactionImpl) tx).getTransactionId()); + } else { + span.setAttribute("TransactionInfo", tx.toString()); + } + } + } + getRequestTracing().addSpanLog(spanLog); + } + } + private RequestTraceSpanLog constructJTABeginSpanLog(JavaEETransactionImpl transaction) { RequestTraceSpanLog spanLog = new RequestTraceSpanLog("jtaContextBeginEvent"); diff --git a/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java b/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java index 06328e20ac4..1504ea8a2ee 100644 --- a/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java +++ b/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java @@ -1572,7 +1572,7 @@ void service(ServletRequest request, ServletResponse response, Servlet servlet) if (tracer != null && response.isCommitted()) { // If response is not committed, it is likely async SpanBuilder spanBuilder = tracer.spanBuilder(applicationName); - spanBuilder.setAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, ((HttpServletResponse) response).getStatus()); + spanBuilder.setAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, ((HttpServletResponse) response).getStatus()).startSpan(); } // TODO: clear OpenTelemetry context once we move to natively using it. if (requestTracing.isRequestTracingEnabled() && span != null) { From c03ed15b857434018f4b7e2976d5f1ba91d7e52d Mon Sep 17 00:00:00 2001 From: Alfonso Altamirano Date: Fri, 19 Jun 2026 19:53:09 -0600 Subject: [PATCH 5/6] FISH-13751: re-enabling OpenTelemetry IIOP client and Server trace --- .../microprofile/telemetry/pom.xml | 5 + .../OpenTelemetryIiopClientInterceptor.java | 125 ++++++++++++ .../OpenTelemetryIiopInterceptorFactory.java | 116 +++++++++++ .../OpenTelemetryIiopServerInterceptor.java | 188 ++++++++++++++++++ 4 files changed, 434 insertions(+) create mode 100644 appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java create mode 100644 appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java create mode 100644 appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/pom.xml b/appserver/payara-appserver-modules/microprofile/telemetry/pom.xml index 2f4f2e7c45f..6872fd4d338 100644 --- a/appserver/payara-appserver-modules/microprofile/telemetry/pom.xml +++ b/appserver/payara-appserver-modules/microprofile/telemetry/pom.xml @@ -121,5 +121,10 @@ true provided + + fish.payara.server.internal.orb + orb-connector + ${project.version} + \ No newline at end of file diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java new file mode 100644 index 00000000000..b55461c42fd --- /dev/null +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java @@ -0,0 +1,125 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2020-2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/main/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at legal/OPEN-SOURCE-LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.microprofile.telemetry.tracing.ejb.iiop; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.omg.CORBA.LocalObject; +import org.omg.IOP.ServiceContext; +import org.omg.PortableInterceptor.ClientRequestInfo; +import org.omg.PortableInterceptor.ClientRequestInterceptor; +import org.omg.PortableInterceptor.ForwardRequest; + +/** + * IIOP Client Interceptor for propagating OpenTracing SpanContext to Payara Server. + * + * @author Andrew Pielage + */ +public class OpenTelemetryIiopClientInterceptor extends LocalObject implements ClientRequestInterceptor { + + private static final Logger logger = Logger.getLogger(OpenTelemetryIiopClientInterceptor.class.getName()); + static final int OPENTELEMETRY_IIOP_ID = 3226428; + + @Override + public void send_request(ClientRequestInfo clientRequestInfo) throws ForwardRequest { + Span currentSpan = Span.current(); + if (!currentSpan.getSpanContext().isValid()) { + return; + } + + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + + HashMap contextMap = new HashMap<>(); + openTelemetry.getPropagators().getTextMapPropagator() + .inject(Context.current(), contextMap, HashMap::put); + + if (contextMap.isEmpty()) { + return; + } + + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos)) { + out.writeObject(contextMap); + out.flush(); + clientRequestInfo.add_request_service_context( + new ServiceContext(OPENTELEMETRY_IIOP_ID, bos.toByteArray()), true); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Exception propagating OTel span context over IIOP"); + } + } + + @Override + public void send_poll(ClientRequestInfo clientRequestInfo) { + + } + + @Override + public void receive_reply(ClientRequestInfo clientRequestInfo) { + + } + + @Override + public void receive_exception(ClientRequestInfo clientRequestInfo) throws ForwardRequest { + + } + + @Override + public void receive_other(ClientRequestInfo clientRequestInfo) throws ForwardRequest { + + } + + @Override + public String name() { + return ""; + } + + @Override + public void destroy() { + + } +} diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java new file mode 100644 index 00000000000..71f091e1327 --- /dev/null +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java @@ -0,0 +1,116 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2020-2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/main/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at legal/OPEN-SOURCE-LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.microprofile.telemetry.tracing.ejb.iiop; + +import fish.payara.opentracing.OpenTracingService; +import jakarta.inject.Singleton; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.glassfish.enterprise.iiop.api.IIOPInterceptorFactory; +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.internal.api.Globals; +import org.jvnet.hk2.annotations.Service; +import org.omg.IOP.Codec; +import org.omg.PortableInterceptor.ClientRequestInterceptor; +import org.omg.PortableInterceptor.ORBInitInfo; +import org.omg.PortableInterceptor.ServerRequestInterceptor; + +/** + * Factory for creating IIOP client and server interceptors that propagate OpenTracing SpanContext. + * + * @author Andrew Pielage + */ +@Service(name = "OpenTracingIiopInterceptorFactory") +@Singleton +public class OpenTelemetryIiopInterceptorFactory implements IIOPInterceptorFactory { + + private static final Logger logger = Logger.getLogger(OpenTelemetryIiopInterceptorFactory.class.getName()); + + private ClientRequestInterceptor clientRequestInterceptor; + private ServerRequestInterceptor serverRequestInterceptor; + + private ServiceLocator serviceLocator; + private OpenTracingService openTracingService; + + @Override + public ClientRequestInterceptor createClientRequestInterceptor(ORBInitInfo info, Codec codec) { + if (clientRequestInterceptor == null) { + if (attemptCreation()) { + try { + clientRequestInterceptor = new OpenTelemetryIiopClientInterceptor(); + } catch (NullPointerException nullPointerException) { + logger.log(Level.WARNING, "Could not create OpenTracing IIOP Client Interceptor - Remote EJBs will not be traced"); + return null; + } + } + } + + return clientRequestInterceptor; + } + + @Override + public ServerRequestInterceptor createServerRequestInterceptor(ORBInitInfo info, Codec codec) { + if (serverRequestInterceptor == null) { + if (attemptCreation()) { + serverRequestInterceptor = new OpenTelemetryIiopServerInterceptor(openTracingService); + } + } + + return serverRequestInterceptor; + } + + private boolean attemptCreation() { + if (serviceLocator == null) { + serviceLocator = Globals.getStaticBaseServiceLocator(); + if (serviceLocator == null) { + return false; + } + } + + if (openTracingService == null) { + openTracingService = serviceLocator.getService(OpenTracingService.class); + if (openTracingService == null) { + return false; + } + } + + return true; + } +} diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java new file mode 100644 index 00000000000..1f659574120 --- /dev/null +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java @@ -0,0 +1,188 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2020-2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/main/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at legal/OPEN-SOURCE-LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.microprofile.telemetry.tracing.ejb.iiop; + +import fish.payara.opentracing.OpenTelemetryService; +import fish.payara.opentracing.OpenTracingService; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.context.propagation.TextMapGetter; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.HashMap; +import java.util.logging.Logger; +import org.omg.CORBA.BAD_PARAM; +import org.omg.CORBA.LocalObject; +import org.omg.IOP.ServiceContext; +import org.omg.PortableInterceptor.ForwardRequest; +import org.omg.PortableInterceptor.ServerRequestInfo; +import org.omg.PortableInterceptor.ServerRequestInterceptor; + +import static fish.payara.microprofile.telemetry.tracing.ejb.iiop.OpenTelemetryIiopClientInterceptor.OPENTELEMETRY_IIOP_ID; + + +/** + * IIOP Server Interceptor for propagating OpenTracing SpanContext to Payara Server. + * + * @author Andrew Pielage + */ +public class OpenTelemetryIiopServerInterceptor extends LocalObject implements ServerRequestInterceptor { + + private static final Logger LOGGER = Logger.getLogger(OpenTelemetryIiopServerInterceptor.class.getName()); + + private OpenTracingService openTracingService; + private final ThreadLocal currentScope = new ThreadLocal<>(); + private final ThreadLocal currentSpan = new ThreadLocal<>(); + + public OpenTelemetryIiopServerInterceptor(OpenTracingService openTracingService) { + this.openTracingService = openTracingService; + } + + @Override + public void receive_request_service_contexts(ServerRequestInfo serverRequestInfo) throws ForwardRequest { + // Noop + } + + @Override + public void receive_request(ServerRequestInfo serverRequestInfo) throws ForwardRequest { + ServiceContext serviceContext; + + if (!tracerAvailable()) { + return; + } + + try { + serviceContext = serverRequestInfo.get_request_service_context(OPENTELEMETRY_IIOP_ID); + if (serviceContext == null) { + return; + } + } catch (BAD_PARAM e) { + // No OTel context was propagated by the client + return; + } + + HashMap contextMap; + try (ByteArrayInputStream bis = new ByteArrayInputStream(serviceContext.context_data); + ObjectInputStream in = new ObjectInputStream(bis)) { + contextMap = (HashMap) in.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new ForwardRequest(e.getMessage(), serverRequestInfo); + } + + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + + TextMapGetter> getter = new TextMapGetter>() { + @Override + public Iterable keys(HashMap carrier) { + return carrier.keySet(); + } + + @Override + public String get(HashMap carrier, String key) { + return carrier.get(key); + } + }; + + Context parentContext = openTelemetry.getPropagators().getTextMapPropagator() + .extract(Context.current(), contextMap, getter); + + Tracer tracer = openTelemetry.getTracerProvider().get(OpenTelemetryService.INSTRUMENTATION_SCOPE_NAME); + Span span = tracer.spanBuilder("rmi") + .setParent(parentContext) + .setSpanKind(SpanKind.SERVER) + .setAttribute("component", "ejb") + .startSpan(); + + if (currentScope.get() != null) { + LOGGER.warning("Overlapping traced RMI operations identified, please report"); + } + + currentSpan.set(span); + currentScope.set(span.makeCurrent()); + } + + @Override + public void send_reply(ServerRequestInfo serverRequestInfo) { + closeScope(); + } + + @Override + public void send_exception(ServerRequestInfo serverRequestInfo) throws ForwardRequest { + closeScope(); + } + + @Override + public void send_other(ServerRequestInfo serverRequestInfo) throws ForwardRequest { + closeScope(); + } + + @Override + public String name() { + return this.getClass().getSimpleName(); + } + + @Override + public void destroy() { + + } + + private void closeScope() { + Scope scope = currentScope.get(); + if (scope != null) { + scope.close(); + currentScope.remove(); + } + Span span = currentSpan.get(); + if (span != null) { + span.end(); + currentSpan.remove(); + } + } + + private boolean tracerAvailable() { + return openTracingService.isEnabled(); + } +} From e155a5168995ed370849aaaf485adaaf8730d04f Mon Sep 17 00:00:00 2001 From: Alfonso Altamirano Date: Fri, 19 Jun 2026 20:41:42 -0600 Subject: [PATCH 6/6] FISH-13751: improving implementation for returning traces --- .../runtime/ContextSetupProviderImpl.java | 3 --- .../concurrent/runtime/InvocationContext.java | 4 ++-- .../telemetry/tracing/TracedInterceptor.java | 3 +-- .../iiop/OpenTelemetryIiopClientInterceptor.java | 5 ++--- .../iiop/OpenTelemetryIiopInterceptorFactory.java | 11 +++++++---- .../iiop/OpenTelemetryIiopServerInterceptor.java | 15 ++++++++------- .../samples/remote-ejb-tracing/pom.xml | 3 --- .../samples/remote/ejb/tracing/EjbRemote.java | 2 +- .../remote/ejb/tracing/RemoteEjbClientIT.java | 9 +++++---- .../JavaEETransactionManagerSimplified.java | 2 -- 10 files changed, 26 insertions(+), 31 deletions(-) diff --git a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java index 352a4bb1f9b..aea7ff8dbbd 100644 --- a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java +++ b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ContextSetupProviderImpl.java @@ -338,9 +338,7 @@ public ContextHandle setup(ContextHandle contextHandle) throws IllegalStateExcep private void startConcurrentContextSpan(ComponentInvocation invocation, InvocationContext handle) { Tracer tracer = openTracing.getTracer(openTracing.getApplicationName( Globals.getDefaultBaseServiceLocator().getService(InvocationManager.class))); - SpanBuilder builder = tracer.spanBuilder("executeConcurrentContext"); - Context parentContext = handle.getParentTraceContext(); if (parentContext != null) { builder.setParent(parentContext); @@ -363,7 +361,6 @@ private void startConcurrentContextSpan(ComponentInvocation invocation, Invocati } builder.setAttribute("Thread Name", Thread.currentThread().getName()); - Span span = builder.startSpan(); currentConcurrentSpan.set(span); currentConcurrentScope.set(span.makeCurrent()); diff --git a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java index 23971b93b6c..55c52bbe6d1 100644 --- a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java +++ b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/InvocationContext.java @@ -70,7 +70,7 @@ public class InvocationContext implements ContextHandle { private List threadContextSnapshots; private List threadContextRestorers; - private io.opentelemetry.context.Context parentTraceContext; + private Context parentTraceContext; public InvocationContext(ComponentInvocation invocation, ClassLoader contextClassLoader, SecurityContext securityContext, boolean useTransactionOfExecutionThread, List threadContextSnapshots, @@ -125,7 +125,7 @@ public List getThreadContextRestorers() { return threadContextRestorers; } - public io.opentelemetry.context.Context getParentTraceContext() { + public Context getParentTraceContext() { return parentTraceContext; } diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java index cc87576f7dc..3be125c6a57 100644 --- a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/TracedInterceptor.java @@ -112,8 +112,7 @@ public Object traceCdiCall(final InvocationContext invocationContext) throws Exc Span span = Span.current(); if (span.isRecording()) { - span.updateName(operationName); - span.setAttribute("otel.service.name", applicationName); + span = span.updateName(operationName).setAttribute("otel.service.name", applicationName); try (Scope scope = span.makeCurrent()) { try { return invocationContext.proceed(); diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java index b55461c42fd..94c2d067aa5 100644 --- a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopClientInterceptor.java @@ -64,7 +64,7 @@ public class OpenTelemetryIiopClientInterceptor extends LocalObject implements C private static final Logger logger = Logger.getLogger(OpenTelemetryIiopClientInterceptor.class.getName()); static final int OPENTELEMETRY_IIOP_ID = 3226428; - + @Override public void send_request(ClientRequestInfo clientRequestInfo) throws ForwardRequest { Span currentSpan = Span.current(); @@ -73,7 +73,6 @@ public void send_request(ClientRequestInfo clientRequestInfo) throws ForwardRequ } OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - HashMap contextMap = new HashMap<>(); openTelemetry.getPropagators().getTextMapPropagator() .inject(Context.current(), contextMap, HashMap::put); @@ -115,7 +114,7 @@ public void receive_other(ClientRequestInfo clientRequestInfo) throws ForwardReq @Override public String name() { - return ""; + return this.getClass().getSimpleName(); } @Override diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java index 71f091e1327..59b8adad0fa 100644 --- a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopInterceptorFactory.java @@ -89,7 +89,12 @@ public ClientRequestInterceptor createClientRequestInterceptor(ORBInitInfo info, public ServerRequestInterceptor createServerRequestInterceptor(ORBInitInfo info, Codec codec) { if (serverRequestInterceptor == null) { if (attemptCreation()) { - serverRequestInterceptor = new OpenTelemetryIiopServerInterceptor(openTracingService); + try { + serverRequestInterceptor = new OpenTelemetryIiopServerInterceptor(openTracingService); + } catch (NullPointerException nullPointerException) { + logger.log(Level.WARNING, "Could not create OpenTracing IIOP Server Interceptor - Remote EJBs will not be traced"); + return null; + } } } @@ -106,9 +111,7 @@ private boolean attemptCreation() { if (openTracingService == null) { openTracingService = serviceLocator.getService(OpenTracingService.class); - if (openTracingService == null) { - return false; - } + return openTracingService != null; } return true; diff --git a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java index 1f659574120..6d59fd20335 100644 --- a/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java +++ b/appserver/payara-appserver-modules/microprofile/telemetry/src/main/java/fish/payara/microprofile/telemetry/tracing/ejb/iiop/OpenTelemetryIiopServerInterceptor.java @@ -76,11 +76,11 @@ public class OpenTelemetryIiopServerInterceptor extends LocalObject implements S private OpenTracingService openTracingService; private final ThreadLocal currentScope = new ThreadLocal<>(); private final ThreadLocal currentSpan = new ThreadLocal<>(); - + public OpenTelemetryIiopServerInterceptor(OpenTracingService openTracingService) { this.openTracingService = openTracingService; } - + @Override public void receive_request_service_contexts(ServerRequestInfo serverRequestInfo) throws ForwardRequest { // Noop @@ -93,7 +93,7 @@ public void receive_request(ServerRequestInfo serverRequestInfo) throws ForwardR if (!tracerAvailable()) { return; } - + try { serviceContext = serverRequestInfo.get_request_service_context(OPENTELEMETRY_IIOP_ID); if (serviceContext == null) { @@ -113,22 +113,20 @@ public void receive_request(ServerRequestInfo serverRequestInfo) throws ForwardR } OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - TextMapGetter> getter = new TextMapGetter>() { @Override public Iterable keys(HashMap carrier) { return carrier.keySet(); } - + @Override public String get(HashMap carrier, String key) { return carrier.get(key); } }; - + Context parentContext = openTelemetry.getPropagators().getTextMapPropagator() .extract(Context.current(), contextMap, getter); - Tracer tracer = openTelemetry.getTracerProvider().get(OpenTelemetryService.INSTRUMENTATION_SCOPE_NAME); Span span = tracer.spanBuilder("rmi") .setParent(parentContext) @@ -183,6 +181,9 @@ private void closeScope() { } private boolean tracerAvailable() { + if (openTracingService == null) { + return false; + } return openTracingService.isEnabled(); } } diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml index bbbf0bdd38f..a613773737f 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/pom.xml @@ -121,9 +121,6 @@ maven-failsafe-plugin ${maven.failsafe.plugin.version} - - false - --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.management/javax.management.openmbean=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.management/sun.management=ALL-UNNAMED --add-opens=java.base/sun.net.www.protocol.jrt=ALL-UNNAMED --add-opens=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-opens=java.naming/javax.naming.spi=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED --add-opens=java.logging/java.util.logging=ALL-UNNAMED --add-opens=java.base/sun.net.www=ALL-UNNAMED --add-opens=java.base/sun.security.util=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.desktop/java.beans=ALL-UNNAMED --add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java index d1e1de08d8a..062e55d9632 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/main/java/fish/payara/samples/remote/ejb/tracing/EjbRemote.java @@ -3,7 +3,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) 2020-2021 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2020-2026 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development diff --git a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java index 430445f6cbf..942896769d9 100644 --- a/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java +++ b/appserver/tests/payara-samples/samples/remote-ejb-tracing/src/test/java/fish/payara/samples/remote/ejb/tracing/RemoteEjbClientIT.java @@ -46,6 +46,7 @@ import org.junit.Assert; import org.junit.Test; +import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import java.util.Properties; @@ -71,13 +72,13 @@ public class RemoteEjbClientIT { @Test public void executeRemoteEjbMethodIT() throws NamingException { Properties contextProperties = new Properties(); - contextProperties.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); + contextProperties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); contextProperties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); contextProperties.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); // enable OpenTelemetry tracing so we get our OpenTracing instance System.setProperty("otel.sdk.disabled", "false"); - javax.naming.Context context = new InitialContext(contextProperties); + Context context = new InitialContext(contextProperties); EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); String baggageItems = ejb.annotatedMethod(); Assert.assertTrue("Baggage items didn't match, received: " + baggageItems, @@ -105,13 +106,13 @@ public void executeRemoteEjbMethodIT() throws NamingException { @Test public void transactionIdAddedAsBaggageIT() throws NamingException { Properties contextProperties = new Properties(); - contextProperties.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); + contextProperties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory"); contextProperties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); contextProperties.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); // enable OpenTelemetry tracing so we get our OpenTracing instance System.setProperty("otel.sdk.disabled", "false"); - javax.naming.Context context = new InitialContext(contextProperties); + Context context = new InitialContext(contextProperties); EjbRemote ejb = (EjbRemote) context.lookup(String.format("java:global%sEjb", uri.getPath())); String baggageItems = ejb.annotatedMethod(); diff --git a/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java b/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java index 2ddc8bfcc01..3db10f7005a 100644 --- a/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java +++ b/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java @@ -1751,10 +1751,8 @@ private void addJtaEventTraceLog(RequestTraceSpanLog spanLog, JavaEETransaction if (span.isRecording()) { AttributesBuilder attrsBuilder = Attributes.builder(); spanLog.getLogEntries().forEach(attrsBuilder::put); - String eventName = spanLog.getLogEntries().getOrDefault("logEvent", "jtaTransactionEvent"); span.addEvent(eventName, attrsBuilder.build(), spanLog.getTimeMillis(), TimeUnit.MILLISECONDS); - // Add transaction ID as baggage item if (tx != null) { if (tx.getClass().equals(JavaEETransactionImpl.class)) {