-
Notifications
You must be signed in to change notification settings - Fork 312
Add phantom instrumentation #1515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
047b044
Add phantom instrumentation
michaelpigg 7dba0da
WIP additional tests
michaelpigg 749aee2
WIP playing around with tests
michaelpigg 96c33f1
WIP Testing plain cassandra
michaelpigg 47352d1
More debugging
michaelpigg dc19712
Change to GuavaAdapter, update tests
michaelpigg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Set properties before any plugins get loaded | ||
ext { | ||
minJavaVersionForTests = JavaVersion.VERSION_1_8 | ||
} | ||
|
||
apply from: "${rootDir}/gradle/java.gradle" | ||
apply from: "${rootDir}/gradle/test-with-scala.gradle" | ||
|
||
apply plugin: 'org.unbroken-dome.test-sets' | ||
|
||
|
||
dependencies { | ||
main_java8CompileOnly group: 'com.outworkers', name: 'phantom-dsl_2.11', version: '2.59.0' | ||
main_java8CompileOnly group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.0.0' | ||
main_java8CompileOnly group: 'io.monix', name: 'monix_2.11', version: '3.2.1' | ||
compile project(':dd-trace-api') | ||
compile project(':dd-java-agent:agent-tooling') | ||
|
||
// compile deps.opentracing | ||
// compile deps.autoservice | ||
// annotationProcessor deps.autoservice | ||
//compile project(':dd-java-agent:instrumentation:hibernate') | ||
testCompile project(':dd-java-agent:instrumentation:trace-annotation') | ||
testCompile project(':dd-java-agent:instrumentation:java-concurrent') | ||
testCompile project(':dd-java-agent:instrumentation:datastax-cassandra-3') | ||
testCompile project(':dd-java-agent:instrumentation:phantom') | ||
|
||
testCompile group: 'com.outworkers', name: 'phantom-dsl_2.11', version: '2.59.0' | ||
testCompile group: 'com.outworkers', name: 'phantom-monix_2.11', version: '2.59.0' | ||
testCompile group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.0.0' | ||
testCompile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.31' | ||
testCompile group: 'io.monix', name: 'monix_2.11', version: '3.2.1' | ||
testCompile deps.scala | ||
testCompile group: 'org.scala-lang', name: 'scala-reflect', version: '2.11.12' | ||
testCompile 'org.scala-lang.modules:scala-java8-compat_2.11:0.9.1' | ||
testCompile group: 'org.cassandraunit', name: 'cassandra-unit', version: '3.11.2.0' | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally we like to have a latestDepTest task that would test the latest version of phantom that this instrumentation supports |
||
|
49 changes: 49 additions & 0 deletions
49
...phantom/src/main/java/datadog/trace/instrumentation/phantom/FutureCompletionListener.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package datadog.trace.instrumentation.phantom; | ||
|
||
import com.outworkers.phantom.ResultSet; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentScope; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentSpan; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import scala.runtime.AbstractFunction1; | ||
import scala.util.Try; | ||
|
||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; | ||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeScope; | ||
import static datadog.trace.instrumentation.phantom.PhantomDecorator.DECORATE; | ||
|
||
public class FutureCompletionListener extends AbstractFunction1<Try<ResultSet>, Object> { | ||
private static final Logger log = LoggerFactory.getLogger(FutureCompletionListener.class); | ||
|
||
private final AgentSpan agentSpan; | ||
public FutureCompletionListener(AgentSpan agentSpan) { | ||
this.agentSpan = agentSpan; | ||
} | ||
|
||
@Override | ||
public Object apply(final Try<ResultSet> resultSetTry) { | ||
log.debug("phantom future completed"); | ||
final AgentScope scope = activateSpan(agentSpan); | ||
try { | ||
final ResultSet resultSet = resultSetTry.get(); // TODO: Optimize the potential throw | ||
log.debug("Call completed successfully"); | ||
if (resultSet != null) { | ||
String keyspace = resultSet.getExecutionInfo().getStatement().getKeyspace(); | ||
if (keyspace != null) { | ||
agentSpan.setTag("keyspace", keyspace); | ||
} | ||
} | ||
DECORATE.beforeFinish(agentSpan); | ||
} catch (final Throwable t) { | ||
log.debug("Call completed with error"); | ||
DECORATE.onError(agentSpan, t); | ||
} finally { | ||
log.debug("doing finish and close"); | ||
agentSpan.finish(); | ||
scope.setAsyncPropagation(false); | ||
scope.close(); | ||
} | ||
return null; | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...ation/phantom/src/main/java/datadog/trace/instrumentation/phantom/GuavaAdapterAdvice.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package datadog.trace.instrumentation.phantom; | ||
|
||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; | ||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; | ||
import static datadog.trace.instrumentation.phantom.PhantomDecorator.DECORATE; | ||
|
||
import com.datastax.driver.core.Session; | ||
import com.datastax.driver.core.Statement; | ||
import com.outworkers.phantom.ResultSet; | ||
import com.outworkers.phantom.ops.QueryContext; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentScope; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentSpan; | ||
import net.bytebuddy.asm.Advice; | ||
import net.bytebuddy.implementation.bytecode.assign.Assigner; | ||
import scala.concurrent.ExecutionContext; | ||
import scala.concurrent.ExecutionContext$; | ||
import scala.concurrent.ExecutionContextExecutor; | ||
import scala.concurrent.Future; | ||
|
||
public class GuavaAdapterAdvice { | ||
@Advice.OnMethodEnter(suppress = Throwable.class) | ||
public static AgentScope enter(@Advice.Argument(value = 0) final Statement statement, | ||
@Advice.Argument(value = 1) final Session session, | ||
@Advice.Argument(value = 2) final ExecutionContextExecutor ctx ) { | ||
System.out.println("Calling with context " + ctx.toString()); | ||
final AgentScope scope = startSpanWithScope(statement); | ||
scope.setAsyncPropagation(true); | ||
return scope; | ||
} | ||
|
||
public static AgentScope startSpanWithScope(final Statement statement) { | ||
final AgentSpan span = startSpan("phantom.future"); | ||
DECORATE.afterStart(span); | ||
DECORATE.onStatement(span, statement.toString()); | ||
//log.debug("activating span " + span); | ||
return activateSpan(span); | ||
} | ||
|
||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||
public static void exit( | ||
@Advice.Argument(value = 2) final ExecutionContextExecutor ctx, | ||
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Future<ResultSet> resultSetFuture, | ||
@Advice.Enter final AgentScope agentScope) { | ||
//log.debug("onMethodExit " + agentScope.toString()); | ||
if (agentScope == null || resultSetFuture == null) { | ||
return; | ||
} | ||
|
||
resultSetFuture.onComplete(new FutureCompletionListener(agentScope.span()), ctx); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
...umentation/phantom/src/main/java/datadog/trace/instrumentation/phantom/PhantomAdvice.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package datadog.trace.instrumentation.phantom; | ||
|
||
import com.datastax.driver.core.Session; | ||
import com.outworkers.phantom.ResultSet; | ||
import com.outworkers.phantom.ops.QueryContext; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentScope; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentSpan; | ||
import net.bytebuddy.asm.Advice; | ||
import net.bytebuddy.implementation.bytecode.assign.Assigner; | ||
import scala.concurrent.ExecutionContextExecutor; | ||
import scala.concurrent.Future; | ||
|
||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; | ||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; | ||
import static datadog.trace.instrumentation.phantom.PhantomDecorator.DECORATE; | ||
|
||
public class PhantomAdvice { | ||
@Advice.OnMethodEnter(suppress = Throwable.class) | ||
public static AgentScope enter(@Advice.This final QueryContext.RootQueryOps rootQueryOps, | ||
@Advice.Argument(value = 0) final Session session, | ||
@Advice.Argument(value = 1) final ExecutionContextExecutor ctx ) { | ||
System.out.println("Calling with context " + ctx.toString()); | ||
final AgentScope scope = startSpanWithScope(rootQueryOps); | ||
scope.setAsyncPropagation(true); | ||
return scope; | ||
} | ||
|
||
public static AgentScope startSpanWithScope(final QueryContext.RootQueryOps queryOps) { | ||
final AgentSpan span = startSpan("phantom.future"); | ||
DECORATE.afterStart(span); | ||
DECORATE.onStatement(span, queryOps.query().queryString()); | ||
//log.debug("activating span " + span); | ||
return activateSpan(span); | ||
} | ||
|
||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||
public static void exit( | ||
@Advice.Argument(value = 1) final ExecutionContextExecutor ctx, | ||
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Future<ResultSet> resultSetFuture, | ||
@Advice.Enter final AgentScope agentScope) { | ||
//log.debug("onMethodExit " + agentScope.toString()); | ||
if (agentScope == null || resultSetFuture == null) { | ||
return; | ||
} | ||
|
||
resultSetFuture.onComplete(new FutureCompletionListener(agentScope.span()), ctx); | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
...ntation/phantom/src/main/java/datadog/trace/instrumentation/phantom/PhantomDecorator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package datadog.trace.instrumentation.phantom; | ||
|
||
import datadog.trace.api.DDSpanTypes; | ||
import datadog.trace.bootstrap.instrumentation.decorator.OrmClientDecorator; | ||
import datadog.trace.bootstrap.instrumentation.decorator.ServerDecorator; | ||
|
||
public class PhantomDecorator extends OrmClientDecorator { | ||
public static final PhantomDecorator DECORATE = new PhantomDecorator(); | ||
|
||
@Override | ||
protected String[] instrumentationNames() { | ||
return new String[] {"phantom"}; | ||
} | ||
|
||
@Override | ||
protected String spanType() { | ||
return "phantom"; | ||
} | ||
|
||
@Override | ||
protected String component() { | ||
return "scala-phantom"; | ||
} | ||
|
||
@Override | ||
public String entityName(Object entity) { | ||
return null; | ||
} | ||
|
||
@Override | ||
protected String dbType() { | ||
return DDSpanTypes.CASSANDRA; | ||
} | ||
|
||
@Override | ||
protected String dbUser(Object o) { | ||
return null; | ||
} | ||
|
||
@Override | ||
protected String dbInstance(Object o) { | ||
return null; | ||
} | ||
|
||
@Override | ||
protected String service() { | ||
return "phantom"; | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
...n/phantom/src/main/java/datadog/trace/instrumentation/phantom/PhantomInstrumentation.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package datadog.trace.instrumentation.phantom; | ||
|
||
import com.datastax.driver.core.Session; | ||
import com.datastax.driver.core.Statement; | ||
import com.google.auto.service.AutoService; | ||
import com.outworkers.phantom.ResultSet; | ||
import com.outworkers.phantom.ops.QueryContext; | ||
import datadog.trace.agent.tooling.Instrumenter; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentScope; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentSpan; | ||
import datadog.trace.context.TraceScope; | ||
import java.util.HashMap; | ||
import lombok.extern.slf4j.Slf4j; | ||
import net.bytebuddy.asm.Advice; | ||
import net.bytebuddy.description.method.MethodDescription; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.implementation.bind.annotation.SuperCall; | ||
import net.bytebuddy.matcher.ElementMatcher; | ||
import net.bytebuddy.matcher.ElementMatchers; | ||
import scala.runtime.AbstractFunction1; | ||
import scala.concurrent.ExecutionContextExecutor; | ||
import scala.concurrent.Future; | ||
import scala.util.Try; | ||
|
||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.*; | ||
import static net.bytebuddy.matcher.ElementMatchers.*; | ||
|
||
@Slf4j | ||
@AutoService(Instrumenter.class) | ||
public class PhantomInstrumentation extends Instrumenter.Default { | ||
public PhantomInstrumentation() { | ||
super("phantom", "scala-phantom"); | ||
} | ||
|
||
|
||
@Override | ||
public ElementMatcher<? super TypeDescription> typeMatcher() { | ||
return ElementMatchers.nameStartsWith("com.outworkers.phantom.builder.query.execution.PromiseInterface"); | ||
} | ||
|
||
@Override | ||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { | ||
final Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>(); | ||
//transformers.put(isMethod().and(named("future")), packageName + ".PhantomAdvice"); | ||
transformers.put(isMethod().and(named("fromGuava").and(ElementMatchers.takesArgument(0, named("com.datastax.driver.core.Statement")))), | ||
packageName + ".GuavaAdapterAdvice"); | ||
return transformers; | ||
} | ||
|
||
@Override | ||
public String[] helperClassNames() { | ||
return new String[]{ | ||
packageName + ".FutureCompletionListener", | ||
packageName + ".PhantomDecorator" | ||
}; | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...n/phantom/src/main/java/datadog/trace/instrumentation/phantom/TaskCompletionListener.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package datadog.trace.instrumentation.phantom; | ||
|
||
import datadog.trace.bootstrap.instrumentation.api.AgentScope; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentSpan; | ||
import monix.eval.Task; | ||
import scala.Function1; | ||
import scala.Option; | ||
import scala.runtime.AbstractFunction1; | ||
import scala.runtime.BoxedUnit; | ||
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; | ||
public class TaskCompletionListener extends AbstractFunction1<Option<Throwable>, Task<BoxedUnit>> { | ||
private final AgentSpan agentSpan; | ||
|
||
public TaskCompletionListener(final AgentSpan agentSpan) { | ||
this.agentSpan = agentSpan; | ||
} | ||
|
||
@Override | ||
public Task<BoxedUnit> apply(final Option<Throwable> throwableOption) { | ||
final AgentScope scope = activateSpan(agentSpan); | ||
agentSpan.finish(); | ||
scope.setAsyncPropagation(false); | ||
scope.close(); | ||
return null; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I missed this. We also need a muzzle check. This gives us a test that the instrumentation activates when we expect it to, and optionally doesn't activate when we expect it not to