diff --git a/dd-java-agent-ittests/dd-java-agent-ittests.gradle b/dd-java-agent-ittests/dd-java-agent-ittests.gradle
index 042a5a934f..06ac22bc99 100644
--- a/dd-java-agent-ittests/dd-java-agent-ittests.gradle
+++ b/dd-java-agent-ittests/dd-java-agent-ittests.gradle
@@ -24,6 +24,7 @@ dependencies {
testCompile project(':dd-trace-ot')
testCompile deps.opentracingMock
+ testCompile deps.testLogging
testCompile(project(':dd-java-agent:testing')) {
// Otherwise this can bring in classes that aren't "shadowed"
@@ -36,16 +37,9 @@ dependencies {
// run embeded mongodb for integration testing
testCompile group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '1.50.5'
- testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '8.2.0.v20160908'
- testCompile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '8.2.0.v20160908'
- testCompile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '8.0.41'
- testCompile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '8.0.41'
testCompile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3'
testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0'
- testCompile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.8.2'
- testCompile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.8.2'
-
// JDBC tests:
testCompile group: 'com.h2database', name: 'h2', version: '1.4.196'
testCompile group: 'org.hsqldb', name: 'hsqldb', version: '2.3.+'
diff --git a/dd-java-agent-ittests/src/test/resources/log4j2.properties b/dd-java-agent-ittests/src/test/resources/log4j2.properties
deleted file mode 100644
index d675564808..0000000000
--- a/dd-java-agent-ittests/src/test/resources/log4j2.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-appender.console.type=Console
-appender.console.name=console
-appender.console.layout.type=PatternLayout
-rootLogger.level=debug
-rootLogger.appenderRef.console.ref=console
diff --git a/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle b/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle
index ce5378d2ed..4d02a44a48 100644
--- a/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle
+++ b/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle
@@ -24,4 +24,11 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
+
+ testCompile project(':dd-java-agent:testing')
+ testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '7.0.0.v20091005'
+ testCompile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '7.0.0.v20091005'
+
+ testCompile project(':dd-java-agent:instrumentation:okhttp-3') // used in the tests
+ testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0'
}
diff --git a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java
index d9a001de0c..4db67e831e 100644
--- a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java
+++ b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java
@@ -19,7 +19,6 @@ import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter;
-import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator;
import io.opentracing.propagation.Format;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
@@ -52,10 +51,7 @@ public final class FilterChain2Instrumentation extends Instrumenter.Configurable
new HelperInjector(
"io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter",
"io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter$MultivaluedMapFlatIterator",
- "io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator",
- "io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator$1",
- "io.opentracing.contrib.web.servlet.filter.TracingFilter",
- "io.opentracing.contrib.web.servlet.filter.TracingFilter$1"))
+ "datadog.trace.instrumentation.servlet2.ServletFilterSpanDecorator"))
.transform(
DDAdvice.create()
.advice(
diff --git a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java
index efe3ef856c..4b7a8e3e80 100644
--- a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java
+++ b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java
@@ -19,7 +19,6 @@ import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter;
-import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator;
import io.opentracing.propagation.Format;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
@@ -52,12 +51,9 @@ public final class HttpServlet2Instrumentation extends Instrumenter.Configurable
new HelperInjector(
"io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter",
"io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter$MultivaluedMapFlatIterator",
- "io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator",
- "io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator$1",
- "io.opentracing.contrib.web.servlet.filter.TracingFilter",
- "io.opentracing.contrib.web.servlet.filter.TracingFilter$1"))
+ "datadog.trace.instrumentation.servlet2.ServletFilterSpanDecorator"))
.transform(
- DDAdvice.create()
+ DDAdvice.create(false) // Can't use the error handler for pre 1.5 classes...
.advice(
named("service")
.and(takesArgument(0, named("javax.servlet.http.HttpServletRequest")))
diff --git a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/ServletFilterSpanDecorator.java b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/ServletFilterSpanDecorator.java
new file mode 100644
index 0000000000..d60732a4af
--- /dev/null
+++ b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/ServletFilterSpanDecorator.java
@@ -0,0 +1,142 @@
+package datadog.trace.instrumentation.servlet2;
+
+import io.opentracing.Span;
+import io.opentracing.tag.Tags;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * SpanDecorator to decorate span at different stages in filter processing (before
+ * filterChain.doFilter(), after and if exception is thrown).
+ *
+ *
Taken from
+ * https://raw.githubusercontent.com/opentracing-contrib/java-web-servlet-filter/v0.1.0/opentracing-web-servlet-filter/src/main/java/io/opentracing/contrib/web/servlet/filter/ServletFilterSpanDecorator.java
+ * and removed async and status code stuff to be Servlet 2.x compatible.
+ *
+ * @author Pavol Loffay
+ */
+public interface ServletFilterSpanDecorator {
+
+ /**
+ * Decorate span before {@link javax.servlet.Filter#doFilter(ServletRequest, ServletResponse,
+ * FilterChain)} is called. This is called right after span in created. Span is already present in
+ * request attributes with name {@link TracingFilter#SERVER_SPAN_CONTEXT}.
+ *
+ * @param httpServletRequest request
+ * @param span span to decorate
+ */
+ void onRequest(HttpServletRequest httpServletRequest, Span span);
+
+ /**
+ * Decorate span after {@link javax.servlet.Filter#doFilter(ServletRequest, ServletResponse,
+ * FilterChain)}.
+ *
+ * @param httpServletRequest request
+ * @param httpServletResponse response
+ * @param span span to decorate
+ */
+ void onResponse(
+ HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Span span);
+
+ /**
+ * Decorate span when an exception is thrown during processing in {@link
+ * javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}.
+ *
+ * @param httpServletRequest request
+ * @param exception exception
+ * @param span span to decorate
+ */
+ void onError(
+ HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse,
+ Throwable exception,
+ Span span);
+
+ /**
+ * Decorate span on asynchronous request timeout.
+ *
+ * @param httpServletRequest request
+ * @param httpServletResponse response
+ * @param timeout timeout
+ * @param span span to decorate
+ */
+ void onTimeout(
+ HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse,
+ long timeout,
+ Span span);
+
+ /**
+ * Adds standard tags to span. {@link Tags#HTTP_URL}, {@link Tags#HTTP_STATUS}, {@link
+ * Tags#HTTP_METHOD} and {@link Tags#COMPONENT}. If an exception during {@link
+ * javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)} is thrown tag
+ * {@link Tags#ERROR} is added and {@link Tags#HTTP_STATUS} not because at this point it is not
+ * known.
+ */
+ ServletFilterSpanDecorator STANDARD_TAGS =
+ new ServletFilterSpanDecorator() {
+ @Override
+ public void onRequest(final HttpServletRequest httpServletRequest, final Span span) {
+ Tags.COMPONENT.set(span, "java-web-servlet");
+
+ Tags.HTTP_METHOD.set(span, httpServletRequest.getMethod());
+ //without query params
+ Tags.HTTP_URL.set(span, httpServletRequest.getRequestURL().toString());
+ }
+
+ @Override
+ public void onResponse(
+ final HttpServletRequest httpServletRequest,
+ final HttpServletResponse httpServletResponse,
+ final Span span) {}
+
+ @Override
+ public void onError(
+ final HttpServletRequest httpServletRequest,
+ final HttpServletResponse httpServletResponse,
+ final Throwable exception,
+ final Span span) {
+ Tags.ERROR.set(span, Boolean.TRUE);
+ span.log(logsForException(exception));
+ }
+
+ @Override
+ public void onTimeout(
+ final HttpServletRequest httpServletRequest,
+ final HttpServletResponse httpServletResponse,
+ final long timeout,
+ final Span span) {
+ Tags.ERROR.set(span, Boolean.TRUE);
+
+ final Map timeoutLogs = new HashMap<>();
+ timeoutLogs.put("event", Tags.ERROR.getKey());
+ timeoutLogs.put("message", "timeout");
+ timeoutLogs.put("timeout", timeout);
+ }
+
+ private Map logsForException(final Throwable throwable) {
+ final Map errorLog = new HashMap<>(3);
+ errorLog.put("event", Tags.ERROR.getKey());
+
+ final String message =
+ throwable.getCause() != null
+ ? throwable.getCause().getMessage()
+ : throwable.getMessage();
+ if (message != null) {
+ errorLog.put("message", message);
+ }
+ final StringWriter sw = new StringWriter();
+ throwable.printStackTrace(new PrintWriter(sw));
+ errorLog.put("stack", sw.toString());
+
+ return errorLog;
+ }
+ };
+}
diff --git a/dd-java-agent/instrumentation/servlet-2/src/test/groovy/JettyServletTest.groovy b/dd-java-agent/instrumentation/servlet-2/src/test/groovy/JettyServletTest.groovy
new file mode 100644
index 0000000000..83dc75839f
--- /dev/null
+++ b/dd-java-agent/instrumentation/servlet-2/src/test/groovy/JettyServletTest.groovy
@@ -0,0 +1,160 @@
+import datadog.opentracing.DDSpan
+import datadog.opentracing.DDTracer
+import datadog.trace.agent.test.AgentTestRunner
+import datadog.trace.api.DDSpanTypes
+import datadog.trace.common.writer.ListWriter
+import io.opentracing.util.GlobalTracer
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.Response
+import org.eclipse.jetty.server.Server
+import org.eclipse.jetty.servlet.ServletContextHandler
+import spock.lang.Unroll
+
+import java.lang.reflect.Field
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+class JettyServletTest extends AgentTestRunner {
+
+ static final int PORT = randomOpenPort()
+
+ // Jetty needs this to ensure consistent ordering for async.
+ static CountDownLatch latch
+ OkHttpClient client = new OkHttpClient.Builder()
+ .addNetworkInterceptor(new Interceptor() {
+ @Override
+ Response intercept(Interceptor.Chain chain) throws IOException {
+ def response = chain.proceed(chain.request())
+ JettyServletTest.latch.await(10, TimeUnit.SECONDS) // don't block forever or test never fails.
+ return response
+ }
+ })
+ // Uncomment when debugging:
+ .connectTimeout(1, TimeUnit.HOURS)
+ .writeTimeout(1, TimeUnit.HOURS)
+ .readTimeout(1, TimeUnit.HOURS)
+ .build()
+
+ private Server jettyServer
+ private ServletContextHandler servletContext
+
+ ListWriter writer = new ListWriter() {
+ @Override
+ void write(final List trace) {
+ add(trace)
+ JettyServletTest.latch.countDown()
+ }
+ }
+ DDTracer tracer = new DDTracer(writer)
+
+ def setup() {
+ jettyServer = new Server(PORT)
+ servletContext = new ServletContextHandler()
+
+ servletContext.addServlet(TestServlet.Sync, "/sync")
+
+ jettyServer.setHandler(servletContext)
+ jettyServer.start()
+
+ System.out.println(
+ "Jetty server: http://localhost:" + PORT + "/")
+
+ try {
+ GlobalTracer.register(tracer)
+ } catch (final Exception e) {
+ // Force it anyway using reflection
+ final Field field = GlobalTracer.getDeclaredField("tracer")
+ field.setAccessible(true)
+ field.set(null, tracer)
+ }
+ writer.start()
+ assert GlobalTracer.isRegistered()
+ }
+
+ def cleanup() {
+ jettyServer.stop()
+ jettyServer.destroy()
+ }
+
+ @Unroll
+ def "test #path servlet call"() {
+ setup:
+ latch = new CountDownLatch(1)
+ def request = new Request.Builder()
+ .url("http://localhost:$PORT/$path")
+ .get()
+ .build()
+ def response = client.newCall(request).execute()
+
+ expect:
+ response.body().string().trim() == expectedResponse
+ writer.size() == 2 // second (parent) trace is the okhttp call above...
+ def trace = writer.firstTrace()
+ trace.size() == 1
+ def span = trace[0]
+
+ span.context().operationName == "servlet.request"
+ span.context().spanType == DDSpanTypes.WEB_SERVLET
+ !span.context().getErrorFlag()
+ span.context().parentId != 0 // parent should be the okhttp call.
+ span.context().tags["http.url"] == "http://localhost:$PORT/$path"
+ span.context().tags["http.method"] == "GET"
+ span.context().tags["span.kind"] == "server"
+ span.context().tags["component"] == "java-web-servlet"
+ span.context().tags["http.status_code"] == null // sadly servlet 2.x doesn't expose it generically.
+ span.context().tags["thread.name"] != null
+ span.context().tags["thread.id"] != null
+ span.context().tags.size() == 7
+
+ where:
+ path | expectedResponse
+ "sync" | "Hello Sync"
+ }
+
+ @Unroll
+ def "test #path error servlet call"() {
+ setup:
+ def request = new Request.Builder()
+ .url("http://localhost:$PORT/$path?error=true")
+ .get()
+ .build()
+ def response = client.newCall(request).execute()
+
+ expect:
+ response.body().string().trim() != expectedResponse
+ writer.size() == 2 // second (parent) trace is the okhttp call above...
+ def trace = writer.firstTrace()
+ trace.size() == 1
+ def span = trace[0]
+
+ span.context().operationName == "servlet.request"
+ span.context().spanType == DDSpanTypes.WEB_SERVLET
+ span.context().getErrorFlag()
+ span.context().parentId != 0 // parent should be the okhttp call.
+ span.context().tags["http.url"] == "http://localhost:$PORT/$path"
+ span.context().tags["http.method"] == "GET"
+ span.context().tags["span.kind"] == "server"
+ span.context().tags["component"] == "java-web-servlet"
+ span.context().tags["http.status_code"] == null // sadly servlet 2.x doesn't expose it generically.
+ span.context().tags["thread.name"] != null
+ span.context().tags["thread.id"] != null
+ span.context().tags["error"] == true
+ span.context().tags["error.msg"] == "some $path error"
+ span.context().tags["error.type"] == RuntimeException.getName()
+ span.context().tags["error.stack"] != null
+ span.context().tags.size() == 11
+
+ where:
+ path | expectedResponse
+ "sync" | "Hello Sync"
+ }
+
+ private static int randomOpenPort() {
+ new ServerSocket(0).withCloseable {
+ it.setReuseAddress(true)
+ return it.getLocalPort()
+ }
+ }
+}
diff --git a/dd-java-agent/instrumentation/servlet-2/src/test/groovy/TestServlet.groovy b/dd-java-agent/instrumentation/servlet-2/src/test/groovy/TestServlet.groovy
new file mode 100644
index 0000000000..77b1f691c1
--- /dev/null
+++ b/dd-java-agent/instrumentation/servlet-2/src/test/groovy/TestServlet.groovy
@@ -0,0 +1,17 @@
+import groovy.servlet.AbstractHttpServlet
+
+import javax.servlet.http.HttpServletRequest
+import javax.servlet.http.HttpServletResponse
+
+class TestServlet {
+
+ static class Sync extends AbstractHttpServlet {
+ @Override
+ void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ if (req.getParameter("error") != null) {
+ throw new RuntimeException("some sync error")
+ }
+ resp.writer.print("Hello Sync")
+ }
+ }
+}
diff --git a/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle b/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle
index 9583e775c5..b8887a2800 100644
--- a/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle
+++ b/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle
@@ -25,4 +25,13 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
+
+ testCompile project(':dd-java-agent:testing')
+ testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '8.2.0.v20160908'
+ testCompile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '8.2.0.v20160908'
+ testCompile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '8.0.41'
+ testCompile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '8.0.41'
+
+ testCompile project(':dd-java-agent:instrumentation:okhttp-3') // used in the tests
+ testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0'
}
diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy b/dd-java-agent/instrumentation/servlet-3/src/test/groovy/JettyServletTest.groovy
similarity index 95%
rename from dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy
rename to dd-java-agent/instrumentation/servlet-3/src/test/groovy/JettyServletTest.groovy
index 52befee00a..33b1772640 100644
--- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy
+++ b/dd-java-agent/instrumentation/servlet-3/src/test/groovy/JettyServletTest.groovy
@@ -1,7 +1,6 @@
-package datadog.trace.agent.integration.servlet
-
import datadog.opentracing.DDSpan
import datadog.opentracing.DDTracer
+import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.DDSpanTypes
import datadog.trace.common.writer.ListWriter
import io.opentracing.util.GlobalTracer
@@ -11,21 +10,20 @@ import okhttp3.Request
import okhttp3.Response
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.ServletContextHandler
-import spock.lang.Specification
import spock.lang.Unroll
import java.lang.reflect.Field
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
-class JettyServletTest extends Specification {
+class JettyServletTest extends AgentTestRunner {
static final int PORT = randomOpenPort()
// Jetty needs this to ensure consistent ordering for async.
static CountDownLatch latch
OkHttpClient client = new OkHttpClient.Builder()
- .addNetworkInterceptor(new Interceptor() {
+ .addNetworkInterceptor(new Interceptor() {
@Override
Response intercept(Interceptor.Chain chain) throws IOException {
def response = chain.proceed(chain.request())
@@ -151,9 +149,9 @@ class JettyServletTest extends Specification {
span.context().tags.size() == 12
where:
- path | expectedResponse
+ path | expectedResponse
//"async" | "Hello Async" // FIXME: I can't seem get the async error handler to trigger
- "sync" | "Hello Sync"
+ "sync" | "Hello Sync"
}
private static int randomOpenPort() {
diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TestServlet.groovy b/dd-java-agent/instrumentation/servlet-3/src/test/groovy/TestServlet.groovy
similarity index 94%
rename from dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TestServlet.groovy
rename to dd-java-agent/instrumentation/servlet-3/src/test/groovy/TestServlet.groovy
index ac1da45fcd..fa25eaaa1d 100644
--- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TestServlet.groovy
+++ b/dd-java-agent/instrumentation/servlet-3/src/test/groovy/TestServlet.groovy
@@ -1,5 +1,3 @@
-package datadog.trace.agent.integration.servlet
-
import groovy.servlet.AbstractHttpServlet
import javax.servlet.annotation.WebServlet
diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy b/dd-java-agent/instrumentation/servlet-3/src/test/groovy/TomcatServletTest.groovy
similarity index 97%
rename from dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy
rename to dd-java-agent/instrumentation/servlet-3/src/test/groovy/TomcatServletTest.groovy
index 4106e6fc02..d324e7c1ec 100644
--- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy
+++ b/dd-java-agent/instrumentation/servlet-3/src/test/groovy/TomcatServletTest.groovy
@@ -1,7 +1,6 @@
-package datadog.trace.agent.integration.servlet
-
import com.google.common.io.Files
import datadog.opentracing.DDTracer
+import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.DDSpanTypes
import datadog.trace.common.writer.ListWriter
import io.opentracing.util.GlobalTracer
@@ -11,12 +10,11 @@ import org.apache.catalina.Context
import org.apache.catalina.startup.Tomcat
import org.apache.tomcat.JarScanFilter
import org.apache.tomcat.JarScanType
-import spock.lang.Specification
import spock.lang.Unroll
import java.lang.reflect.Field
-class TomcatServletTest extends Specification {
+class TomcatServletTest extends AgentTestRunner {
static final int PORT = randomOpenPort()
OkHttpClient client = new OkHttpClient.Builder()
diff --git a/dd-java-agent/tooling/src/main/java/datadog/trace/agent/tooling/DDAdvice.java b/dd-java-agent/tooling/src/main/java/datadog/trace/agent/tooling/DDAdvice.java
index bce90f5e92..442e635c36 100644
--- a/dd-java-agent/tooling/src/main/java/datadog/trace/agent/tooling/DDAdvice.java
+++ b/dd-java-agent/tooling/src/main/java/datadog/trace/agent/tooling/DDAdvice.java
@@ -18,9 +18,15 @@ public class DDAdvice extends AgentBuilder.Transformer.ForAdvice {
* @return the bytebuddy advice
*/
public static AgentBuilder.Transformer.ForAdvice create() {
- return new DDAdvice()
- .with(AGENT_CLASS_LOCATION_STRATEGY)
- .withExceptionHandler(ExceptionHandlers.defaultExceptionHandler());
+ return create(true);
+ }
+
+ public static AgentBuilder.Transformer.ForAdvice create(final boolean includeExceptionHandler) {
+ ForAdvice advice = new DDAdvice().with(AGENT_CLASS_LOCATION_STRATEGY);
+ if (includeExceptionHandler) {
+ advice = advice.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler());
+ }
+ return advice;
}
private DDAdvice() {}