convert undertow groovy test to java (#12207)

This commit is contained in:
shalk(xiao kun) 2024-10-09 23:05:11 +08:00 committed by GitHub
parent 2986b570b4
commit 8f18c30493
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 436 additions and 357 deletions

View File

@ -24,3 +24,11 @@ dependencies {
tasks.withType<Test>().configureEach {
jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true")
}
// since 2.3.x, undertow is compiled by JDK 11
val latestDepTest = findProperty("testLatestDeps") as Boolean
if (latestDepTest) {
otelJava {
minJavaVersionSupported.set(JavaVersion.VERSION_11)
}
}

View File

@ -1,18 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.undertow.Undertow
import io.undertow.UndertowOptions
class UndertowHttp2ServerTest extends UndertowServerTest {
void configureUndertow(Undertow.Builder builder) {
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)
}
boolean useHttp2() {
true
}
}

View File

@ -1,111 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
import io.opentelemetry.semconv.HttpAttributes
import io.undertow.Handlers
import io.undertow.Undertow
import io.undertow.util.Headers
import io.undertow.util.HttpString
import io.undertow.util.StatusCodes
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
class UndertowServerDispatchTest extends HttpServerTest<Undertow> implements AgentTestTrait {
@Override
boolean verifyServerSpanEndTime() {
return false
}
@Override
boolean testException() {
// throwing exception from dispatched task just makes the request time out
return false
}
@Override
boolean hasResponseCustomizer(ServerEndpoint endpoint) {
true
}
@Override
Undertow startServer(int port) {
Undertow server = Undertow.builder()
.addHttpListener(port, "localhost")
.setHandler(Handlers.path()
.addExactPath(SUCCESS.rawPath()) { exchange ->
exchange.dispatch {
controller(SUCCESS) {
exchange.getResponseSender().send(SUCCESS.body)
}
}
}
.addExactPath(QUERY_PARAM.rawPath()) { exchange ->
exchange.dispatch {
controller(QUERY_PARAM) {
exchange.getResponseSender().send(exchange.getQueryString())
}
}
}
.addExactPath(REDIRECT.rawPath()) { exchange ->
exchange.dispatch {
controller(REDIRECT) {
exchange.setStatusCode(StatusCodes.FOUND)
exchange.getResponseHeaders().put(Headers.LOCATION, REDIRECT.body)
exchange.endExchange()
}
}
}
.addExactPath(CAPTURE_HEADERS.rawPath()) { exchange ->
exchange.dispatch {
controller(CAPTURE_HEADERS) {
exchange.setStatusCode(StatusCodes.OK)
exchange.getResponseHeaders().put(new HttpString("X-Test-Response"), exchange.getRequestHeaders().getFirst("X-Test-Request"))
exchange.getResponseSender().send(CAPTURE_HEADERS.body)
}
}
}
.addExactPath(ERROR.rawPath()) { exchange ->
exchange.dispatch {
controller(ERROR) {
exchange.setStatusCode(ERROR.status)
exchange.getResponseSender().send(ERROR.body)
}
}
}
.addExactPath(INDEXED_CHILD.rawPath()) { exchange ->
exchange.dispatch {
controller(INDEXED_CHILD) {
INDEXED_CHILD.collectSpanAttributes { name -> exchange.getQueryParameters().get(name).peekFirst() }
exchange.getResponseSender().send(INDEXED_CHILD.body)
}
}
}
).build()
server.start()
return server
}
@Override
void stopServer(Undertow undertow) {
undertow.stop()
}
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(HttpAttributes.HTTP_ROUTE)
attributes
}
}

View File

