Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .fossa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,9 @@ targets:
- type: gradle
path: ./
target: ':instrumentation:servlet:servlet-3.0:javaagent'
- type: gradle
path: ./
target: ':instrumentation:servlet:servlet-3.0:library'
- type: gradle
path: ./
target: ':instrumentation:servlet:servlet-5.0:javaagent'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,11 @@
package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;

import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.getSnippetInjectionHelper;
import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.helper;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
import io.opentelemetry.javaagent.bootstrap.servlet.MappingResolver;
import io.opentelemetry.javaagent.instrumentation.servlet.ServletRequestContext;
import io.opentelemetry.javaagent.instrumentation.servlet.v3_0.snippet.Servlet3SnippetInjectingResponseWrapper;
import javax.annotation.Nullable;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -30,67 +23,6 @@
@SuppressWarnings("unused")
public class Servlet3Advice {

public static class AdviceScope {
private final CallDepth callDepth;
private final ServletRequestContext<HttpServletRequest> requestContext;
private final Context context;
private final Scope scope;

public AdviceScope(
CallDepth callDepth,
HttpServletRequest request,
HttpServletResponse response,
Object servletOrFilter) {
this.callDepth = callDepth;
this.callDepth.getAndIncrement();

Context currentContext = Context.current();
Context attachedContext = helper().getServerContext(request);
Context contextToUpdate;

requestContext = new ServletRequestContext<>(request, servletOrFilter);
if (attachedContext == null && helper().shouldStart(currentContext, requestContext)) {
context = helper().start(currentContext, requestContext);
helper().setAsyncListenerResponse(context, response);

contextToUpdate = context;
} else if (attachedContext != null
&& helper().needsRescoping(currentContext, attachedContext)) {
// Given request already has a context associated with it.
// see the needsRescoping() javadoc for more explanation
contextToUpdate = attachedContext;
context = null;
} else {
// We are inside nested servlet/filter/app-server span, don't create new span
contextToUpdate = currentContext;
context = null;
}

// Update context with info from current request to ensure that server span gets the best
// possible name.
// In case server span was created by app server instrumentations calling updateContext
// returns a new context that contains servlet context path that is used in other
// instrumentations for naming server span.
MappingResolver mappingResolver = Servlet3Singletons.getMappingResolver(servletOrFilter);
boolean servlet = servletOrFilter instanceof Servlet;
contextToUpdate = helper().updateContext(contextToUpdate, request, mappingResolver, servlet);
scope = contextToUpdate.makeCurrent();

if (context != null) {
// Only trigger response customizer once, so only if server span was created here
HttpServerResponseCustomizerHolder.getCustomizer()
.customize(contextToUpdate, response, Servlet3Accessor.INSTANCE);
}
}

public void exit(
@Nullable Throwable throwable, HttpServletRequest request, HttpServletResponse response) {

boolean topLevel = callDepth.decrementAndGet() == 0;
helper().end(requestContext, request, response, throwable, topLevel, context, scope);
}
}

@AssignReturned.ToArguments({
@ToArgument(value = 0, index = 1),
@ToArgument(value = 1, index = 2)
Expand All @@ -114,8 +46,8 @@ public static Object[] onEnter(
response =
new Servlet3SnippetInjectingResponseWrapper((HttpServletResponse) response, snippet);
}
AdviceScope adviceScope =
new AdviceScope(
Servlet3RequestAdviceScope adviceScope =
new Servlet3RequestAdviceScope(
CallDepth.forClass(AppServerBridge.getCallDepthKey()),
(HttpServletRequest) request,
(HttpServletResponse) response,
Expand All @@ -129,7 +61,7 @@ public static void stopSpan(
@Advice.Argument(1) ServletResponse response,
@Advice.Thrown @Nullable Throwable throwable,
@Advice.Enter Object[] enterResult) {
AdviceScope adviceScope = (AdviceScope) enterResult[0];
Servlet3RequestAdviceScope adviceScope = (Servlet3RequestAdviceScope) enterResult[0];
if (adviceScope == null
|| !(request instanceof HttpServletRequest)
|| !(response instanceof HttpServletResponse)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;

import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.FILTER_MAPPING_RESOLVER_FACTORY;
import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.FILTER_MAPPING_RESOLVER;

import javax.servlet.Filter;
import javax.servlet.FilterConfig;
Expand All @@ -20,7 +20,6 @@ public static void filterInit(
if (filterConfig == null) {
return;
}
FILTER_MAPPING_RESOLVER_FACTORY.set(
filter, new Servlet3FilterMappingResolverFactory(filterConfig));
FILTER_MAPPING_RESOLVER.set(filter, new Servlet3FilterMappingResolverFactory(filterConfig));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;

import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.SERVLET_MAPPING_RESOLVER_FACTORY;
import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.SERVLET_MAPPING_RESOLVER;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
Expand All @@ -20,7 +20,6 @@ public static void servletInit(
if (servletConfig == null) {
return;
}
SERVLET_MAPPING_RESOLVER_FACTORY.set(
servlet, new Servlet3MappingResolverFactory(servletConfig));
SERVLET_MAPPING_RESOLVER.set(servlet, new Servlet3MappingResolverFactory(servletConfig));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;

import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.helper;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
import io.opentelemetry.javaagent.bootstrap.servlet.MappingResolver;
import io.opentelemetry.javaagent.instrumentation.servlet.ServletRequestContext;
import javax.annotation.Nullable;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet3RequestAdviceScope {
private final CallDepth callDepth;
private final ServletRequestContext<HttpServletRequest> requestContext;
private final Context context;
private final Scope scope;

public Servlet3RequestAdviceScope(
CallDepth callDepth,
HttpServletRequest request,
HttpServletResponse response,
Object servletOrFilter) {
this.callDepth = callDepth;
this.callDepth.getAndIncrement();

Context currentContext = Context.current();
Context attachedContext = helper().getServerContext(request);
Context contextToUpdate;

requestContext = new ServletRequestContext<>(request, servletOrFilter);
if (attachedContext == null && helper().shouldStart(currentContext, requestContext)) {
context = helper().start(currentContext, requestContext);
helper().setAsyncListenerResponse(context, response);

contextToUpdate = context;
} else if (attachedContext != null
&& helper().needsRescoping(currentContext, attachedContext)) {
// Given request already has a context associated with it.
// see the needsRescoping() javadoc for more explanation
contextToUpdate = attachedContext;
context = null;
} else {
// We are inside nested servlet/filter/app-server span, don't create new span
contextToUpdate = currentContext;
context = null;
}

// Update context with info from current request to ensure that server span gets the best
// possible name.
// In case server span was created by app server instrumentations calling updateContext
// returns a new context that contains servlet context path that is used in other
// instrumentations for naming server span.
MappingResolver mappingResolver = Servlet3Singletons.getMappingResolver(servletOrFilter);
boolean servlet = servletOrFilter instanceof Servlet;
contextToUpdate = helper().updateContext(contextToUpdate, request, mappingResolver, servlet);
scope = contextToUpdate.makeCurrent();

if (context != null) {
// Only trigger response customizer once, so only if server span was created here
HttpServerResponseCustomizerHolder.getCustomizer()
.customize(contextToUpdate, response, Servlet3Accessor.INSTANCE);
}
}

public void exit(
@Nullable Throwable throwable, HttpServletRequest request, HttpServletResponse response) {

boolean topLevel = callDepth.decrementAndGet() == 0;
helper().end(requestContext, request, response, throwable, topLevel, context, scope);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;

import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.responseInstrumenter;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.instrumentation.servlet.common.response.HttpServletResponseAdviceHelper;
import javax.annotation.Nullable;

public class Servlet3ResponseAdviceScope {
private final CallDepth callDepth;
private final ClassAndMethod classAndMethod;
private final Context context;
private final Scope scope;

public Servlet3ResponseAdviceScope(
CallDepth callDepth, Class<?> declaringClass, String methodName) {
this.callDepth = callDepth;
if (callDepth.getAndIncrement() > 0) {
this.classAndMethod = null;
this.context = null;
this.scope = null;
return;
}
HttpServletResponseAdviceHelper.StartResult result =
HttpServletResponseAdviceHelper.startSpan(
responseInstrumenter(), declaringClass, methodName);
if (result != null) {
classAndMethod = result.getClassAndMethod();
context = result.getContext();
scope = result.getScope();
} else {
classAndMethod = null;
context = null;
scope = null;
}
}

public void exit(@Nullable Throwable throwable) {
if (callDepth.decrementAndGet() > 0) {
return;
}
HttpServletResponseAdviceHelper.stopSpan(
responseInstrumenter(), throwable, context, scope, classAndMethod);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,23 @@

package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;

import static io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3Singletons.responseInstrumenter;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.instrumentation.servlet.common.response.HttpServletResponseAdviceHelper;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;
import net.bytebuddy.asm.Advice;

@SuppressWarnings("unused")
public class Servlet3ResponseSendAdvice {

public static class AdviceScope {
private final CallDepth callDepth;
private final ClassAndMethod classAndMethod;
private final Context context;
private final Scope scope;

public AdviceScope(CallDepth callDepth, Class<?> declaringClass, String methodName) {
this.callDepth = callDepth;
if (callDepth.getAndIncrement() > 0) {
this.classAndMethod = null;
this.context = null;
this.scope = null;
return;
}
HttpServletResponseAdviceHelper.StartResult result =
HttpServletResponseAdviceHelper.startSpan(
responseInstrumenter(), declaringClass, methodName);
if (result != null) {
classAndMethod = result.getClassAndMethod();
context = result.getContext();
scope = result.getScope();
} else {
classAndMethod = null;
context = null;
scope = null;
}
}

public void exit(@Nullable Throwable throwable) {
if (callDepth.decrementAndGet() > 0) {
return;
}
HttpServletResponseAdviceHelper.stopSpan(
responseInstrumenter(), throwable, context, scope, classAndMethod);
}
}

@Advice.OnMethodEnter(suppress = Throwable.class)
public static AdviceScope start(
public static Servlet3ResponseAdviceScope start(
@Advice.Origin("#t") Class<?> declaringClass, @Advice.Origin("#m") String methodName) {
return new AdviceScope(
return new Servlet3ResponseAdviceScope(
CallDepth.forClass(HttpServletResponse.class), declaringClass, methodName);
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopSpan(
@Advice.Thrown Throwable throwable, @Advice.Enter AdviceScope adviceScope) {
@Advice.Thrown Throwable throwable, @Advice.Enter Servlet3ResponseAdviceScope adviceScope) {
adviceScope.exit(throwable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@
public final class Servlet3Singletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.servlet-3.0";

public static final VirtualField<Servlet, MappingResolver.Factory>
SERVLET_MAPPING_RESOLVER_FACTORY =
VirtualField.find(Servlet.class, MappingResolver.Factory.class);

public static final VirtualField<Filter, MappingResolver.Factory>
FILTER_MAPPING_RESOLVER_FACTORY =
VirtualField.find(Filter.class, MappingResolver.Factory.class);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change isn't necessary, but it seems odd that these are duplicated. I combined them, but if it's intentional I can revert this change.


private static final Instrumenter<
ServletRequestContext<HttpServletRequest>, ServletResponseContext<HttpServletResponse>>
INSTRUMENTER =
Expand All @@ -41,9 +33,9 @@ public final class Servlet3Singletons {
private static final ServletHelper<HttpServletRequest, HttpServletResponse> HELPER =
new ServletHelper<>(INSTRUMENTER, Servlet3Accessor.INSTANCE);

private static final VirtualField<Servlet, MappingResolver.Factory> SERVLET_MAPPING_RESOLVER =
public static final VirtualField<Servlet, MappingResolver.Factory> SERVLET_MAPPING_RESOLVER =
VirtualField.find(Servlet.class, MappingResolver.Factory.class);
private static final VirtualField<Filter, MappingResolver.Factory> FILTER_MAPPING_RESOLVER =
public static final VirtualField<Filter, MappingResolver.Factory> FILTER_MAPPING_RESOLVER =
VirtualField.find(Filter.class, MappingResolver.Factory.class);

private static final Instrumenter<ClassAndMethod, Void> RESPONSE_INSTRUMENTER =
Expand Down
Loading
Loading