Skip to content

Commit

Permalink
Merge pull request #3041 from Pandrex247/PAYARA-2924-NPE-on-Jaxrs-Asy…
Browse files Browse the repository at this point in the history
…nc-Server

PAYARA-2924 NPE on JAX-RS Async-Server EE7 Sample
  • Loading branch information
arjantijms authored Aug 24, 2018
2 parents 5738bd9 + c0f00cf commit 7ab5253
Show file tree
Hide file tree
Showing 14 changed files with 287 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ public void addSpanTag(String name, String value) {
}
}

public String getSpanTag(String tag) {
return spanTags.get(tag);
}

public Map<String, String> getSpanTags() {
return spanTags;
}

public void addSpanLog(RequestTraceSpanLog spanLog) {
spanLogs.add(spanLog);
}
Expand Down
10 changes: 10 additions & 0 deletions appserver/concurrent/concurrent-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@
<artifactId>healthcheck-stuck</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>fish.payara.payara-modules</groupId>
<artifactId>opentracing-adapter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile.opentracing</groupId>
<artifactId>microprofile-opentracing-api</artifactId>
<version>${microprofile-opentracing.version}</version>
</dependency>
</dependencies>
</project>

Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import com.sun.enterprise.security.SecurityContext;
import com.sun.enterprise.transaction.api.JavaEETransactionManager;
import com.sun.enterprise.util.Utility;
import fish.payara.opentracing.propagation.MapToTextMap;
import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.concurrent.LogFacade;
Expand All @@ -65,9 +66,13 @@
import java.util.logging.Logger;

import fish.payara.nucleus.requesttracing.RequestTracingService;
import fish.payara.notification.requesttracing.RequestTraceSpan;
import fish.payara.nucleus.healthcheck.stuck.StuckThreadsStore;
import fish.payara.notification.requesttracing.EventType;
import fish.payara.notification.requesttracing.RequestTraceSpanContext;
import fish.payara.opentracing.OpenTracingService;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.Tracer.SpanBuilder;
import io.opentracing.propagation.Format;
import org.glassfish.internal.api.Globals;