@ -1,228 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
import io.opentelemetry.semconv.ServerAttributes
import io.opentelemetry.semconv.ClientAttributes
import io.opentelemetry.semconv.UserAgentAttributes
import io.opentelemetry.semconv.HttpAttributes
import io.opentelemetry.semconv.NetworkAttributes
import io.opentelemetry.semconv.UrlAttributes
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse
import io.undertow.Handlers
import io.undertow.Undertow
import io.undertow.util.Headers
import io.undertow.util.HttpString
import io.undertow.util.StatusCodes
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
//TODO make test which mixes handlers and servlets
class UndertowServerTest extends HttpServerTest<Undertow> implements AgentTestTrait {
@Override
Undertow startServer(int port) {
Undertow.Builder builder = Undertow.builder()
.addHttpListener(port, "localhost")
.setHandler(Handlers.path()
.addExactPath(SUCCESS.rawPath()) { exchange ->
controller(SUCCESS) {
exchange.getResponseSender().send(SUCCESS.body)
}
}
.addExactPath(QUERY_PARAM.rawPath()) { exchange ->
controller(QUERY_PARAM) {
exchange.getResponseSender().send(exchange.getQueryString())
}
}
.addExactPath(REDIRECT.rawPath()) { exchange ->
controller(REDIRECT) {
exchange.setStatusCode(StatusCodes.FOUND)
exchange.getResponseHeaders().put(Headers.LOCATION, REDIRECT.body)
exchange.endExchange()
}
}
.addExactPath(CAPTURE_HEADERS.rawPath()) { exchange ->
controller(CAPTURE_HEADERS) {
exchange.setStatusCode(StatusCodes.OK)
exchange.getResponseHeaders().put(new HttpString("X-Test-Response"), exchange.getRequestHeaders().getFirst("X-Test-Request"))
exchange.getResponseSender().send(CAPTURE_HEADERS.body)
}
}
.addExactPath(ERROR.rawPath()) { exchange ->
controller(ERROR) {
exchange.setStatusCode(ERROR.status)
exchange.getResponseSender().send(ERROR.body)
}
}
.addExactPath(EXCEPTION.rawPath()) { exchange ->
controller(EXCEPTION) {
throw new Exception(EXCEPTION.body)
}
}
.addExactPath(INDEXED_CHILD.rawPath()) { exchange ->
controller(INDEXED_CHILD) {
INDEXED_CHILD.collectSpanAttributes { name -> exchange.getQueryParameters().get(name).peekFirst() }
exchange.getResponseSender().send(INDEXED_CHILD.body)
}
}
.addExactPath("sendResponse") { exchange ->
Span.current().addEvent("before-event")
runWithSpan("sendResponse") {
exchange.setStatusCode(StatusCodes.OK)
exchange.getResponseSender().send("sendResponse")
}
// event is added only when server span has not been ended
// we need to make sure that sending response does not end server span
Span.current().addEvent("after-event")
}
.addExactPath("sendResponseWithException") { exchange ->
Span.current().addEvent("before-event")
runWithSpan("sendResponseWithException") {
exchange.setStatusCode(StatusCodes.OK)
exchange.getResponseSender().send("sendResponseWithException")
}
// event is added only when server span has not been ended
// we need to make sure that sending response does not end server span
Span.current().addEvent("after-event")
throw new Exception("exception after sending response")
}
)
configureUndertow(builder)
Undertow server = builder.build()
server.start()
return server
}
@Override
void stopServer(Undertow undertow) {
undertow.stop()
}
void configureUndertow(Undertow.Builder builder) {
}
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(HttpAttributes.HTTP_ROUTE)
attributes
}
@Override
boolean hasResponseCustomizer(ServerEndpoint endpoint) {
true
}
def "test send response"() {
setup:
def uri = address.resolve("sendResponse")
AggregatedHttpResponse response = client.get(uri.toString()).aggregate().join()
expect:
response.status().code() == 200
response.contentUtf8().trim() == "sendResponse"
and:
assertTraces(1) {
trace(0, 2) {
it.span(0) {
hasNoParent()
name "GET"
kind SpanKind.SERVER
event(0) {
eventName "before-event"
}
event(1) {
eventName "after-event"
}
def protocolVersion = useHttp2() ? "2" : "1.1"
attributes {
"$ClientAttributes.CLIENT_ADDRESS" TEST_CLIENT_IP
"$UrlAttributes.URL_SCHEME" uri.getScheme()
"$UrlAttributes.URL_PATH" uri.getPath()
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
"$UserAgentAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" protocolVersion
"$ServerAttributes.SERVER_ADDRESS" uri.host
"$ServerAttributes.SERVER_PORT" uri.port
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
"$NetworkAttributes.NETWORK_PEER_PORT" Long
}
}
span(1) {
name "sendResponse"
kind SpanKind.INTERNAL
childOf span(0)
}
}
}
}
def "test send response with exception"() {
setup:
def uri = address.resolve("sendResponseWithException")
AggregatedHttpResponse response = client.get(uri.toString()).aggregate().join()
expect:
response.status().code() == 200
response.contentUtf8().trim() == "sendResponseWithException"
and:
assertTraces(1) {
trace(0, 2) {
it.span(0) {
hasNoParent()
name "GET"
kind SpanKind.SERVER
status StatusCode.ERROR
event(0) {
eventName "before-event"
}
event(1) {
eventName "after-event"
}
errorEvent(Exception, "exception after sending response", 2)
def protocolVersion = useHttp2() ? "2" : "1.1"
attributes {
"$ClientAttributes.CLIENT_ADDRESS" TEST_CLIENT_IP
"$UrlAttributes.URL_SCHEME" uri.getScheme()
"$UrlAttributes.URL_PATH" uri.getPath()
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
"$UserAgentAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" protocolVersion
"$ServerAttributes.SERVER_ADDRESS" uri.host
"$ServerAttributes.SERVER_PORT" uri.port
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
"$NetworkAttributes.NETWORK_PEER_PORT" Long
}
}
span(1) {
name "sendResponseWithException"
kind SpanKind.INTERNAL
childOf span(0)
}
}
}
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.undertow;
import io.undertow.Undertow;
import io.undertow.UndertowOptions;
class UndertowHttp2ServerTest extends UndertowServerTest {
@Override
public void configureUndertow(Undertow.Builder builder) {
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);
}
@Override
public boolean useHttp2() {
return true;
}
}

