Starting to get tests building
This commit is contained in:
parent
8f876c1b7d
commit
73122ea72c
|
@ -0,0 +1 @@
|
||||||
|
logs/
|
|
@ -0,0 +1,47 @@
|
||||||
|
ext {
|
||||||
|
minJavaVersionForTests = JavaVersion.VERSION_1_8
|
||||||
|
// Play doesn't work with Java 9+ until 2.6.12
|
||||||
|
maxJavaVersionForTests = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
muzzle {
|
||||||
|
pass {
|
||||||
|
group = 'com.typesafe.play'
|
||||||
|
module = 'play_2.11'
|
||||||
|
versions = '[2.3.0,2.4)'
|
||||||
|
assertInverse = true
|
||||||
|
}
|
||||||
|
fail {
|
||||||
|
group = 'com.typesafe.play'
|
||||||
|
module = 'play_2.12'
|
||||||
|
versions = '[,]'
|
||||||
|
}
|
||||||
|
fail {
|
||||||
|
group = 'com.typesafe.play'
|
||||||
|
module = 'play_2.13'
|
||||||
|
versions = '[,]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "${rootDir}/gradle/java.gradle"
|
||||||
|
apply from: "${rootDir}/gradle/test-with-scala.gradle"
|
||||||
|
|
||||||
|
apply plugin: 'org.unbroken-dome.test-sets'
|
||||||
|
|
||||||
|
testSets {
|
||||||
|
latestDepTest {
|
||||||
|
dirName = 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
main_java8Compile group: 'com.typesafe.play', name: 'play_2.11', version: '2.3.9'
|
||||||
|
|
||||||
|
testCompile group: 'com.typesafe.play', name: 'play-java_2.11', version: '2.3.9'
|
||||||
|
testCompile group: 'com.typesafe.play', name: 'play-java-ws_2.11', version: '2.3.9'
|
||||||
|
testCompile(group: 'com.typesafe.play', name: 'play-test_2.11', version: '2.3.9')
|
||||||
|
|
||||||
|
latestDepTestCompile group: 'com.typesafe.play', name: 'play-java_2.11', version: '2.3.+'
|
||||||
|
latestDepTestCompile group: 'com.typesafe.play', name: 'play-java-ws_2.11', version: '2.3.+'
|
||||||
|
latestDepTestCompile(group: 'com.typesafe.play', name: 'play-test_2.11', version: '2.3.+')
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package datadog.trace.instrumentation.play24;
|
||||||
|
|
||||||
|
import static datadog.trace.agent.tooling.ClassLoaderMatcher.hasClassesNamed;
|
||||||
|
import static datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers.implementsInterface;
|
||||||
|
import static java.util.Collections.singletonMap;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
|
import java.util.Map;
|
||||||
|
import net.bytebuddy.description.method.MethodDescription;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
|
@AutoService(Instrumenter.class)
|
||||||
|
public final class PlayInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
|
public PlayInstrumentation() {
|
||||||
|
super("play");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
||||||
|
// Optimization for expensive typeMatcher.
|
||||||
|
return hasClassesNamed("play.api.mvc.Action");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||||
|
return implementsInterface(named("play.api.mvc.Action"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] helperClassNames() {
|
||||||
|
return new String[] {
|
||||||
|
packageName + ".PlayHttpServerDecorator",
|
||||||
|
packageName + ".RequestCompleteCallback",
|
||||||
|
packageName + ".PlayHeaders",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||||
|
return singletonMap(
|
||||||
|
named("apply")
|
||||||
|
.and(takesArgument(0, named("play.api.mvc.Request")))
|
||||||
|
.and(returns(named("scala.concurrent.Future"))),
|
||||||
|
packageName + ".PlayAdvice");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package datadog.trace.instrumentation.play24;
|
||||||
|
|
||||||
|
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan;
|
||||||
|
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan;
|
||||||
|
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate;
|
||||||
|
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
|
||||||
|
import static datadog.trace.instrumentation.play24.PlayHeaders.GETTER;
|
||||||
|
import static datadog.trace.instrumentation.play24.PlayHttpServerDecorator.DECORATE;
|
||||||
|
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.Tags;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
import play.api.mvc.Action;
|
||||||
|
import play.api.mvc.Request;
|
||||||
|
import play.api.mvc.Result;
|
||||||
|
import scala.concurrent.Future;
|
||||||
|
|
||||||
|
public class PlayAdvice {
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static AgentScope onEnter(@Advice.Argument(0) final Request req) {
|
||||||
|
final AgentSpan span;
|
||||||
|
if (activeSpan() == null) {
|
||||||
|
final Context extractedContext = propagate().extract(req.headers(), GETTER);
|
||||||
|
span = startSpan("play.request", extractedContext);
|
||||||
|
} else {
|
||||||
|
// An upstream framework (e.g. akka-http, netty) has already started the span.
|
||||||
|
// Do not extract the context.
|
||||||
|
span = startSpan("play.request");
|
||||||
|
}
|
||||||
|
DECORATE.afterStart(span);
|
||||||
|
DECORATE.onConnection(span, req);
|
||||||
|
|
||||||
|
final AgentScope scope = activateSpan(span, false);
|
||||||
|
scope.setAsyncPropagation(true);
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
public static void stopTraceOnResponse(
|
||||||
|
@Advice.Enter final AgentScope playControllerScope,
|
||||||
|
@Advice.This final Object thisAction,
|
||||||
|
@Advice.Thrown final Throwable throwable,
|
||||||
|
@Advice.Argument(0) final Request req,
|
||||||
|
@Advice.Return(readOnly = false) final Future<Result> responseFuture) {
|
||||||
|
final AgentSpan playControllerSpan = playControllerScope.span();
|
||||||
|
|
||||||
|
// Call onRequest on return after tags are populated.
|
||||||
|
DECORATE.onRequest(playControllerSpan, req);
|
||||||
|
|
||||||
|
if (throwable == null) {
|
||||||
|
responseFuture.onComplete(
|
||||||
|
new RequestCompleteCallback(playControllerSpan),
|
||||||
|
((Action) thisAction).executionContext());
|
||||||
|
} else {
|
||||||
|
DECORATE.onError(playControllerSpan, throwable);
|
||||||
|
playControllerSpan.setTag(Tags.HTTP_STATUS, 500);
|
||||||
|
DECORATE.beforeFinish(playControllerSpan);
|
||||||
|
playControllerSpan.finish();
|
||||||
|
}
|
||||||
|
playControllerScope.close();
|
||||||
|
|
||||||
|
final AgentSpan rootSpan = activeSpan();
|
||||||
|
// set the resource name on the upstream akka/netty span
|
||||||
|
DECORATE.onRequest(rootSpan, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unused method for muzzle to allow only 2.4-2.5
|
||||||
|
public static void muzzleCheck() {
|
||||||
|
play.libs.Akka.system();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package datadog.trace.instrumentation.play24;
|
||||||
|
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.AgentPropagation;
|
||||||
|
import play.api.mvc.Headers;
|
||||||
|
import scala.Option;
|
||||||
|
import scala.collection.JavaConversions;
|
||||||
|
|
||||||
|
public class PlayHeaders implements AgentPropagation.Getter<Headers> {
|
||||||
|
|
||||||
|
public static final PlayHeaders GETTER = new PlayHeaders();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<String> keys(final Headers headers) {
|
||||||
|
return JavaConversions.asJavaIterable(headers.keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(final Headers headers, final String key) {
|
||||||
|
final Option<String> option = headers.get(key);
|
||||||
|
if (option.isDefined()) {
|
||||||
|
return option.get();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package datadog.trace.instrumentation.play24;
|
||||||
|
|
||||||
|
import datadog.trace.api.DDTags;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.Tags;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.UndeclaredThrowableException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import play.api.mvc.Request;
|
||||||
|
import play.api.mvc.Result;
|
||||||
|
import scala.Option;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class PlayHttpServerDecorator extends HttpServerDecorator<Request, Request, Result> {
|
||||||
|
public static final PlayHttpServerDecorator DECORATE = new PlayHttpServerDecorator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] instrumentationNames() {
|
||||||
|
return new String[] {"play"};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String component() {
|
||||||
|
return "play-action";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String method(final Request httpRequest) {
|
||||||
|
return httpRequest.method();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected URI url(final Request request) throws URISyntaxException {
|
||||||
|
return new URI((request.secure() ? "https://" : "http://") + request.host() + request.uri());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String peerHostIP(final Request request) {
|
||||||
|
return request.remoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer peerPort(final Request request) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer status(final Result httpResponse) {
|
||||||
|
return httpResponse.header().status();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AgentSpan onRequest(final AgentSpan span, final Request request) {
|
||||||
|
super.onRequest(span, request);
|
||||||
|
if (request != null) {
|
||||||
|
// more about routes here:
|
||||||
|
// https://github.com/playframework/playframework/blob/master/documentation/manual/releases/release26/migration26/Migration26.md#router-tags-are-now-attributes
|
||||||
|
final Option pathOption = request.tags().get("ROUTE_PATTERN");
|
||||||
|
if (!pathOption.isEmpty()) {
|
||||||
|
final String path = (String) pathOption.get();
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, request.method() + " " + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return span;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AgentSpan onError(final AgentSpan span, Throwable throwable) {
|
||||||
|
span.setTag(Tags.HTTP_STATUS, 500);
|
||||||
|
if (throwable != null
|
||||||
|
// This can be moved to instanceof check when using Java 8.
|
||||||
|
&& throwable.getClass().getName().equals("java.util.concurrent.CompletionException")
|
||||||
|
&& throwable.getCause() != null) {
|
||||||
|
throwable = throwable.getCause();
|
||||||
|
}
|
||||||
|
while ((throwable instanceof InvocationTargetException
|
||||||
|
|| throwable instanceof UndeclaredThrowableException)
|
||||||
|
&& throwable.getCause() != null) {
|
||||||
|
throwable = throwable.getCause();
|
||||||
|
}
|
||||||
|
return super.onError(span, throwable);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package datadog.trace.instrumentation.play24;
|
||||||
|
|
||||||
|
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeScope;
|
||||||
|
import static datadog.trace.instrumentation.play24.PlayHttpServerDecorator.DECORATE;
|
||||||
|
|
||||||
|
import datadog.trace.context.TraceScope;
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import play.api.mvc.Result;
|
||||||
|
import scala.util.Try;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class RequestCompleteCallback extends scala.runtime.AbstractFunction1<Try<Result>, Object> {
|
||||||
|
private final AgentSpan span;
|
||||||
|
|
||||||
|
public RequestCompleteCallback(final AgentSpan span) {
|
||||||
|
this.span = span;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object apply(final Try<Result> result) {
|
||||||
|
try {
|
||||||
|
if (result.isFailure()) {
|
||||||
|
DECORATE.onError(span, result.failed().get());
|
||||||
|
} else {
|
||||||
|
DECORATE.onResponse(span, result.get());
|
||||||
|
}
|
||||||
|
DECORATE.beforeFinish(span);
|
||||||
|
final TraceScope scope = activeScope();
|
||||||
|
if (scope != null) {
|
||||||
|
scope.setAsyncPropagation(false);
|
||||||
|
}
|
||||||
|
} catch (final Throwable t) {
|
||||||
|
log.debug("error in play instrumentation", t);
|
||||||
|
} finally {
|
||||||
|
span.finish();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import datadog.trace.agent.test.base.HttpClientTest
|
||||||
|
import play.libs.ws.WS
|
||||||
|
import spock.lang.AutoCleanup
|
||||||
|
import spock.lang.Shared
|
||||||
|
import spock.lang.Subject
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
// Play 2.6+ uses a separately versioned client that shades the underlying dependency
|
||||||
|
// This means our built in instrumentation won't work.
|
||||||
|
class PlayWSClientTest extends HttpClientTest {
|
||||||
|
@Subject
|
||||||
|
@Shared
|
||||||
|
@AutoCleanup
|
||||||
|
def client = WS.client()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int doRequest(String method, URI uri, Map<String, String> headers, Closure callback) {
|
||||||
|
def request = client.url(uri.toString())
|
||||||
|
headers.entrySet().each {
|
||||||
|
request.setHeader(it.key, it.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
def status = request.execute(method).map({
|
||||||
|
callback?.call()
|
||||||
|
it
|
||||||
|
}).map({
|
||||||
|
it.status
|
||||||
|
})
|
||||||
|
return status.get(1, TimeUnit.SECONDS)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String component() {
|
||||||
|
return "" // NettyHttpClientDecorator.DECORATE.component()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String expectedOperationName() {
|
||||||
|
return "netty.client.request"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean testRedirects() {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean testConnectionFailure() {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package server;
|
||||||
|
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import datadog.trace.agent.test.base.HttpServerTestAdvice;
|
||||||
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
|
|
||||||
|
@AutoService(Instrumenter.class)
|
||||||
|
public class NettyServerTestInstrumentation implements Instrumenter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||||
|
return agentBuilder
|
||||||
|
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
|
||||||
|
.transform(
|
||||||
|
new AgentBuilder.Transformer.ForAdvice()
|
||||||
|
.advice(
|
||||||
|
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
class PlayAsyncServerTest { //extends PlayServerTest {
|
||||||
|
// @Override
|
||||||
|
// Server startServer(int port) {
|
||||||
|
// def router =
|
||||||
|
// new RoutingDsl()
|
||||||
|
// .GET(SUCCESS.getPath()).routeAsync({
|
||||||
|
// CompletableFuture.supplyAsync({
|
||||||
|
// controller(SUCCESS) {
|
||||||
|
// Results.status(SUCCESS.getStatus(), SUCCESS.getBody())
|
||||||
|
// }
|
||||||
|
// }, HttpExecution.defaultContext())
|
||||||
|
// } as Supplier)
|
||||||
|
// .GET(QUERY_PARAM.getPath()).routeAsync({
|
||||||
|
// CompletableFuture.supplyAsync({
|
||||||
|
// controller(QUERY_PARAM) {
|
||||||
|
// Results.status(QUERY_PARAM.getStatus(), QUERY_PARAM.getBody())
|
||||||
|
// }
|
||||||
|
// }, HttpExecution.defaultContext())
|
||||||
|
// } as Supplier)
|
||||||
|
// .GET(REDIRECT.getPath()).routeAsync({
|
||||||
|
// CompletableFuture.supplyAsync({
|
||||||
|
// controller(REDIRECT) {
|
||||||
|
// Results.found(REDIRECT.getBody())
|
||||||
|
// }
|
||||||
|
// }, HttpExecution.defaultContext())
|
||||||
|
// } as Supplier)
|
||||||
|
// .GET(ERROR.getPath()).routeAsync({
|
||||||
|
// CompletableFuture.supplyAsync({
|
||||||
|
// controller(ERROR) {
|
||||||
|
// Results.status(ERROR.getStatus(), ERROR.getBody())
|
||||||
|
// }
|
||||||
|
// }, HttpExecution.defaultContext())
|
||||||
|
// } as Supplier)
|
||||||
|
// .GET(EXCEPTION.getPath()).routeAsync({
|
||||||
|
// CompletableFuture.supplyAsync({
|
||||||
|
// controller(EXCEPTION) {
|
||||||
|
// throw new Exception(EXCEPTION.getBody())
|
||||||
|
// }
|
||||||
|
// }, HttpExecution.defaultContext())
|
||||||
|
// } as Supplier)
|
||||||
|
//
|
||||||
|
// return Server.forRouter(router.build(), port)
|
||||||
|
// }
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import datadog.opentracing.DDSpan
|
||||||
|
import datadog.trace.agent.test.asserts.TraceAssert
|
||||||
|
import datadog.trace.agent.test.base.HttpServerTest
|
||||||
|
import datadog.trace.api.DDSpanTypes
|
||||||
|
import datadog.trace.api.DDTags
|
||||||
|
import datadog.trace.bootstrap.instrumentation.api.Tags
|
||||||
|
import play.api.test.TestServer
|
||||||
|
|
||||||
|
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.*
|
||||||
|
|
||||||
|
class PlayServerTest extends HttpServerTest<TestServer> {
|
||||||
|
@Override
|
||||||
|
TestServer startServer(int port) {
|
||||||
|
def server = SyncServer.server(port)
|
||||||
|
server.start()
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void stopServer(TestServer server) {
|
||||||
|
server.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String component() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String expectedOperationName() {
|
||||||
|
return "netty.request"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean hasHandlerSpan() {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// Return the handler span's name
|
||||||
|
String reorderHandlerSpan() {
|
||||||
|
"play.request"
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean testExceptionBody() {
|
||||||
|
// I can't figure out how to set a proper exception handler to customize the response body.
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void handlerSpan(TraceAssert trace, int index, Object parent, ServerEndpoint endpoint = SUCCESS) {
|
||||||
|
trace.span(index) {
|
||||||
|
serviceName expectedServiceName()
|
||||||
|
operationName "play.request"
|
||||||
|
spanType DDSpanTypes.HTTP_SERVER
|
||||||
|
errored endpoint == ERROR || endpoint == EXCEPTION
|
||||||
|
childOf(parent as DDSpan)
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT" ""
|
||||||
|
"$Tags.SPAN_KIND" Tags.SPAN_KIND_SERVER
|
||||||
|
"$Tags.PEER_HOST_IPV4" { it == null || it == "127.0.0.1" } // Optional
|
||||||
|
"$Tags.HTTP_URL" String
|
||||||
|
"$Tags.HTTP_METHOD" String
|
||||||
|
"$Tags.HTTP_STATUS" Integer
|
||||||
|
if (endpoint == ERROR) {
|
||||||
|
"$Tags.ERROR" true
|
||||||
|
} else if (endpoint == EXCEPTION) {
|
||||||
|
errorTags(Exception, EXCEPTION.body)
|
||||||
|
}
|
||||||
|
if (endpoint.query) {
|
||||||
|
"$DDTags.HTTP_QUERY" endpoint.query
|
||||||
|
}
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
object AsyncServer {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint._
|
||||||
|
import play.api.mvc.{Action, Handler, Results}
|
||||||
|
import play.api.test.{FakeApplication, TestServer}
|
||||||
|
|
||||||
|
object SyncServer {
|
||||||
|
val routes: PartialFunction[(String, String), Handler] = {
|
||||||
|
case ("GET", "/success") => Action { request => Results.Status(SUCCESS.getStatus) }
|
||||||
|
}
|
||||||
|
|
||||||
|
def server(port: Int): TestServer = {
|
||||||
|
TestServer(port, FakeApplication(withRoutes = routes))
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,6 +116,7 @@ include ':dd-java-agent:instrumentation:netty-3.8'
|
||||||
include ':dd-java-agent:instrumentation:netty-4.0'
|
include ':dd-java-agent:instrumentation:netty-4.0'
|
||||||
include ':dd-java-agent:instrumentation:netty-4.1'
|
include ':dd-java-agent:instrumentation:netty-4.1'
|
||||||
include ':dd-java-agent:instrumentation:okhttp-3'
|
include ':dd-java-agent:instrumentation:okhttp-3'
|
||||||
|
include ':dd-java-agent:instrumentation:play-2.3'
|
||||||
include ':dd-java-agent:instrumentation:play-2.4'
|
include ':dd-java-agent:instrumentation:play-2.4'
|
||||||
include ':dd-java-agent:instrumentation:play-2.6'
|
include ':dd-java-agent:instrumentation:play-2.6'
|
||||||
include ':dd-java-agent:instrumentation:play-ws'
|
include ':dd-java-agent:instrumentation:play-ws'
|
||||||
|
|
Loading…
Reference in New Issue