public class ContextSetupProviderImpl implements ContextSetupProvider {
Expand All @@ -88,6 +93,7 @@ static enum CONTEXT_TYPE {CLASSLOADING, SECURITY, NAMING, WORKAREA}
private boolean classloading, security, naming, workArea;

private RequestTracingService requestTracing;
private OpenTracingService openTracing;
private StuckThreadsStore stuckThreads;

public ContextSetupProviderImpl(InvocationManager invocationManager,
Expand All @@ -114,6 +120,12 @@ public ContextSetupProviderImpl(InvocationManager invocationManager,
logger.log(Level.INFO, "Error retrieving Stuck Threads Sore Healthcheck service "
+ "during initialisation of Concurrent Context - NullPointerException");
}
try {
this.openTracing = Globals.getDefaultHabitat().getService(OpenTracingService.class);
} catch (NullPointerException ex) {
logger.log(Level.INFO, "Error retrieving OpenTracing service "
+ "during initialisation of Concurrent Context - NullPointerException");
}

for (CONTEXT_TYPE contextType: contextTypes) {
switch(contextType) {
Expand Down Expand Up @@ -221,8 +233,7 @@ else if(backupClassLoader != null) {
}

if (requestTracing != null && requestTracing.isRequestTracingEnabled()) {
RequestTraceSpan span = constructConcurrentContextSpan(invocation);
requestTracing.startTrace(span);
startConcurrentContextSpan(invocation, handle);
}

if (stuckThreads != null){
Expand All @@ -231,20 +242,40 @@ else if(backupClassLoader != null) {

return new InvocationContext(invocation, resetClassLoader, resetSecurityContext, handle.isUseTransactionOfExecutionThread());
}

private RequestTraceSpan constructConcurrentContextSpan(ComponentInvocation invocation) {
RequestTraceSpan span = new RequestTraceSpan(EventType.TRACE_START, "executeConcurrentContext");

private void startConcurrentContextSpan(ComponentInvocation invocation, InvocationContext handle) {
Tracer tracer = openTracing.getTracer(openTracing.getApplicationName(
Globals.getDefaultBaseServiceLocator().getService(InvocationManager.class)));

span.addSpanTag("App Name", invocation.getAppName());
span.addSpanTag("Component ID", invocation.getComponentId());
span.addSpanTag("Module Name", invocation.getModuleName());
Object instance = invocation.getInstance();
if (instance != null) {
span.addSpanTag("Class Name", instance.getClass().getName());
}
span.addSpanTag("Thread Name", Thread.currentThread().getName());
SpanContext spanContext = tracer.extract(Format.Builtin.TEXT_MAP, new MapToTextMap(handle.getSpanContextMap()));

return span;
if (spanContext != null) {
// Start a trace in the request tracing system
SpanBuilder builder = tracer.buildSpan("executeConcurrentContext")
.asChildOf(spanContext)
.withTag("App Name", invocation.getAppName())
.withTag("Component ID", invocation.getComponentId())
.withTag("Module Name", invocation.getModuleName());

Object instance = invocation.getInstance();
if (instance != null) {
builder.withTag("Class Name", instance.getClass().getName());
}

builder.withTag("Thread Name", Thread.currentThread().getName());

// Check for the presence of a propagated parent operation name
try {
String operationName = ((RequestTraceSpanContext) spanContext).getBaggageItems().get("operation.name");
if (operationName != null) {
builder.withTag("Parent Operation Name", operationName);
}
} catch (ClassCastException cce) {
logger.log(Level.FINE, "ClassCastException caught converting Span Context", cce);
}

builder.startActive(true);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,37 @@

package org.glassfish.concurrent.runtime;

import com.hazelcast.logging.Logger;
import com.sun.enterprise.security.SecurityContext;
import fish.payara.notification.requesttracing.RequestTraceSpan;
import fish.payara.notification.requesttracing.RequestTraceSpanContext;
import fish.payara.opentracing.propagation.MapToTextMap;
import fish.payara.nucleus.requesttracing.RequestTracingService;
import fish.payara.opentracing.OpenTracingService;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.enterprise.concurrent.spi.ContextHandle;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;

import javax.security.auth.Subject;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.Globals;

public class InvocationContext implements ContextHandle {

private transient ComponentInvocation invocation;
private transient ClassLoader contextClassLoader;
private transient SecurityContext securityContext;
private transient Map spanContextMap;
private boolean useTransactionOfExecutionThread;

static final long serialVersionUID = 5642415011655486579L;
Expand All @@ -64,8 +81,60 @@ public InvocationContext(ComponentInvocation invocation, ClassLoader contextClas
this.contextClassLoader = contextClassLoader;
this.securityContext = securityContext;
this.useTransactionOfExecutionThread = useTransactionOfExecutionThread;
saveTracingContext();
}

private void saveTracingContext() {
ServiceLocator serviceLocator = Globals.getDefaultBaseServiceLocator();

if (serviceLocator != null) {
RequestTracingService requestTracing = serviceLocator.getService(RequestTracingService.class);
OpenTracingService openTracing = serviceLocator.getService(OpenTracingService.class);

// Check that there's actually a trace running
if (requestTracing != null && requestTracing.isRequestTracingEnabled()
&& requestTracing.isTraceInProgress() && openTracing != null) {

Tracer tracer = openTracing.getTracer(openTracing.getApplicationName(
serviceLocator.getService(InvocationManager.class)));

SpanContext spanContext = null;

// Check if there's an active Span running
Span activeSpan = tracer.activeSpan();
if (activeSpan != null) {
// The traceId is likely incorrect at this point as it initialises as a random UUID
try {
((RequestTraceSpan) activeSpan).setTraceId(requestTracing.getConversationID());
} catch (ClassCastException cce) {
Logger.getLogger(InvocationContext.class).log(
Level.FINE,
"ClassCastException caught converting Span",
cce);
}

spanContext = activeSpan.context();
} else {
// Create a new span context using the starting span as a parent - the request tracing service doesn't
// know about unfinished spans so we can't get the actual parent with the current impl
spanContext = new RequestTraceSpanContext(
requestTracing.getConversationID(),
requestTracing.getStartingTraceID());
}

// Check to see if we're using the mock tracer to prevent ClassCastExceptions
try {
tracer.inject(spanContext, Format.Builtin.TEXT_MAP, new MapToTextMap(spanContextMap = new HashMap()));
} catch (ClassCastException cce) {
Logger.getLogger(InvocationContext.class).log(
Level.FINE,
"ClassCastException caught injecting SpanContext",
cce);
}
}
}
}

public ComponentInvocation getInvocation() {
return invocation;
}
Expand All @@ -81,7 +150,11 @@ public SecurityContext getSecurityContext() {
public boolean isUseTransactionOfExecutionThread() {
return useTransactionOfExecutionThread;
}


public Map getSpanContextMap() {
return spanContextMap;
}

private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.writeBoolean(useTransactionOfExecutionThread);
// write values for invocation
Expand Down Expand Up @@ -160,5 +233,4 @@ private ComponentInvocation createComponentInvocation(String componentId, String
return newInv;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import java.util.AbstractMap;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -100,32 +99,34 @@ public void postConstruct() {
// Before method invocation
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
// ***** Request Tracing Service Instrumentation *****
// If request tracing is enabled, and there's a trace actually in progress, add the propagation headers
if (requestTracing != null && requestTracing.isRequestTracingEnabled() && requestTracing.isTraceInProgress()) {
// Check that we aren't overwriting a header
if (!requestContext.getHeaders().containsKey(PropagationHeaders.PROPAGATED_TRACE_ID)) {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_TRACE_ID,
requestTracing.getConversationID());
}
if (requestTracing != null && requestTracing.isRequestTracingEnabled()) {
// ***** Request Tracing Service Instrumentation *****
// If there is a trace in progress, add the propagation headers with the relevant details
if (requestTracing.isTraceInProgress()) {
// Check that we aren't overwriting a header
if (!requestContext.getHeaders().containsKey(PropagationHeaders.PROPAGATED_TRACE_ID)) {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_TRACE_ID,
requestTracing.getConversationID());
}

// Check that we aren't overwriting a header
if (!requestContext.getHeaders().containsKey(PropagationHeaders.PROPAGATED_PARENT_ID)) {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_PARENT_ID,
requestTracing.getStartingTraceID());
}
// Check that we aren't overwriting a header
if (!requestContext.getHeaders().containsKey(PropagationHeaders.PROPAGATED_PARENT_ID)) {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_PARENT_ID,
requestTracing.getStartingTraceID());
}

// Check that we aren't overwriting a relationship type
if (!requestContext.getHeaders().containsKey(PropagationHeaders.PROPAGATED_RELATIONSHIP_TYPE)) {
if (requestContext.getMethod().equals("POST")) {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_RELATIONSHIP_TYPE,
RequestTraceSpan.SpanContextRelationshipType.FollowsFrom);
} else {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_RELATIONSHIP_TYPE,
RequestTraceSpan.SpanContextRelationshipType.ChildOf);
// Check that we aren't overwriting a relationship type
if (!requestContext.getHeaders().containsKey(PropagationHeaders.PROPAGATED_RELATIONSHIP_TYPE)) {
if (requestContext.getMethod().equals("POST")) {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_RELATIONSHIP_TYPE,
RequestTraceSpan.SpanContextRelationshipType.FollowsFrom);
} else {
requestContext.getHeaders().add(PropagationHeaders.PROPAGATED_RELATIONSHIP_TYPE,
RequestTraceSpan.SpanContextRelationshipType.ChildOf);
}
}
}

// ***** OpenTracing Instrumentation *****
// Get or create the tracer instance for this application
Tracer tracer = openTracing.getTracer(openTracing.getApplicationName(
Expand All @@ -142,33 +143,33 @@ public void filter(ClientRequestContext requestContext) throws IOException {
// This is required to account for asynchronous client requests
SpanContext parentSpanContext = (SpanContext) requestContext.getProperty(
PropagationHeaders.OPENTRACING_PROPAGATED_SPANCONTEXT);

if (parentSpanContext != null) {
spanBuilder.asChildOf(parentSpanContext);
}

// If there is a propagated span context, set it as a parent of the new span
parentSpanContext = tracer.extract(Format.Builtin.HTTP_HEADERS,
new MultivaluedMapToTextMap(requestContext.getHeaders()));
if (parentSpanContext != null) {
spanBuilder.asChildOf(parentSpanContext);

parentSpanContext = tracer.extract(Format.Builtin.HTTP_HEADERS, new MultivaluedMapToTextMap(requestContext.getHeaders()));
if (parentSpanContext != null) {
spanBuilder.asChildOf(parentSpanContext);
}
}

// Start the span and mark it as active
Span activeSpan = spanBuilder.startActive(true).span();

// Inject the active span context for propagation
tracer.inject(
activeSpan.context(),
Format.Builtin.HTTP_HEADERS,
new MultivaluedMapToTextMap(requestContext.getHeaders()));
// Inject the active span context for propagation
tracer.inject(
activeSpan.context(),
Format.Builtin.HTTP_HEADERS,
new MultivaluedMapToTextMap(requestContext.getHeaders()));
}
}

// After method invocation
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
// If request tracing is enabled, and there's a trace actually in progress, add info about method
if (requestTracing != null && requestTracing.isRequestTracingEnabled() && requestTracing.isTraceInProgress()) {
if (requestTracing != null && requestTracing.isRequestTracingEnabled()) {
// Get the active span from the application's tracer instance
try (Scope activeScope = openTracing.getTracer(openTracing.getApplicationName(
serviceLocator.getService(InvocationManager.class)))
Expand Down
Loading

0 comments on commit 7ab5253

Please sign in to comment.