View File

@ -0,0 +1,135 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.undertow;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS;
import com.google.common.collect.ImmutableSet;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest;
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
import io.opentelemetry.semconv.NetworkAttributes;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import io.undertow.util.StatusCodes;
import org.junit.jupiter.api.extension.RegisterExtension;
class UndertowServerDispatchTest extends AbstractHttpServerTest<Undertow> {
@RegisterExtension
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
@Override
public Undertow setupServer() {
Undertow server =
Undertow.builder()
.addHttpListener(port, "localhost")
.setHandler(
Handlers.path()
.addExactPath(
SUCCESS.rawPath(),
exchange ->
exchange.dispatch(
k ->
controller(
SUCCESS,
() -> k.getResponseSender().send(SUCCESS.getBody()))))
.addExactPath(
QUERY_PARAM.rawPath(),
exchange ->
exchange.dispatch(
k ->
controller(
QUERY_PARAM,
() -> k.getResponseSender().send(k.getQueryString()))))
.addExactPath(
REDIRECT.rawPath(),
exchange ->
exchange.dispatch(
k ->
controller(
REDIRECT,
() -> {
k.setStatusCode(StatusCodes.FOUND);
k.getResponseHeaders()
.put(Headers.LOCATION, REDIRECT.getBody());
k.endExchange();
})))
.addExactPath(
CAPTURE_HEADERS.rawPath(),
exchange ->
exchange.dispatch(
k ->
controller(
CAPTURE_HEADERS,
() -> {
k.setStatusCode(StatusCodes.OK);
k.getResponseHeaders()
.put(
new HttpString("X-Test-Response"),
exchange
.getRequestHeaders()
.getFirst("X-Test-Request"));
k.getResponseSender().send(CAPTURE_HEADERS.getBody());
})))
.addExactPath(
ERROR.rawPath(),
exchange ->
exchange.dispatch(
k ->
controller(
ERROR,
() -> {
exchange.setStatusCode(ERROR.getStatus());
exchange.getResponseSender().send(ERROR.getBody());
})))
.addExactPath(
INDEXED_CHILD.rawPath(),
exchange ->
exchange.dispatch(
k ->
controller(
INDEXED_CHILD,
() -> {
INDEXED_CHILD.collectSpanAttributes(
name ->
exchange
.getQueryParameters()
.get(name)
.peekFirst());
exchange
.getResponseSender()
.send(INDEXED_CHILD.getBody());
}))))
.build();
server.start();
return server;
}
@Override
public void stopServer(Undertow undertow) {
undertow.stop();
}
@Override
protected void configure(HttpServerTestOptions options) {
super.configure(options);
options.setVerifyServerSpanEndTime(false);
// throwing exception from dispatched task just makes the request time out
options.setTestException(false);
options.setHasResponseCustomizer(endpoint -> true);
options.setHttpAttributes(endpoint -> ImmutableSet.of(NetworkAttributes.NETWORK_PEER_PORT));
}
}

