Repository: datadog/dd-trace-java
Issue: ClassCastException with Slick

Using Slick 3.2.1, I see the following exceptions in the logs:

> Caused by: java.lang.ClassCastException: datadog.trace.instrumentation.java.concurrent.ExecutorInstrumentation$RunnableWrapper cannot be cast to slick.util.AsyncExecutor$PrioritizedRunnable
        at slick.util.ManagedArrayBlockingQueue.offer(ManagedArrayBlockingQueue.scala:13)
        at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
        at slick.util.AsyncExecutor$$anon$2$$anon$3.execute(AsyncExecutor.scala:120)
        ...
        at slick.basic.BasicBackend$DatabaseDef.runSynchronousDatabaseAction(BasicBackend.scala:231)
        at slick.basic.BasicBackend$DatabaseDef.runSynchronousDatabaseAction$(BasicBackend.scala:229)
        at slick.jdbc.JdbcBackend$DatabaseDef.runSynchronousDatabaseAction(JdbcBackend.scala:37)
        at slick.basic.BasicBackend$DatabaseDef.runInContext(BasicBackend.scala:208)
        at slick.basic.BasicBackend$DatabaseDef.runInContext$(BasicBackend.scala:140)
        at slick.jdbc.JdbcBackend$DatabaseDef.runInContext(JdbcBackend.scala:37)
        at slick.basic.BasicBackend$DatabaseDef.runInternal(BasicBackend.scala:76)
        at slick.basic.BasicBackend$DatabaseDef.runInternal$(BasicBackend.scala:75)
        at slick.jdbc.JdbcBackend$DatabaseDef.runInternal(JdbcBackend.scala:37)
        at slick.basic.BasicBackend$DatabaseDef.run(BasicBackend.scala:73)
        at slick.basic.BasicBackend$DatabaseDef.run$(BasicBackend.scala:73)
        at slick.jdbc.JdbcBackend$DatabaseDef.run(JdbcBackend.scala:37)

Looks like the Java APM agent is interfering with a cast that occurs in Slick. Let me know if you need any other details.

Changed files:
dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java

diff --git a/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java b/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java
index 0ecbf2ae84..2dca101cbc 100644
--- a/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java
+++ b/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java
@@ -137,12 +137,13 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
   public static class WrapRunnableAdvice {
     @Advice.OnMethodEnter(suppress = Throwable.class)
     public static DatadogWrapper wrapJob(
-        @Advice.Argument(value = 0, readOnly = false) Runnable task) {
+        @Advice.This Object dis, @Advice.Argument(value = 0, readOnly = false) Runnable task) {
       final Scope scope = GlobalTracer.get().scopeManager().active();
       if (scope instanceof TraceScope
           && ((TraceScope) scope).isAsyncPropagating()
           && task != null
-          && !(task instanceof DatadogWrapper)) {
+          && !(task instanceof DatadogWrapper)
+          && (!dis.getClass().getName().startsWith("slick.util.AsyncExecutor"))) {
         task = new RunnableWrapper(task, (TraceScope) scope);
         return (RunnableWrapper) task;
       }
@@ -161,12 +162,13 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
   public static class WrapCallableAdvice {
     @Advice.OnMethodEnter(suppress = Throwable.class)
     public static DatadogWrapper wrapJob(
-        @Advice.Argument(value = 0, readOnly = false) Callable<?> task) {
+        @Advice.This Object dis, @Advice.Argument(value = 0, readOnly = false) Callable<?> task) {
       final Scope scope = GlobalTracer.get().scopeManager().active();
       if (scope instanceof TraceScope
           && ((TraceScope) scope).isAsyncPropagating()
           && task != null
-          && !(task instanceof DatadogWrapper)) {
+          && !(task instanceof DatadogWrapper)
+          && (!dis.getClass().getName().startsWith("slick.util.AsyncExecutor"))) {
         task = new CallableWrapper<>(task, (TraceScope) scope);
         return (CallableWrapper) task;
       }
@@ -185,9 +187,12 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
   public static class WrapCallableCollectionAdvice {
     @Advice.OnMethodEnter(suppress = Throwable.class)
     public static Collection<?> wrapJob(
+        @Advice.This Object dis,
         @Advice.Argument(value = 0, readOnly = false) Collection<? extends Callable<?>> tasks) {
       final Scope scope = GlobalTracer.get().scopeManager().active();
-      if (scope instanceof TraceScope && ((TraceScope) scope).isAsyncPropagating()) {
+      if (scope instanceof TraceScope
+          && ((TraceScope) scope).isAsyncPropagating()
+          && (!dis.getClass().getName().startsWith("slick.util.AsyncExecutor"))) {
         final Collection<Callable<?>> wrappedTasks = new ArrayList<>(tasks.size());
         for (Callable<?> task : tasks) {
           if (task != null) {