Skip to content

Commit 3bac106

Browse files
Fix finatra latest dep test
1 parent c81ded7 commit 3bac106

6 files changed

Lines changed: 220 additions & 3 deletions

File tree

dd-java-agent/instrumentation/finatra-2.9/finatra-2.9.gradle

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ apply from: "$rootDir/gradle/test-with-scala.gradle"
99
apply plugin: 'org.unbroken-dome.test-sets'
1010

1111
testSets {
12-
13-
latestDepTest {
12+
// Up to 20.7 where the server structure changes
13+
latestPre207Test {
1414
dirName = 'test'
1515
}
16+
17+
latestDepTest
1618
}
1719

1820
muzzle {
@@ -40,11 +42,20 @@ dependencies {
4042
// Required for older versions of finatra on JDKs >= 11
4143
testCompile group: 'com.sun.activation', name: 'javax.activation', version: '1.2.0'
4244

45+
latestPre207TestCompile group: 'com.twitter', name: 'finatra-http_2.11', version: '[,20.7.0)'
46+
4347
latestDepTestCompile group: 'com.twitter', name: 'finatra-http_2.11', version: '+'
44-
latestDepTestCompile(group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.0')
48+
latestDepTestCompile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.0'
4549
}
4650

4751
compileLatestDepTestGroovy {
4852
classpath = classpath.plus(files(compileLatestDepTestScala.destinationDir))
4953
dependsOn compileLatestDepTestScala
5054
}
55+
56+
compileLatestPre207TestGroovy {
57+
classpath = classpath.plus(files(compileLatestPre207TestScala.destinationDir))
58+
dependsOn compileLatestPre207TestScala
59+
}
60+
61+
latestDepTest.finalizedBy latestPre207Test
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import com.twitter.app.lifecycle.Event
2+
import com.twitter.app.lifecycle.Observer
3+
import com.twitter.finatra.http.HttpServer
4+
import com.twitter.util.Await
5+
import com.twitter.util.Closable
6+
import com.twitter.util.Duration
7+
import com.twitter.util.Promise
8+
import datadog.trace.agent.test.asserts.TraceAssert
9+
import datadog.trace.agent.test.base.HttpServerTest
10+
import datadog.trace.api.DDSpanTypes
11+
import datadog.trace.bootstrap.instrumentation.api.Tags
12+
import datadog.trace.core.DDSpan
13+
import datadog.trace.instrumentation.finatra.FinatraDecorator
14+
15+
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.ERROR
16+
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
17+
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.SUCCESS
18+
19+
class FinatraServer270Test extends HttpServerTest<HttpServer> {
20+
private static final Duration TIMEOUT = Duration.fromSeconds(5)
21+
private static final Duration STARTUP_TIMEOUT = Duration.fromSeconds(20)
22+
23+
static closeAndWait(Closable closable) {
24+
if (closable != null) {
25+
Await.ready(closable.close(), TIMEOUT)
26+
}
27+
}
28+
29+
@Override
30+
HttpServer startServer(int port) {
31+
HttpServer testServer = new FinatraServer()
32+
33+
// Starting the server is blocking so start it in a separate thread
34+
Thread startupThread = new Thread({
35+
testServer.main("-admin.port=:0", "-http.port=:" + port)
36+
})
37+
startupThread.setDaemon(true)
38+
startupThread.start()
39+
40+
Promise<Boolean> startupPromise = new Promise<>()
41+
42+
testServer.withObserver(new Observer() {
43+
@Override
44+
void onSuccess(Event event) {
45+
if (event == testServer.startupCompletionEvent()) {
46+
startupPromise.setValue(true)
47+
}
48+
}
49+
50+
void onEntry(Event event) {
51+
52+
}
53+
54+
@Override
55+
void onFailure(Event stage, Throwable throwable) {
56+
if (stage != Event.Close$.MODULE$) {
57+
startupPromise.setException(throwable)
58+
}
59+
}
60+
})
61+
62+
Await.result(startupPromise, STARTUP_TIMEOUT)
63+
64+
return testServer
65+
}
66+
67+
@Override
68+
boolean hasHandlerSpan() {
69+
return true
70+
}
71+
72+
@Override
73+
boolean testNotFound() {
74+
// Resource name is set to "GET /notFound"
75+
false
76+
}
77+
78+
@Override
79+
void stopServer(HttpServer httpServer) {
80+
Await.ready(httpServer.close(), TIMEOUT)
81+
}
82+
83+
@Override
84+
String component() {
85+
return FinatraDecorator.DECORATE.component()
86+
}
87+
88+
@Override
89+
String expectedOperationName() {
90+
return "finatra.request"
91+
}
92+
93+
void handlerSpan(TraceAssert trace, int index, Object parent, ServerEndpoint endpoint = SUCCESS) {
94+
def errorEndpoint = endpoint == EXCEPTION || endpoint == ERROR
95+
trace.span(index) {
96+
serviceName expectedServiceName()
97+
operationName "finatra.controller"
98+
resourceName "FinatraController"
99+
spanType DDSpanTypes.HTTP_SERVER
100+
errored errorEndpoint
101+
childOf(parent as DDSpan)
102+
tags {
103+
"$Tags.COMPONENT" FinatraDecorator.DECORATE.component()
104+
"$Tags.SPAN_KIND" Tags.SPAN_KIND_SERVER
105+
106+
// Finatra doesn't propagate the stack trace or exception to the instrumentation
107+
// so the normal errorTags() method can't be used
108+
defaultTags()
109+
}
110+
}
111+
}
112+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import static net.bytebuddy.matcher.ElementMatchers.named;
2+
3+
import com.google.auto.service.AutoService;
4+
import datadog.trace.agent.test.base.HttpServerTestAdvice;
5+
import datadog.trace.agent.tooling.Instrumenter;
6+
import net.bytebuddy.agent.builder.AgentBuilder;
7+
8+
@AutoService(Instrumenter.class)
9+
public class NettyServerTestInstrumentation implements Instrumenter {
10+
11+
@Override
12+
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
13+
return agentBuilder
14+
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
15+
.transform(
16+
new AgentBuilder.Transformer.ForAdvice()
17+
.advice(
18+
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
19+
}
20+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import com.twitter.finagle.http.{Request, Response}
2+
import com.twitter.finatra.http.Controller
3+
import com.twitter.util.Future
4+
import datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint._
5+
import datadog.trace.agent.test.base.HttpServerTest.controller
6+
import groovy.lang.Closure
7+
8+
class FinatraController extends Controller {
9+
any(SUCCESS.getPath) { request: Request =>
10+
controller(SUCCESS, new Closure[Response](null) {
11+
override def call(): Response = {
12+
response.ok(SUCCESS.getBody)
13+
}
14+
})
15+
}
16+
17+
any(ERROR.getPath) { request: Request =>
18+
controller(ERROR, new Closure[Response](null) {
19+
override def call(): Response = {
20+
response.internalServerError(ERROR.getBody)
21+
}
22+
})
23+
}
24+
25+
any(QUERY_PARAM.getPath) { request: Request =>
26+
controller(QUERY_PARAM, new Closure[Response](null) {
27+
override def call(): Response = {
28+
response.ok(QUERY_PARAM.getBody)
29+
}
30+
})
31+
}
32+
33+
any(EXCEPTION.getPath) { request: Request =>
34+
controller(EXCEPTION, new Closure[Future[Response]](null) {
35+
override def call(): Future[Response] = {
36+
throw new Exception(EXCEPTION.getBody)
37+
}
38+
})
39+
}
40+
41+
any(REDIRECT.getPath) { request: Request =>
42+
controller(REDIRECT, new Closure[Response](null) {
43+
override def call(): Response = {
44+
response.found.location(REDIRECT.getBody)
45+
}
46+
})
47+
}
48+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import com.twitter.finagle.http.Request
2+
import com.twitter.finatra.http.HttpServer
3+
import com.twitter.finatra.http.filters.ExceptionMappingFilter
4+
import com.twitter.finatra.http.routing.HttpRouter
5+
6+
class FinatraServer extends HttpServer {
7+
override protected def configureHttp(router: HttpRouter): Unit = {
8+
router
9+
.filter[ExceptionMappingFilter[Request]]
10+
.add[FinatraController]
11+
.exceptionMapper[ResponseSettingExceptionMapper]
12+
}
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import com.twitter.finagle.http.{Request, Response}
2+
import com.twitter.finatra.http.exceptions.ExceptionMapper
3+
import com.twitter.finatra.http.response.ResponseBuilder
4+
import javax.inject.{Inject, Singleton}
5+
6+
@Singleton
7+
class ResponseSettingExceptionMapper @Inject()(response: ResponseBuilder)
8+
extends ExceptionMapper[Exception] {
9+
10+
override def toResponse(request: Request, exception: Exception): Response = {
11+
response.internalServerError(exception.getMessage)
12+
}
13+
}

0 commit comments

Comments
 (0)