View File

@ -0,0 +1,271 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.undertow;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.ImmutableSet;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest;
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
import io.opentelemetry.semconv.ClientAttributes;
import io.opentelemetry.semconv.ExceptionAttributes;
import io.opentelemetry.semconv.HttpAttributes;
import io.opentelemetry.semconv.NetworkAttributes;
import io.opentelemetry.semconv.ServerAttributes;
import io.opentelemetry.semconv.UrlAttributes;
import io.opentelemetry.semconv.UserAgentAttributes;
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import io.undertow.util.StatusCodes;
import java.net.URI;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
class UndertowServerTest extends AbstractHttpServerTest<Undertow> {
@RegisterExtension
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
@Override
public Undertow setupServer() {
Undertow.Builder builder =
Undertow.builder()
.addHttpListener(port, "localhost")
.setHandler(
Handlers.path()
.addExactPath(
SUCCESS.rawPath(),
exchange ->
controller(
SUCCESS,
() -> exchange.getResponseSender().send(SUCCESS.getBody())))
.addExactPath(
QUERY_PARAM.rawPath(),
exchange ->
controller(
QUERY_PARAM,
() -> exchange.getResponseSender().send(exchange.getQueryString())))
.addExactPath(
REDIRECT.rawPath(),
exchange ->
controller(
REDIRECT,
() -> {
exchange.setStatusCode(StatusCodes.FOUND);
exchange
.getResponseHeaders()
.put(Headers.LOCATION, REDIRECT.getBody());
exchange.endExchange();
}))
.addExactPath(
CAPTURE_HEADERS.rawPath(),
exchange ->
controller(
CAPTURE_HEADERS,
() -> {
exchange.setStatusCode(StatusCodes.OK);
exchange
.getResponseHeaders()
.put(
new HttpString("X-Test-Response"),
exchange.getRequestHeaders().getFirst("X-Test-Request"));
exchange.getResponseSender().send(CAPTURE_HEADERS.getBody());
}))
.addExactPath(
ERROR.rawPath(),
exchange ->
controller(
ERROR,
() -> {
exchange.setStatusCode(ERROR.getStatus());
exchange.getResponseSender().send(ERROR.getBody());
}))
.addExactPath(
EXCEPTION.rawPath(),
exchange ->
testing.runWithSpan(
"controller",
(ThrowingRunnable<Exception>)
() -> {
throw new Exception(EXCEPTION.getBody());
}))
.addExactPath(
INDEXED_CHILD.rawPath(),
exchange ->
controller(
INDEXED_CHILD,
() -> {
INDEXED_CHILD.collectSpanAttributes(
name -> exchange.getQueryParameters().get(name).peekFirst());
exchange.getResponseSender().send(INDEXED_CHILD.getBody());
}))
.addExactPath(
"sendResponse",
exchange -> {
Span.current().addEvent("before-event");
testing.runWithSpan(
"sendResponse",
() -> {
exchange.setStatusCode(StatusCodes.OK);
exchange.getResponseSender().send("sendResponse");
});
// event is added only when server span has not been ended
// we need to make sure that sending response does not end server span
Span.current().addEvent("after-event");
})
.addExactPath(
"sendResponseWithException",
exchange -> {
Span.current().addEvent("before-event");
testing.runWithSpan(
"sendResponseWithException",
() -> {
exchange.setStatusCode(StatusCodes.OK);
exchange.getResponseSender().send("sendResponseWithException");
});
// event is added only when server span has not been ended
// we need to make sure that sending response does not end server span
Span.current().addEvent("after-event");
throw new Exception("exception after sending response");
}));
configureUndertow(builder);
Undertow server = builder.build();
server.start();
return server;
}
@Override
public void stopServer(Undertow undertow) {
undertow.stop();
}
@Override
protected void configure(HttpServerTestOptions options) {
super.configure(options);
options.setHttpAttributes(endpoint -> ImmutableSet.of(NetworkAttributes.NETWORK_PEER_PORT));
options.setHasResponseCustomizer(serverEndpoint -> true);
options.setUseHttp2(useHttp2());
}
protected void configureUndertow(Undertow.Builder builder) {}
protected boolean useHttp2() {
return false;
}
@DisplayName("test send response")
@Test
void testSendResponse() {
URI uri = address.resolve("sendResponse");
AggregatedHttpResponse response = client.get(uri.toString()).aggregate().join();
assertThat(response.status().code()).isEqualTo(200);
assertThat(response.contentUtf8().trim()).isEqualTo("sendResponse");
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("GET")
.hasNoParent()
.hasKind(SpanKind.SERVER)
.hasEventsSatisfyingExactly(
event -> event.hasName("before-event"),
event -> event.hasName("after-event"))
.hasAttributesSatisfyingExactly(
equalTo(ClientAttributes.CLIENT_ADDRESS, TEST_CLIENT_IP),
equalTo(UrlAttributes.URL_SCHEME, uri.getScheme()),
equalTo(UrlAttributes.URL_PATH, uri.getPath()),
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200),
equalTo(UserAgentAttributes.USER_AGENT_ORIGINAL, TEST_USER_AGENT),
equalTo(
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
useHttp2() ? "2" : "1.1"),
equalTo(ServerAttributes.SERVER_ADDRESS, uri.getHost()),
equalTo(ServerAttributes.SERVER_PORT, uri.getPort()),
equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"),
satisfies(
NetworkAttributes.NETWORK_PEER_PORT,
k -> k.isInstanceOf(Long.class))),
span ->
span.hasName("sendResponse")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))));
}
@Test
@DisplayName("test send response with exception")
void testSendResponseWithException() {
URI uri = address.resolve("sendResponseWithException");
AggregatedHttpResponse response = client.get(uri.toString()).aggregate().join();
assertThat(response.status().code()).isEqualTo(200);
assertThat(response.contentUtf8().trim()).isEqualTo("sendResponseWithException");
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("GET")
.hasNoParent()
.hasKind(SpanKind.SERVER)
.hasEventsSatisfyingExactly(
event -> event.hasName("before-event"),
event -> event.hasName("after-event"),
event ->
event
.hasName("exception")
.hasAttributesSatisfyingExactly(
equalTo(
ExceptionAttributes.EXCEPTION_TYPE,
Exception.class.getName()),
equalTo(
ExceptionAttributes.EXCEPTION_MESSAGE,
"exception after sending response"),
satisfies(
ExceptionAttributes.EXCEPTION_STACKTRACE,
val -> val.isInstanceOf(String.class))))
.hasAttributesSatisfyingExactly(
equalTo(ClientAttributes.CLIENT_ADDRESS, TEST_CLIENT_IP),
equalTo(UrlAttributes.URL_SCHEME, uri.getScheme()),
equalTo(UrlAttributes.URL_PATH, uri.getPath()),
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200),
equalTo(UserAgentAttributes.USER_AGENT_ORIGINAL, TEST_USER_AGENT),
equalTo(
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
useHttp2() ? "2" : "1.1"),
equalTo(ServerAttributes.SERVER_ADDRESS, uri.getHost()),
equalTo(ServerAttributes.SERVER_PORT, uri.getPort()),
equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"),
satisfies(
NetworkAttributes.NETWORK_PEER_PORT,
k -> k.isInstanceOf(Long.class))),
span ->
span.hasName("sendResponseWithException")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))));
}
}