Pass around context more instead of span (HttpServerTracer) (#1810)
This commit is contained in:
parent
01b4345742
commit
0bd85d7b7f
|
|
@ -12,7 +12,6 @@ import io.opentelemetry.api.trace.SpanBuilder;
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.api.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.api.trace.attributes.SemanticAttributes;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
|
||||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
@ -35,17 +34,29 @@ public abstract class HttpServerTracer<REQUEST, RESPONSE, CONNECTION, STORAGE> e
|
||||||
super(tracer);
|
super(tracer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context startSpan(REQUEST request, CONNECTION connection, Method origin) {
|
public Context startSpan(REQUEST request, CONNECTION connection, STORAGE storage, Method origin) {
|
||||||
String spanName = spanNameForMethod(origin);
|
String spanName = spanNameForMethod(origin);
|
||||||
return startSpan(request, connection, spanName);
|
return startSpan(request, connection, storage, spanName);
|
||||||
}
|
|
||||||
|
|
||||||
public Context startSpan(REQUEST request, CONNECTION connection, String spanName) {
|
|
||||||
return startSpan(request, connection, spanName, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context startSpan(
|
public Context startSpan(
|
||||||
REQUEST request, CONNECTION connection, String spanName, long startTimestamp) {
|
REQUEST request, CONNECTION connection, STORAGE storage, String spanName) {
|
||||||
|
return startSpan(request, connection, storage, spanName, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context startSpan(
|
||||||
|
REQUEST request,
|
||||||
|
CONNECTION connection,
|
||||||
|
@Nullable STORAGE storage,
|
||||||
|
String spanName,
|
||||||
|
long startTimestamp) {
|
||||||
|
|
||||||
|
// not checking if inside of nested SERVER span because of concerns about context leaking
|
||||||
|
// and so always starting with a clean context here
|
||||||
|
|
||||||
|
// also we can't conditionally start a span in this method, because the caller won't know
|
||||||
|
// whether to call end() or not on the Span in the returned Context
|
||||||
|
|
||||||
Context parentContext = extract(request, getGetter());
|
Context parentContext = extract(request, getGetter());
|
||||||
SpanBuilder builder = tracer.spanBuilder(spanName).setSpanKind(SERVER).setParent(parentContext);
|
SpanBuilder builder = tracer.spanBuilder(spanName).setSpanKind(SERVER).setParent(parentContext);
|
||||||
|
|
||||||
|
|
@ -58,67 +69,51 @@ public abstract class HttpServerTracer<REQUEST, RESPONSE, CONNECTION, STORAGE> e
|
||||||
onRequest(span, request);
|
onRequest(span, request);
|
||||||
onConnectionAndRequest(span, connection, request);
|
onConnectionAndRequest(span, connection, request);
|
||||||
|
|
||||||
return parentContext.with(span);
|
Context context = parentContext.with(CONTEXT_SERVER_SPAN_KEY, span).with(span);
|
||||||
|
attachServerContext(context, storage);
|
||||||
|
|
||||||
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new scoped context, based on the current context, with the given span.
|
* Convenience method. Delegates to {@link #end(Context, Object, long)}, passing {@code timestamp}
|
||||||
*
|
|
||||||
* <p>Attaches new context to the request to avoid creating duplicate server spans.
|
|
||||||
*/
|
|
||||||
public Scope startScope(Span span, STORAGE storage) {
|
|
||||||
return startScope(span, storage, Context.current());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new scoped context, based on the given context, with the given span.
|
|
||||||
*
|
|
||||||
* <p>Attaches new context to the request to avoid creating duplicate server spans.
|
|
||||||
*/
|
|
||||||
public Scope startScope(Span span, STORAGE storage, Context context) {
|
|
||||||
// TODO we could do this in one go, but TracingContextUtils.CONTEXT_SPAN_KEY is private
|
|
||||||
Context newContext = context.with(CONTEXT_SERVER_SPAN_KEY, span).with(span);
|
|
||||||
attachServerContext(newContext, storage);
|
|
||||||
return newContext.makeCurrent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method. Delegates to {@link #end(Span, Object, long)}, passing {@code timestamp}
|
|
||||||
* value of {@code -1}.
|
* value of {@code -1}.
|
||||||
*/
|
*/
|
||||||
// TODO should end methods remove SPAN attribute from request as well?
|
// TODO should end methods remove SPAN attribute from request as well?
|
||||||
public void end(Span span, RESPONSE response) {
|
public void end(Context context, RESPONSE response) {
|
||||||
end(span, response, -1);
|
end(context, response, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should end methods remove SPAN attribute from request as well?
|
// TODO should end methods remove SPAN attribute from request as well?
|
||||||
public void end(Span span, RESPONSE response, long timestamp) {
|
public void end(Context context, RESPONSE response, long timestamp) {
|
||||||
|
Span span = Span.fromContext(context);
|
||||||
setStatus(span, responseStatus(response));
|
setStatus(span, responseStatus(response));
|
||||||
endSpan(span, timestamp);
|
endSpan(span, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method. Delegates to {@link #endExceptionally(Span, Throwable, Object)}, passing
|
* Convenience method. Delegates to {@link #endExceptionally(Context, Throwable, Object)}, passing
|
||||||
* {@code response} value of {@code null}.
|
* {@code response} value of {@code null}.
|
||||||
*/
|
*/
|
||||||
@Override
|
public void endExceptionally(Context context, Throwable throwable) {
|
||||||
public void endExceptionally(Span span, Throwable throwable) {
|
endExceptionally(context, throwable, null);
|
||||||
endExceptionally(span, throwable, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method. Delegates to {@link #endExceptionally(Span, Throwable, Object, long)},
|
* Convenience method. Delegates to {@link #endExceptionally(Context, Throwable, Object, long)},
|
||||||
* passing {@code timestamp} value of {@code -1}.
|
* passing {@code timestamp} value of {@code -1}.
|
||||||
*/
|
*/
|
||||||
public void endExceptionally(Span span, Throwable throwable, RESPONSE response) {
|
public void endExceptionally(Context context, Throwable throwable, RESPONSE response) {
|
||||||
endExceptionally(span, throwable, response, -1);
|
endExceptionally(context, throwable, response, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If {@code response} is {@code null}, the {@code http.status_code} will be set to {@code 500}
|
* If {@code response} is {@code null}, the {@code http.status_code} will be set to {@code 500}
|
||||||
* and the {@link Span} status will be set to {@link io.opentelemetry.api.trace.StatusCode#ERROR}.
|
* and the {@link Span} status will be set to {@link io.opentelemetry.api.trace.StatusCode#ERROR}.
|
||||||
*/
|
*/
|
||||||
public void endExceptionally(Span span, Throwable throwable, RESPONSE response, long timestamp) {
|
public void endExceptionally(
|
||||||
|
Context context, Throwable throwable, RESPONSE response, long timestamp) {
|
||||||
|
Span span = Span.fromContext(context);
|
||||||
onError(span, unwrapThrowable(throwable));
|
onError(span, unwrapThrowable(throwable));
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
setStatus(span, 500);
|
setStatus(span, 500);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ package io.opentelemetry.instrumentation.servlet;
|
||||||
import io.opentelemetry.api.trace.Span;
|
import io.opentelemetry.api.trace.Span;
|
||||||
import io.opentelemetry.api.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.api.trace.attributes.SemanticAttributes;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
|
||||||
import io.opentelemetry.context.propagation.TextMapPropagator.Getter;
|
import io.opentelemetry.context.propagation.TextMapPropagator.Getter;
|
||||||
import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
|
import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
|
||||||
import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
|
import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
|
||||||
|
|
@ -26,19 +25,12 @@ public abstract class ServletHttpServerTracer<RESPONSE>
|
||||||
private static final Logger log = LoggerFactory.getLogger(ServletHttpServerTracer.class);
|
private static final Logger log = LoggerFactory.getLogger(ServletHttpServerTracer.class);
|
||||||
|
|
||||||
public Context startSpan(HttpServletRequest request) {
|
public Context startSpan(HttpServletRequest request) {
|
||||||
return startSpan(request, request, getSpanName(request));
|
Context context = startSpan(request, request, request, getSpanName(request));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scope startScope(Span span, HttpServletRequest request) {
|
|
||||||
Context context = Context.current();
|
|
||||||
// if we start returning Context from startSpan() then we can add ServletContextPath there
|
|
||||||
// (https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1481)
|
|
||||||
String contextPath = request.getContextPath();
|
String contextPath = request.getContextPath();
|
||||||
if (contextPath != null && !contextPath.isEmpty() && !contextPath.equals("/")) {
|
if (contextPath != null && !contextPath.isEmpty() && !contextPath.equals("/")) {
|
||||||
context = context.with(ServletContextPath.CONTEXT_KEY, contextPath);
|
context = context.with(ServletContextPath.CONTEXT_KEY, contextPath);
|
||||||
}
|
}
|
||||||
return super.startScope(span, request, context);
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -109,10 +101,10 @@ public abstract class ServletHttpServerTracer<RESPONSE>
|
||||||
return super.unwrapThrowable(result);
|
return super.unwrapThrowable(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrincipal(Span span, HttpServletRequest request) {
|
public void setPrincipal(Context context, HttpServletRequest request) {
|
||||||
Principal principal = request.getUserPrincipal();
|
Principal principal = request.getUserPrincipal();
|
||||||
if (principal != null) {
|
if (principal != null) {
|
||||||
span.setAttribute(SemanticAttributes.ENDUSER_ID, principal.getName());
|
Span.fromContext(context).setAttribute(SemanticAttributes.ENDUSER_ID, principal.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,8 @@ import akka.http.scaladsl.model.HttpRequest;
|
||||||
import akka.http.scaladsl.model.HttpResponse;
|
import akka.http.scaladsl.model.HttpResponse;
|
||||||
import akka.stream.Materializer;
|
import akka.stream.Materializer;
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
|
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
|
||||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -96,14 +94,13 @@ public class AkkaHttpServerInstrumentationModule extends InstrumentationModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpResponse apply(HttpRequest request) {
|
public HttpResponse apply(HttpRequest request) {
|
||||||
Context ctx = tracer().startSpan(request, request, "akka.request");
|
Context ctx = tracer().startSpan(request, request, null, "akka.request");
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(ctx);
|
try (Scope ignored = ctx.makeCurrent()) {
|
||||||
try (Scope ignored = tracer().startScope(span, null)) {
|
|
||||||
HttpResponse response = userHandler.apply(request);
|
HttpResponse response = userHandler.apply(request);
|
||||||
tracer().end(span, response);
|
tracer().end(ctx, response);
|
||||||
return response;
|
return response;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
tracer().endExceptionally(span, t);
|
tracer().endExceptionally(ctx, t);
|
||||||
throw t;
|
throw t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -122,29 +119,28 @@ public class AkkaHttpServerInstrumentationModule extends InstrumentationModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Future<HttpResponse> apply(HttpRequest request) {
|
public Future<HttpResponse> apply(HttpRequest request) {
|
||||||
Context ctx = tracer().startSpan(request, request, "akka.request");
|
Context ctx = tracer().startSpan(request, request, null, "akka.request");
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(ctx);
|
try (Scope ignored = ctx.makeCurrent()) {
|
||||||
try (Scope ignored = tracer().startScope(span, null)) {
|
|
||||||
return userHandler
|
return userHandler
|
||||||
.apply(request)
|
.apply(request)
|
||||||
.transform(
|
.transform(
|
||||||
new AbstractFunction1<HttpResponse, HttpResponse>() {
|
new AbstractFunction1<HttpResponse, HttpResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public HttpResponse apply(HttpResponse response) {
|
public HttpResponse apply(HttpResponse response) {
|
||||||
tracer().end(span, response);
|
tracer().end(ctx, response);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new AbstractFunction1<Throwable, Throwable>() {
|
new AbstractFunction1<Throwable, Throwable>() {
|
||||||
@Override
|
@Override
|
||||||
public Throwable apply(Throwable t) {
|
public Throwable apply(Throwable t) {
|
||||||
tracer().endExceptionally(span, t);
|
tracer().endExceptionally(ctx, t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
executionContext);
|
executionContext);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
tracer().endExceptionally(span, t);
|
tracer().endExceptionally(ctx, t);
|
||||||
throw t;
|
throw t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,9 @@ public class OpenTelemetryService extends SimpleDecoratingHttpService {
|
||||||
long requestStartTimeMicros =
|
long requestStartTimeMicros =
|
||||||
ctx.log().ensureAvailable(RequestLogProperty.REQUEST_START_TIME).requestStartTimeMicros();
|
ctx.log().ensureAvailable(RequestLogProperty.REQUEST_START_TIME).requestStartTimeMicros();
|
||||||
long requestStartTimeNanos = TimeUnit.MICROSECONDS.toNanos(requestStartTimeMicros);
|
long requestStartTimeNanos = TimeUnit.MICROSECONDS.toNanos(requestStartTimeMicros);
|
||||||
Context context = serverTracer.startSpan(req, ctx, spanName, requestStartTimeNanos);
|
Context context = serverTracer.startSpan(req, ctx, null, spanName, requestStartTimeNanos);
|
||||||
Span span = Span.fromContext(context);
|
|
||||||
|
|
||||||
if (span.isRecording()) {
|
if (Span.fromContext(context).isRecording()) {
|
||||||
ctx.log()
|
ctx.log()
|
||||||
.whenComplete()
|
.whenComplete()
|
||||||
.thenAccept(
|
.thenAccept(
|
||||||
|
|
@ -70,14 +69,14 @@ public class OpenTelemetryService extends SimpleDecoratingHttpService {
|
||||||
long requestEndTimeNanos = requestStartTimeNanos + log.responseDurationNanos();
|
long requestEndTimeNanos = requestStartTimeNanos + log.responseDurationNanos();
|
||||||
if (log.responseCause() != null) {
|
if (log.responseCause() != null) {
|
||||||
serverTracer.endExceptionally(
|
serverTracer.endExceptionally(
|
||||||
span, log.responseCause(), log, requestEndTimeNanos);
|
context, log.responseCause(), log, requestEndTimeNanos);
|
||||||
} else {
|
} else {
|
||||||
serverTracer.end(span, log, requestEndTimeNanos);
|
serverTracer.end(context, log, requestEndTimeNanos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Scope ignored = span.makeCurrent()) {
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
return unwrap().serve(ctx, req);
|
return unwrap().serve(ctx, req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
||||||
|
|
@ -31,11 +29,9 @@ public class HttpCodecFilterAdvice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader;
|
HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader;
|
||||||
Context extractedContext = tracer().startSpan(httpRequest, httpRequest, method);
|
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(extractedContext);
|
|
||||||
|
|
||||||
// We don't actually want to attach new context to this thread, as actual request will continue
|
// We don't want to attach the new context to this thread, as actual request will continue on
|
||||||
// on some other thread. But we do want to attach that new context to FilterChainContext
|
// some other thread where we will read and attach it via tracer().getServerContext(ctx).
|
||||||
tracer().startScope(span, ctx).close();
|
tracer().startSpan(httpRequest, httpRequest, ctx, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
||||||
|
|
@ -31,11 +29,9 @@ public class HttpCodecFilterOldAdvice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader;
|
HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader;
|
||||||
Context extractedContext = tracer().startSpan(httpRequest, httpRequest, method);
|
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(extractedContext);
|
|
||||||
|
|
||||||
// We don't actually want to attach new context to this thread, as actual request will continue
|
// We don't want to attach the new context to this thread, as actual request will continue on
|
||||||
// on some other thread. But we do want to attach that new context to FilterChainContext
|
// some other thread where we will read and attach it via tracer().getServerContext(ctx).
|
||||||
tracer().startScope(span, ctx).close();
|
tracer().startSpan(httpRequest, httpRequest, ctx, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
import io.opentelemetry.context.Context;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
||||||
import org.glassfish.grizzly.http.HttpResponsePacket;
|
import org.glassfish.grizzly.http.HttpResponsePacket;
|
||||||
|
|
@ -16,9 +16,9 @@ public class HttpServerFilterAdvice {
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
public static void onExit(
|
public static void onExit(
|
||||||
@Advice.Argument(0) FilterChainContext ctx, @Advice.Argument(2) HttpResponsePacket response) {
|
@Advice.Argument(0) FilterChainContext ctx, @Advice.Argument(2) HttpResponsePacket response) {
|
||||||
Span span = tracer().getServerSpan(ctx);
|
Context context = tracer().getServerContext(ctx);
|
||||||
if (span != null) {
|
if (context != null) {
|
||||||
tracer().end(span, response);
|
tracer().end(context, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,8 @@ package io.opentelemetry.javaagent.instrumentation.jetty;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.jetty.JettyHttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.jetty.JettyHttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import io.opentelemetry.javaagent.instrumentation.servlet.v3_0.TagSettingAsyncListener;
|
import io.opentelemetry.javaagent.instrumentation.servlet.v3_0.TagSettingAsyncListener;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
@ -25,7 +23,7 @@ public class JettyHandlerAdvice {
|
||||||
@Advice.Origin Method method,
|
@Advice.Origin Method method,
|
||||||
@Advice.This Object source,
|
@Advice.This Object source,
|
||||||
@Advice.Argument(value = 2, readOnly = false) HttpServletRequest request,
|
@Advice.Argument(value = 2, readOnly = false) HttpServletRequest request,
|
||||||
@Advice.Local("otelSpan") Span span,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
|
|
||||||
Context attachedContext = tracer().getServerContext(request);
|
Context attachedContext = tracer().getServerContext(request);
|
||||||
|
|
@ -34,9 +32,8 @@ public class JettyHandlerAdvice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context ctx = tracer().startSpan(request, request, method);
|
context = tracer().startSpan(request, request, request, method);
|
||||||
span = Java8BytecodeBridge.spanFromContext(ctx);
|
scope = context.makeCurrent();
|
||||||
scope = tracer().startScope(span, request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
|
@ -44,22 +41,22 @@ public class JettyHandlerAdvice {
|
||||||
@Advice.Argument(2) HttpServletRequest request,
|
@Advice.Argument(2) HttpServletRequest request,
|
||||||
@Advice.Argument(3) HttpServletResponse response,
|
@Advice.Argument(3) HttpServletResponse response,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
@Advice.Local("otelSpan") Span span,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scope.close();
|
scope.close();
|
||||||
|
|
||||||
if (span == null) {
|
if (context == null) {
|
||||||
// an existing span was found
|
// an existing span was found
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer().setPrincipal(span, request);
|
tracer().setPrincipal(context, request);
|
||||||
|
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
tracer().endExceptionally(span, throwable, response);
|
tracer().endExceptionally(context, throwable, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +65,9 @@ public class JettyHandlerAdvice {
|
||||||
// In case of async servlets wait for the actual response to be ready
|
// In case of async servlets wait for the actual response to be ready
|
||||||
if (request.isAsyncStarted()) {
|
if (request.isAsyncStarted()) {
|
||||||
try {
|
try {
|
||||||
request.getAsyncContext().addListener(new TagSettingAsyncListener(responseHandled, span));
|
request
|
||||||
|
.getAsyncContext()
|
||||||
|
.addListener(new TagSettingAsyncListener(responseHandled, context));
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
// org.eclipse.jetty.server.Request may throw an exception here if request became
|
// org.eclipse.jetty.server.Request may throw an exception here if request became
|
||||||
// finished after check above. We just ignore that exception and move on.
|
// finished after check above. We just ignore that exception and move on.
|
||||||
|
|
@ -77,7 +76,7 @@ public class JettyHandlerAdvice {
|
||||||
|
|
||||||
// Check again in case the request finished before adding the listener.
|
// Check again in case the request finished before adding the listener.
|
||||||
if (!request.isAsyncStarted() && responseHandled.compareAndSet(false, true)) {
|
if (!request.isAsyncStarted() && responseHandled.compareAndSet(false, true)) {
|
||||||
tracer().end(span, response);
|
tracer().end(context, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,9 @@ package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.NettyHttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.NettyHttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
|
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
|
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
|
|
@ -46,12 +44,13 @@ public class HttpServerRequestTracingHandler extends SimpleChannelUpstreamHandle
|
||||||
|
|
||||||
HttpRequest request = (HttpRequest) msg.getMessage();
|
HttpRequest request = (HttpRequest) msg.getMessage();
|
||||||
|
|
||||||
Context context = tracer().startSpan(request, ctx.getChannel(), "netty.request");
|
Context context =
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(context);
|
tracer().startSpan(request, ctx.getChannel(), channelTraceContext, "netty.request");
|
||||||
try (Scope ignored = tracer().startScope(span, channelTraceContext)) {
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
ctx.sendUpstream(msg);
|
ctx.sendUpstream(msg);
|
||||||
|
// the span is ended normally in HttpServerResponseTracingHandler
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
tracer().endExceptionally(span, throwable);
|
tracer().endExceptionally(context, throwable);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.NettyHttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.NettyHttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
|
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
|
||||||
|
|
@ -37,13 +36,12 @@ public class HttpServerResponseTracingHandler extends SimpleChannelDownstreamHan
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span span = Span.fromContext(context);
|
|
||||||
try (Scope ignored = context.makeCurrent()) {
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
ctx.sendDownstream(msg);
|
ctx.sendDownstream(msg);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
tracer().endExceptionally(span, throwable);
|
tracer().endExceptionally(context, throwable);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
tracer().end(span, (HttpResponse) msg.getMessage());
|
tracer().end(context, (HttpResponse) msg.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,8 @@ import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
|
|
||||||
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
|
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
|
@ -34,12 +32,12 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context context = tracer().startSpan((HttpRequest) msg, channel, "netty.request");
|
Context context = tracer().startSpan((HttpRequest) msg, channel, channel, "netty.request");
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(context);
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
try (Scope ignored = tracer().startScope(span, channel)) {
|
|
||||||
ctx.fireChannelRead(msg);
|
ctx.fireChannelRead(msg);
|
||||||
|
// the span is ended normally in HttpServerResponseTracingHandler
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
tracer().endExceptionally(span, throwable);
|
tracer().endExceptionally(context, throwable);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
|
|
||||||
|
|
@ -25,13 +24,12 @@ public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdap
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span span = Span.fromContext(context);
|
|
||||||
try (Scope ignored = context.makeCurrent()) {
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
ctx.write(msg, prm);
|
ctx.write(msg, prm);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
tracer().endExceptionally(span, throwable);
|
tracer().endExceptionally(context, throwable);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
tracer().end(span, (HttpResponse) msg);
|
tracer().end(context, (HttpResponse) msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,8 @@ import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
|
|
||||||
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
|
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
|
@ -34,12 +32,12 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context context = tracer().startSpan((HttpRequest) msg, channel, "netty.request");
|
Context context = tracer().startSpan((HttpRequest) msg, channel, channel, "netty.request");
|
||||||
Span span = Java8BytecodeBridge.spanFromContext(context);
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
try (Scope ignored = tracer().startScope(span, channel)) {
|
|
||||||
ctx.fireChannelRead(msg);
|
ctx.fireChannelRead(msg);
|
||||||
|
// the span is ended normally in HttpServerResponseTracingHandler
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
tracer().endExceptionally(span, throwable);
|
tracer().endExceptionally(context, throwable);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
|
|
||||||
|
|
@ -25,13 +24,12 @@ public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdap
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span span = Span.fromContext(context);
|
|
||||||
try (Scope ignored = context.makeCurrent()) {
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
ctx.write(msg, prm);
|
ctx.write(msg, prm);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
tracer().endExceptionally(span, throwable);
|
tracer().endExceptionally(context, throwable);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
tracer().end(span, (HttpResponse) msg);
|
tracer().end(context, (HttpResponse) msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,9 @@ package io.opentelemetry.javaagent.instrumentation.servlet.v2_2;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.servlet.v2_2.Servlet2HttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.servlet.v2_2.Servlet2HttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
|
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
@ -24,7 +22,7 @@ public class Servlet2Advice {
|
||||||
public static void onEnter(
|
public static void onEnter(
|
||||||
@Advice.Argument(0) ServletRequest request,
|
@Advice.Argument(0) ServletRequest request,
|
||||||
@Advice.Argument(value = 1, typing = Assigner.Typing.DYNAMIC) ServletResponse response,
|
@Advice.Argument(value = 1, typing = Assigner.Typing.DYNAMIC) ServletResponse response,
|
||||||
@Advice.Local("otelSpan") Span span,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
|
|
||||||
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
|
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
|
||||||
|
|
@ -37,9 +35,8 @@ public class Servlet2Advice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context ctx = tracer().startSpan(httpServletRequest);
|
context = tracer().startSpan(httpServletRequest);
|
||||||
span = Java8BytecodeBridge.spanFromContext(ctx);
|
scope = context.makeCurrent();
|
||||||
scope = tracer().startScope(span, httpServletRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
|
@ -47,14 +44,14 @@ public class Servlet2Advice {
|
||||||
@Advice.Argument(0) ServletRequest request,
|
@Advice.Argument(0) ServletRequest request,
|
||||||
@Advice.Argument(1) ServletResponse response,
|
@Advice.Argument(1) ServletResponse response,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
@Advice.Local("otelSpan") Span span,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scope.close();
|
scope.close();
|
||||||
|
|
||||||
tracer().setPrincipal(span, (HttpServletRequest) request);
|
tracer().setPrincipal(context, (HttpServletRequest) request);
|
||||||
|
|
||||||
Integer responseStatus =
|
Integer responseStatus =
|
||||||
InstrumentationContext.get(ServletResponse.class, Integer.class).get(response);
|
InstrumentationContext.get(ServletResponse.class, Integer.class).get(response);
|
||||||
|
|
@ -62,9 +59,9 @@ public class Servlet2Advice {
|
||||||
ResponseWithStatus responseWithStatus =
|
ResponseWithStatus responseWithStatus =
|
||||||
new ResponseWithStatus((HttpServletResponse) response, responseStatus);
|
new ResponseWithStatus((HttpServletResponse) response, responseStatus);
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
tracer().end(span, responseWithStatus);
|
tracer().end(context, responseWithStatus);
|
||||||
} else {
|
} else {
|
||||||
tracer().endExceptionally(span, throwable, responseWithStatus);
|
tracer().endExceptionally(context, throwable, responseWithStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,8 @@ package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3HttpServerTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3HttpServerTracer.tracer;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
|
|
@ -24,7 +22,7 @@ public class Servlet3Advice {
|
||||||
public static void onEnter(
|
public static void onEnter(
|
||||||
@Advice.Argument(value = 0, readOnly = false) ServletRequest request,
|
@Advice.Argument(value = 0, readOnly = false) ServletRequest request,
|
||||||
@Advice.Argument(value = 1, readOnly = false) ServletResponse response,
|
@Advice.Argument(value = 1, readOnly = false) ServletResponse response,
|
||||||
@Advice.Local("otelSpan") Span span,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
|
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -42,9 +40,8 @@ public class Servlet3Advice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context ctx = tracer().startSpan(httpServletRequest);
|
context = tracer().startSpan(httpServletRequest);
|
||||||
span = Java8BytecodeBridge.spanFromContext(ctx);
|
scope = context.makeCurrent();
|
||||||
scope = tracer().startScope(span, httpServletRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
|
@ -52,21 +49,21 @@ public class Servlet3Advice {
|
||||||
@Advice.Argument(0) ServletRequest request,
|
@Advice.Argument(0) ServletRequest request,
|
||||||
@Advice.Argument(1) ServletResponse response,
|
@Advice.Argument(1) ServletResponse response,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
@Advice.Local("otelSpan") Span span,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scope.close();
|
scope.close();
|
||||||
|
|
||||||
if (span == null) {
|
if (context == null) {
|
||||||
// an existing span was found
|
// an existing span was found
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer().setPrincipal(span, (HttpServletRequest) request);
|
tracer().setPrincipal(context, (HttpServletRequest) request);
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
tracer().endExceptionally(span, throwable, (HttpServletResponse) response);
|
tracer().endExceptionally(context, throwable, (HttpServletResponse) response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,7 +72,9 @@ public class Servlet3Advice {
|
||||||
// In case of async servlets wait for the actual response to be ready
|
// In case of async servlets wait for the actual response to be ready
|
||||||
if (request.isAsyncStarted()) {
|
if (request.isAsyncStarted()) {
|
||||||
try {
|
try {
|
||||||
request.getAsyncContext().addListener(new TagSettingAsyncListener(responseHandled, span));
|
request
|
||||||
|
.getAsyncContext()
|
||||||
|
.addListener(new TagSettingAsyncListener(responseHandled, context));
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
// org.eclipse.jetty.server.Request may throw an exception here if request became
|
// org.eclipse.jetty.server.Request may throw an exception here if request became
|
||||||
// finished after check above. We just ignore that exception and move on.
|
// finished after check above. We just ignore that exception and move on.
|
||||||
|
|
@ -84,7 +83,7 @@ public class Servlet3Advice {
|
||||||
|
|
||||||
// Check again in case the request finished before adding the listener.
|
// Check again in case the request finished before adding the listener.
|
||||||
if (!request.isAsyncStarted() && responseHandled.compareAndSet(false, true)) {
|
if (!request.isAsyncStarted() && responseHandled.compareAndSet(false, true)) {
|
||||||
tracer().end(span, (HttpServletResponse) response);
|
tracer().end(context, (HttpServletResponse) response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,24 +37,25 @@ public class Servlet3HttpServerTracer extends ServletHttpServerTracer<HttpServle
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endExceptionally(
|
public void endExceptionally(
|
||||||
Span span, Throwable throwable, HttpServletResponse response, long timestamp) {
|
Context context, Throwable throwable, HttpServletResponse response, long timestamp) {
|
||||||
if (response.isCommitted()) {
|
if (response.isCommitted()) {
|
||||||
super.endExceptionally(span, throwable, response, timestamp);
|
super.endExceptionally(context, throwable, response, timestamp);
|
||||||
} else {
|
} else {
|
||||||
// passing null response to super, in order to capture as 500 / INTERNAL, due to servlet spec
|
// passing null response to super, in order to capture as 500 / INTERNAL, due to servlet spec
|
||||||
// https://javaee.github.io/servlet-spec/downloads/servlet-4.0/servlet-4_0_FINAL.pdf:
|
// https://javaee.github.io/servlet-spec/downloads/servlet-4.0/servlet-4_0_FINAL.pdf:
|
||||||
// "If a servlet generates an error that is not handled by the error page mechanism as
|
// "If a servlet generates an error that is not handled by the error page mechanism as
|
||||||
// described above, the container must ensure to send a response with status 500."
|
// described above, the container must ensure to send a response with status 500."
|
||||||
super.endExceptionally(span, throwable, null, timestamp);
|
super.endExceptionally(context, throwable, null, timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void end(Span span, HttpServletResponse response, long timestamp) {
|
public void end(Context context, HttpServletResponse response, long timestamp) {
|
||||||
super.end(span, response, timestamp);
|
super.end(context, response, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTimeout(Span span, long timeout) {
|
public void onTimeout(Context context, long timeout) {
|
||||||
|
Span span = Span.fromContext(context);
|
||||||
span.setStatus(StatusCode.ERROR);
|
span.setStatus(StatusCode.ERROR);
|
||||||
span.setAttribute("timeout", timeout);
|
span.setAttribute("timeout", timeout);
|
||||||
span.end();
|
span.end();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;
|
package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
import io.opentelemetry.context.Context;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.servlet.AsyncEvent;
|
import javax.servlet.AsyncEvent;
|
||||||
import javax.servlet.AsyncListener;
|
import javax.servlet.AsyncListener;
|
||||||
|
|
@ -16,24 +16,24 @@ public class TagSettingAsyncListener implements AsyncListener {
|
||||||
new Servlet3HttpServerTracer();
|
new Servlet3HttpServerTracer();
|
||||||
|
|
||||||
private final AtomicBoolean responseHandled;
|
private final AtomicBoolean responseHandled;
|
||||||
private final Span span;
|
private final Context context;
|
||||||
|
|
||||||
public TagSettingAsyncListener(AtomicBoolean responseHandled, Span span) {
|
public TagSettingAsyncListener(AtomicBoolean responseHandled, Context context) {
|
||||||
this.responseHandled = responseHandled;
|
this.responseHandled = responseHandled;
|
||||||
this.span = span;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(AsyncEvent event) {
|
public void onComplete(AsyncEvent event) {
|
||||||
if (responseHandled.compareAndSet(false, true)) {
|
if (responseHandled.compareAndSet(false, true)) {
|
||||||
servletHttpServerTracer.end(span, (HttpServletResponse) event.getSuppliedResponse());
|
servletHttpServerTracer.end(context, (HttpServletResponse) event.getSuppliedResponse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimeout(AsyncEvent event) {
|
public void onTimeout(AsyncEvent event) {
|
||||||
if (responseHandled.compareAndSet(false, true)) {
|
if (responseHandled.compareAndSet(false, true)) {
|
||||||
servletHttpServerTracer.onTimeout(span, event.getAsyncContext().getTimeout());
|
servletHttpServerTracer.onTimeout(context, event.getAsyncContext().getTimeout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ public class TagSettingAsyncListener implements AsyncListener {
|
||||||
public void onError(AsyncEvent event) {
|
public void onError(AsyncEvent event) {
|
||||||
if (responseHandled.compareAndSet(false, true)) {
|
if (responseHandled.compareAndSet(false, true)) {
|
||||||
servletHttpServerTracer.endExceptionally(
|
servletHttpServerTracer.endExceptionally(
|
||||||
span, event.getThrowable(), (HttpServletResponse) event.getSuppliedResponse());
|
context, event.getThrowable(), (HttpServletResponse) event.getSuppliedResponse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.spring.webmvc;
|
package io.opentelemetry.instrumentation.spring.webmvc;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
|
|
@ -31,13 +30,12 @@ public class WebMvcTracingFilter extends OncePerRequestFilter implements Ordered
|
||||||
public void doFilterInternal(
|
public void doFilterInternal(
|
||||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
Context ctx = tracer.startSpan(request, request, FILTER_CLASS + "." + FILTER_METHOD);
|
Context ctx = tracer.startSpan(request, request, request, FILTER_CLASS + "." + FILTER_METHOD);
|
||||||
Span serverSpan = Span.fromContext(ctx);
|
try (Scope ignored = ctx.makeCurrent()) {
|
||||||
try (Scope ignored = tracer.startScope(serverSpan, request)) {
|
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
tracer.end(serverSpan, response);
|
tracer.end(ctx, response);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
tracer.endExceptionally(serverSpan, t, response);
|
tracer.endExceptionally(ctx, t, response);
|
||||||
throw t;
|
throw t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue