Delete unused servlet tracer code
MODIFY
instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletAdditionalAttributesExtractor.java
instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletAdditionalAttributesExtractor.java
@@ -9,15 +9,17 @@ import static io.opentelemetry.api.common.AttributeKey.longKey;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributesBuilder;
+import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.servlet.ServletAccessor;
-import io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.security.Principal;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ServletAdditionalAttributesExtractor<REQUEST, RESPONSE>
extends AttributesExtractor<ServletRequestContext<REQUEST>, ServletResponseContext<RESPONSE>> {
+ private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES =
+ Config.get().getBoolean("otel.instrumentation.servlet.experimental-span-attributes", false);
private static final AttributeKey<Long> SERVLET_TIMEOUT = longKey("servlet.timeout");
private final ServletAccessor<REQUEST, RESPONSE> accessor;
@@ -40,7 +42,7 @@ public class ServletAdditionalAttributesExtractor<REQUEST, RESPONSE>
if (principal != null) {
set(attributes, SemanticAttributes.ENDUSER_ID, principal.getName());
}
- if (!ServletHttpServerTracer.CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) {
+ if (!CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) {
return;
}
if (responseContext != null && responseContext.hasTimeout()) {

MODIFY
instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletHelper.java
instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletHelper.java
@@ -9,9 +9,12 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.servlet.ServletAccessor;
-import io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer;
public class ServletHelper<REQUEST, RESPONSE> extends BaseServletHelper<REQUEST, RESPONSE> {
+ private static final String ASYNC_LISTENER_ATTRIBUTE =
+ ServletHelper.class.getName() + ".AsyncListener";
+ private static final String ASYNC_LISTENER_RESPONSE_ATTRIBUTE =
+ ServletHelper.class.getName() + ".AsyncListenerResponse";
public ServletHelper(
Instrumenter<ServletRequestContext<REQUEST>, ServletResponseContext<RESPONSE>> instrumenter,
@@ -76,14 +79,11 @@ public class ServletHelper<REQUEST, RESPONSE> extends BaseServletHelper<REQUEST,
* is not possible to access response from async event in listeners.
*/
public void setAsyncListenerResponse(REQUEST request, RESPONSE response) {
- accessor.setRequestAttribute(
- request, ServletHttpServerTracer.ASYNC_LISTENER_RESPONSE_ATTRIBUTE, response);
+ accessor.setRequestAttribute(request, ASYNC_LISTENER_RESPONSE_ATTRIBUTE, response);
}
public RESPONSE getAsyncListenerResponse(REQUEST request) {
- return (RESPONSE)
- accessor.getRequestAttribute(
- request, ServletHttpServerTracer.ASYNC_LISTENER_RESPONSE_ATTRIBUTE);
+ return (RESPONSE) accessor.getRequestAttribute(request, ASYNC_LISTENER_RESPONSE_ATTRIBUTE);
}
public void attachAsyncListener(REQUEST request) {
@@ -102,12 +102,11 @@ public class ServletHelper<REQUEST, RESPONSE> extends BaseServletHelper<REQUEST,
request,
new AsyncRequestCompletionListener<>(this, instrumenter, requestContext, context),
response);
- accessor.setRequestAttribute(request, ServletHttpServerTracer.ASYNC_LISTENER_ATTRIBUTE, true);
+ accessor.setRequestAttribute(request, ASYNC_LISTENER_ATTRIBUTE, true);
}
}
public boolean isAsyncListenerAttached(REQUEST request) {
- return accessor.getRequestAttribute(request, ServletHttpServerTracer.ASYNC_LISTENER_ATTRIBUTE)
- != null;
+ return accessor.getRequestAttribute(request, ASYNC_LISTENER_ATTRIBUTE) != null;
}
}

DELETE
instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/common/service/ServletAndFilterAdviceHelper.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.javaagent.instrumentation.servlet.common.service;
-
-import io.opentelemetry.context.Context;
-import io.opentelemetry.context.Scope;
-import io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer;
-import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
-
-@Deprecated
-public class ServletAndFilterAdviceHelper {
- public static <REQUEST, RESPONSE> void stopSpan(
- ServletHttpServerTracer<REQUEST, RESPONSE> tracer,
- REQUEST request,
- RESPONSE response,
- Throwable throwable,
- boolean topLevel,
- Context context,
- Scope scope) {
-
- if (scope != null) {
- scope.close();
- }
-
- if (context == null && topLevel) {
- Context currentContext = Java8BytecodeBridge.currentContext();
- // Something else is managing the context, we're in the outermost level of Servlet
- // instrumentation and we have an uncaught throwable. Let's add it to the current span.
- if (throwable != null) {
- tracer.addUnwrappedThrowable(currentContext, throwable);
- }
- tracer.setPrincipal(currentContext, request);
- }
-
- if (scope == null || context == null) {
- return;
- }
-
- tracer.setPrincipal(context, request);
- if (throwable != null) {
- tracer.endExceptionally(context, throwable, response);
- return;
- }
-
- if (mustEndOnHandlerMethodExit(tracer, request)) {
- tracer.end(context, response);
- }
- }
-
- /**
- * Helper method to determine whether the appserver handler/servlet service/servlet filter method
- * that started a span must also end it, even if no error was detected. Extracted as a separate
- * method to avoid duplicating the comments on the logic behind this choice.
- */
- public static <REQUEST, RESPONSE> boolean mustEndOnHandlerMethodExit(
- ServletHttpServerTracer<REQUEST, RESPONSE> tracer, REQUEST request) {
-
- if (tracer.isAsyncListenerAttached(request)) {
- // This request is handled asynchronously and startAsync instrumentation has already attached
- // the listener.
- return false;
- }
-
- // This means that startAsync was not called (assuming startAsync instrumentation works
- // correctly on this servlet engine), therefore the request was handled synchronously, and
- // handler method end must also end the span.
- return true;
- }
-}

DELETE
instrumentation/servlet/servlet-common/library/src/main/java/io/opentelemetry/instrumentation/servlet/ServletHttpServerTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.servlet;
-
-import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.CONTAINER;
-import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.FILTER;
-import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.SERVLET;
-
-import io.opentelemetry.api.trace.Span;
-import io.opentelemetry.api.trace.SpanContext;
-import io.opentelemetry.api.trace.StatusCode;
-import io.opentelemetry.context.Context;
-import io.opentelemetry.context.propagation.TextMapGetter;
-import io.opentelemetry.instrumentation.api.config.Config;
-import io.opentelemetry.instrumentation.api.servlet.AppServerBridge;
-import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
-import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
-import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
-import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.Principal;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Function;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Deprecated
-public abstract class ServletHttpServerTracer<REQUEST, RESPONSE>
- extends HttpServerTracer<REQUEST, RESPONSE, REQUEST, REQUEST> {
-
- private static final Logger logger = LoggerFactory.getLogger(ServletHttpServerTracer.class);
-
- public static final String ASYNC_LISTENER_ATTRIBUTE =
- ServletHttpServerTracer.class.getName() + ".AsyncListener";
- public static final String ASYNC_LISTENER_RESPONSE_ATTRIBUTE =
- ServletHttpServerTracer.class.getName() + ".AsyncListenerResponse";
-
- public static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES =
- Config.get().getBoolean("otel.instrumentation.servlet.experimental-span-attributes", false);
-
- private final ServletAccessor<REQUEST, RESPONSE> accessor;
- private final Function<REQUEST, String> contextPathExtractor;
-
- protected ServletHttpServerTracer(ServletAccessor<REQUEST, RESPONSE> accessor) {
- this.accessor = accessor;
- this.contextPathExtractor = accessor::getRequestContextPath;
- }
-
- public Context startSpan(REQUEST request, String spanName, boolean servlet) {
- Context context = startSpan(request, request, request, spanName);
-
- SpanContext spanContext = Span.fromContext(context).getSpanContext();
- // we do this e.g. so that servlet containers can use these values in their access logs
- accessor.setRequestAttribute(request, "trace_id", spanContext.getTraceId());
- accessor.setRequestAttribute(request, "span_id", spanContext.getSpanId());
-
- // server span name shouldn't be updated when server span was created from a call to Servlet
- // (if created from a call to Filter then name may be updated from updateContext)
- ServerSpanNaming.updateSource(context, servlet ? SERVLET : FILTER);
-
- return addServletContextPath(context, request);
- }
-
- @Override
- protected Context customizeContext(Context context, REQUEST request) {
- // add context for tracking whether servlet instrumentation has updated the server span name
- context = ServerSpanNaming.init(context, CONTAINER);
- // add context for current request's context path
- return addServletContextPath(context, request);
- }
-
- protected Context addServletContextPath(Context context, REQUEST request) {
- return ServletContextPath.init(context, contextPathExtractor, request);
- }
-
- @Override
- public void endExceptionally(
- Context context, Throwable throwable, RESPONSE response, long timestamp) {
- if (accessor.isResponseCommitted(response)) {
- super.endExceptionally(context, throwable, response, timestamp);
- } else {
- // 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:
- // "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."
- super.endExceptionally(context, throwable, null, timestamp);
- }
- }
-
- @Override
- protected String url(REQUEST httpServletRequest) {
- try {
- return new URI(
- accessor.getRequestScheme(httpServletRequest),
- null,
- accessor.getRequestServerName(httpServletRequest),
- accessor.getRequestServerPort(httpServletRequest),
- accessor.getRequestUri(httpServletRequest),
- accessor.getRequestQueryString(httpServletRequest),
- null)
- .toString();
- } catch (URISyntaxException e) {
- logger.debug("Failed to construct request URI", e);
- return null;
- }
- }
-
- @Override
- public Context getServerContext(REQUEST request) {
- Object context = accessor.getRequestAttribute(request, CONTEXT_ATTRIBUTE);
- return context instanceof Context ? (Context) context : null;
- }
-
- @Override
- protected void attachServerContext(Context context, REQUEST request) {
- accessor.setRequestAttribute(request, CONTEXT_ATTRIBUTE, context);
- }
-
- @Override
- protected Integer peerPort(REQUEST connection) {
- return accessor.getRequestRemotePort(connection);
- }
-
- @Override
- protected String peerHostIp(REQUEST connection) {
- return accessor.getRequestRemoteAddr(connection);
- }
-
- @Override
- protected String method(REQUEST request) {
- return accessor.getRequestMethod(request);
- }
-
- @Override
- protected int responseStatus(RESPONSE response) {
- return accessor.getResponseStatus(response);
- }
-
- @Override
- protected abstract TextMapGetter<REQUEST> getGetter();
-
- /**
- * Response object must be attached to a request prior to {@link #attachAsyncListener(Object)}
- * being called, as otherwise in some environments it is not possible to access response from
- * async event in listeners.
- */
- public void setAsyncListenerResponse(REQUEST request, RESPONSE response) {
- accessor.setRequestAttribute(request, ASYNC_LISTENER_RESPONSE_ATTRIBUTE, response);
- }
-
- public void attachAsyncListener(REQUEST request) {
- Context context = getServerContext(request);
-
- if (context != null) {
- Object response = accessor.getRequestAttribute(request, ASYNC_LISTENER_RESPONSE_ATTRIBUTE);
-
- accessor.addRequestAsyncListener(
- request, new TagSettingAsyncListener<>(this, new AtomicBoolean(), context), response);
- accessor.setRequestAttribute(request, ASYNC_LISTENER_ATTRIBUTE, true);
- }
- }
-
- public boolean isAsyncListenerAttached(REQUEST request) {
- return accessor.getRequestAttribute(request, ASYNC_LISTENER_ATTRIBUTE) != null;
- }
-
- public void addUnwrappedThrowable(Context context, Throwable throwable) {
- if (AppServerBridge.shouldRecordException(context)) {
- onException(context, throwable);
- }
- }
-
- @Override
- protected Throwable unwrapThrowable(Throwable throwable) {
- if (accessor.isServletException(throwable) && throwable.getCause() != null) {
- throwable = throwable.getCause();
- }
- return super.unwrapThrowable(throwable);
- }
-
- public void setPrincipal(Context context, REQUEST request) {
- Principal principal = accessor.getRequestUserPrincipal(request);
- if (principal != null) {
- Span.fromContext(context).setAttribute(SemanticAttributes.ENDUSER_ID, principal.getName());
- }
- }
-
- @Override
- protected String flavor(REQUEST connection, REQUEST request) {
- return accessor.getRequestProtocol(connection);
- }
-
- @Override
- protected String requestHeader(REQUEST httpServletRequest, String name) {
- return accessor.getRequestHeader(httpServletRequest, name);
- }
-
- public Throwable errorException(REQUEST request) {
- Object value = accessor.getRequestAttribute(request, errorExceptionAttributeName());
-
- if (value instanceof Throwable) {
- return (Throwable) value;
- } else {
- return null;
- }
- }
-
- protected abstract String errorExceptionAttributeName();
-
- public String getSpanName(REQUEST request) {
- String servletPath = accessor.getRequestServletPath(request);
- if (servletPath.isEmpty()) {
- return "HTTP " + accessor.getRequestMethod(request);
- }
- String contextPath = accessor.getRequestContextPath(request);
- if (contextPath == null || contextPath.isEmpty() || contextPath.equals("/")) {
- return servletPath;
- }
- return contextPath + servletPath;
- }
-
- public void onTimeout(Context context, long timeout) {
- Span span = Span.fromContext(context);
- span.setStatus(StatusCode.ERROR);
- if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) {
- span.setAttribute("servlet.timeout", timeout);
- }
- span.end();
- }
-
- /*
- Given request already has a context associated with it.
- As there should not be nested spans of kind SERVER, we should NOT create a new span here.
-
- But it may happen that there is no span in current Context or it is from a different trace.
- E.g. in case of async servlet request processing we create span for incoming request in one thread,
- but actual request continues processing happens in another thread.
- Depending on servlet container implementation, this processing may again arrive into this method.
- E.g. Jetty handles async requests in a way that calls HttpServlet.service method twice.
-
- In this case we have to put the span from the request into current context before continuing.
- */
- public boolean needsRescoping(Context currentContext, Context attachedContext) {
- return !sameTrace(Span.fromContext(currentContext), Span.fromContext(attachedContext));
- }
-
- private static boolean sameTrace(Span oneSpan, Span otherSpan) {
- return oneSpan.getSpanContext().getTraceId().equals(otherSpan.getSpanContext().getTraceId());
- }
-}

DELETE
instrumentation/servlet/servlet-common/library/src/main/java/io/opentelemetry/instrumentation/servlet/TagSettingAsyncListener.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.servlet;
-
-import io.opentelemetry.context.Context;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@Deprecated
-public class TagSettingAsyncListener<REQUEST, RESPONSE> implements ServletAsyncListener<RESPONSE> {
- private final ServletHttpServerTracer<REQUEST, RESPONSE> tracer;
- private final AtomicBoolean responseHandled;
- private final Context context;
-
- public TagSettingAsyncListener(
- ServletHttpServerTracer<REQUEST, RESPONSE> tracer,
- AtomicBoolean responseHandled,
- Context context) {
- this.tracer = tracer;
- this.responseHandled = responseHandled;
- this.context = context;
- }
-
- @Override
- public void onComplete(RESPONSE response) {
- if (responseHandled.compareAndSet(false, true)) {
- tracer.end(context, response);
- }
- }
-
- @Override
- public void onTimeout(long timeout) {
- if (responseHandled.compareAndSet(false, true)) {
- tracer.onTimeout(context, timeout);
- }
- }
-
- @Override
- public void onError(Throwable throwable, RESPONSE response) {
- if (responseHandled.compareAndSet(false, true)) {
- tracer.endExceptionally(context, throwable, response);
- }
- }
-}

DELETE
instrumentation/servlet/servlet-javax-common/library/src/main/java/io/opentelemetry/instrumentation/servlet/javax/JavaxServletHttpServerTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.servlet.javax;
-
-import io.opentelemetry.context.propagation.TextMapGetter;
-import io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer;
-import javax.servlet.http.HttpServletRequest;
-
-public abstract class JavaxServletHttpServerTracer<RESPONSE>
- extends ServletHttpServerTracer<HttpServletRequest, RESPONSE> {
- protected JavaxServletHttpServerTracer(JavaxServletAccessor<RESPONSE> accessor) {
- super(accessor);
- }
-
- @Override
- protected TextMapGetter<HttpServletRequest> getGetter() {
- return JavaxHttpServletRequestGetter.GETTER;
- }
-
- @Override
- protected String errorExceptionAttributeName() {
- return "javax.servlet.error.exception";
- }
-}

DELETE
instrumentation/servlet/servlet-javax-common/library/src/test/java/RequestOnlyTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import io.opentelemetry.instrumentation.servlet.ServletAsyncListener;
-import io.opentelemetry.instrumentation.servlet.javax.JavaxServletAccessor;
-import io.opentelemetry.instrumentation.servlet.javax.JavaxServletHttpServerTracer;
-import javax.servlet.http.HttpServletRequest;
-
-public class RequestOnlyTracer extends JavaxServletHttpServerTracer<Void> {
- public RequestOnlyTracer() {
- super(
- new JavaxServletAccessor<Void>() {
- @Override
- public Integer getRequestRemotePort(HttpServletRequest httpServletRequest) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addRequestAsyncListener(
- HttpServletRequest request, ServletAsyncListener<Void> listener, Object response) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getResponseStatus(Void unused) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getResponseHeader(Void unused, String name) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isResponseCommitted(Void unused) {
- throw new UnsupportedOperationException();
- }
- });
- }
-
- @Override
- protected String getInstrumentationName() {
- return "test";
- }
-}

DELETE
instrumentation/servlet/servlet-javax-common/library/src/test/java/ServletHttpServerTracerTest.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import javax.servlet.http.HttpServletRequest;
-import org.junit.jupiter.api.Test;
-
-public class ServletHttpServerTracerTest {
- private static final RequestOnlyTracer tracer = new RequestOnlyTracer();
-
- @Test
- void testGetSpanName_emptySpanName() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- when(request.getServletPath()).thenReturn("");
- when(request.getMethod()).thenReturn("PUT");
- String spanName = tracer.getSpanName(request);
- assertThat(spanName).isEqualTo("HTTP PUT");
- }
-
- @Test
- void testGetSpanName_nullSpanName() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- when(request.getServletPath()).thenReturn(null);
- assertThatThrownBy(() -> tracer.getSpanName(request)).isInstanceOf(NullPointerException.class);
- }
-
- @Test
- void testGetSpanName_nullContextPath() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- when(request.getServletPath()).thenReturn("/swizzler");
- when(request.getContextPath()).thenReturn(null);
- String spanName = tracer.getSpanName(request);
- assertThat(spanName).isEqualTo("/swizzler");
- }
-
- @Test
- void testGetSpanName_emptyContextPath() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- when(request.getServletPath()).thenReturn("/swizzler");
- when(request.getContextPath()).thenReturn("");
- String spanName = tracer.getSpanName(request);
- assertThat(spanName).isEqualTo("/swizzler");
- }
-
- @Test
- void testGetSpanName_slashContextPath() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- when(request.getServletPath()).thenReturn("/swizzler");
- when(request.getContextPath()).thenReturn("/");
- String spanName = tracer.getSpanName(request);
- assertThat(spanName).isEqualTo("/swizzler");
- }
-
- @Test
- void testGetSpanName_appendsSpanNameToContext() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- when(request.getServletPath()).thenReturn("/swizzler");
- when(request.getContextPath()).thenReturn("/path/to");
- String spanName = tracer.getSpanName(request);
- assertThat(spanName).isEqualTo("/path/to/swizzler");
- }
-}

Delete unused servlet tracer code (#4243)