opentelemetry-java-instrume.../instrumentation/tapestry-5.4/javaagent/src/test/groovy/TapestryTest.groovy

178 lines
5.0 KiB
Groovy

/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import static io.opentelemetry.api.trace.StatusCode.ERROR
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait
import io.opentelemetry.testing.internal.armeria.client.ClientRequestContext
import io.opentelemetry.testing.internal.armeria.client.DecoratingHttpClientFunction
import io.opentelemetry.testing.internal.armeria.client.HttpClient
import io.opentelemetry.testing.internal.armeria.client.WebClient
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse
import io.opentelemetry.testing.internal.armeria.common.HttpHeaderNames
import io.opentelemetry.testing.internal.armeria.common.HttpRequest
import io.opentelemetry.testing.internal.armeria.common.HttpResponse
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.util.resource.Resource
import org.eclipse.jetty.webapp.WebAppContext
import org.jsoup.Jsoup
class TapestryTest extends AgentInstrumentationSpecification implements HttpServerTestTrait<Server> {
@Override
Server startServer(int port) {
WebAppContext webAppContext = new WebAppContext()
webAppContext.setContextPath(getContextPath())
// set up test application
webAppContext.setBaseResource(Resource.newResource("src/test/webapp"))
def jettyServer = new Server(port)
jettyServer.connectors.each {
it.setHost('localhost')
}
jettyServer.setHandler(webAppContext)
jettyServer.start()
return jettyServer
}
@Override
void stopServer(Server server) {
server.stop()
server.destroy()
}
@Override
String getContextPath() {
return "/jetty-context"
}
WebClient client
def setup() {
client = WebClient.builder(address)
.decorator(new DecoratingHttpClientFunction() {
// https://github.com/line/armeria/issues/2489
@Override
HttpResponse execute(HttpClient delegate, ClientRequestContext ctx, HttpRequest req) throws Exception {
return HttpResponse.from(delegate.execute(ctx, req).aggregate().thenApply {resp ->
if (resp.status().isRedirection()) {
return delegate.execute(ctx, HttpRequest.of(req.method(), URI.create(resp.headers().get(HttpHeaderNames.LOCATION)).path))
}
return resp.toHttpResponse()
})
}
})
.build()
}
static serverSpan(TraceAssert trace, int index, String spanName) {
trace.span(index) {
hasNoParent()
name spanName
kind SpanKind.SERVER
}
}
def "test index page"() {
setup:
AggregatedHttpResponse response = client.get("/").aggregate().join()
def doc = Jsoup.parse(response.contentUtf8())
expect:
response.status().code() == 200
doc.selectFirst("title").text() == "Index page"
assertTraces(1) {
trace(0, 2) {
serverSpan(it, 0, getContextPath() + "/Index")
span(1) {
name "activate/Index"
kind SpanKind.INTERNAL
childOf span(0)
}
}
}
}
def "test start action"() {
setup:
// index.start triggers an action named "start" on index page
AggregatedHttpResponse response = client.get("/index.start").aggregate().join()
def doc = Jsoup.parse(response.contentUtf8())
expect:
response.status().code() == 200
doc.selectFirst("title").text() == "Other page"
assertTraces(2) {
trace(0, 4) {
serverSpan(it, 0, getContextPath() + "/Index")
span(1) {
name "activate/Index"
kind SpanKind.INTERNAL
childOf span(0)
}
span(2) {
name "action/Index:start"
kind SpanKind.INTERNAL
childOf span(0)
}
span(3) {
name "Response.sendRedirect"
kind SpanKind.INTERNAL
childOf span(2)
}
}
trace(1, 2) {
serverSpan(it, 0, getContextPath() + "/Other")
span(1) {
name "activate/Other"
kind SpanKind.INTERNAL
childOf span(0)
}
}
}
}
def "test exception action"() {
setup:
// index.exception triggers an action named "exception" on index page
AggregatedHttpResponse response = client.get("/index.exception").aggregate().join()
expect:
response.status().code() == 500
def ex = new IllegalStateException("expected")
assertTraces(1) {
trace(0, 3) {
span(0) {
hasNoParent()
kind SpanKind.SERVER
name getContextPath() + "/Index"
status ERROR
}
span(1) {
name "activate/Index"
kind SpanKind.INTERNAL
childOf span(0)
}
span(2) {
name "action/Index:exception"
kind SpanKind.INTERNAL
childOf span(0)
status ERROR
errorEvent(ex.class, ex.message)
}
}
}
}
}