Skip to content

Commit b6295c4

Browse files
committed
Fix WebFlux exception signal log assertions
1 parent 4768165 commit b6295c4

6 files changed

Lines changed: 258 additions & 92 deletions

File tree

instrumentation/spring/spring-webflux/spring-webflux-5.0/testing/src/main/java/io/opentelemetry/instrumentation/spring/webflux/server/AbstractControllerSpringWebFluxServerTest.java

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package io.opentelemetry.instrumentation.spring.webflux.server;
77

8+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs;
9+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents;
810
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
911
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND;
1012
import static io.opentelemetry.instrumentation.testing.util.TestLatestDeps.testLatestDeps;
@@ -35,44 +37,65 @@ protected SpanDataAssert assertHandlerSpan(
3537
span.hasName(handlerSpanName).hasKind(SpanKind.INTERNAL);
3638
if (endpoint == EXCEPTION) {
3739
span.hasStatus(StatusData.error());
38-
span.hasEventsSatisfyingExactly(
39-
event ->
40-
event
41-
.hasName("exception")
42-
.hasAttributesSatisfyingExactly(
43-
equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"),
44-
equalTo(EXCEPTION_MESSAGE, EXCEPTION.getBody()),
45-
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
46-
} else if (endpoint == NOT_FOUND) {
47-
span.hasStatus(StatusData.error());
48-
if (testLatestDeps()) {
49-
span.hasEventsSatisfyingExactly(
50-
event ->
51-
event
52-
.hasName("exception")
53-
.hasAttributesSatisfyingExactly(
54-
equalTo(
55-
EXCEPTION_TYPE,
56-
"org.springframework.web.reactive.resource.NoResourceFoundException"),
57-
equalTo(
58-
EXCEPTION_MESSAGE, "404 NOT_FOUND \"No static resource notFound.\""),
59-
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
60-
} else {
40+
if (emitExceptionAsSpanEvents()) {
6141
span.hasEventsSatisfyingExactly(
6242
event ->
6343
event
6444
.hasName("exception")
6545
.hasAttributesSatisfyingExactly(
66-
satisfies(
67-
EXCEPTION_TYPE,
68-
val ->
69-
val.isIn(
70-
"org.springframework.web.server.ResponseStatusException",
71-
// Changed in spring 7+
72-
"org.springframework.web.reactive.resource.NoResourceFoundException")),
73-
satisfies(EXCEPTION_MESSAGE, val -> val.contains("404")),
46+
equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"),
47+
equalTo(EXCEPTION_MESSAGE, EXCEPTION.getBody()),
7448
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
7549
}
50+
} else if (endpoint == NOT_FOUND) {
51+
span.hasStatus(StatusData.error());
52+
if (emitExceptionAsSpanEvents()) {
53+
if (testLatestDeps()) {
54+
span.hasEventsSatisfyingExactly(
55+
event ->
56+
event
57+
.hasName("exception")
58+
.hasAttributesSatisfyingExactly(
59+
equalTo(
60+
EXCEPTION_TYPE,
61+
"org.springframework.web.reactive.resource.NoResourceFoundException"),
62+
equalTo(
63+
EXCEPTION_MESSAGE,
64+
"404 NOT_FOUND \"No static resource notFound.\""),
65+
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
66+
} else {
67+
span.hasEventsSatisfyingExactly(
68+
event ->
69+
event
70+
.hasName("exception")
71+
.hasAttributesSatisfyingExactly(
72+
satisfies(
73+
EXCEPTION_TYPE,
74+
val ->
75+
val.isIn(
76+
"org.springframework.web.server.ResponseStatusException",
77+
// Changed in spring 7+
78+
"org.springframework.web.reactive.resource.NoResourceFoundException")),
79+
satisfies(EXCEPTION_MESSAGE, val -> val.contains("404")),
80+
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
81+
}
82+
}
83+
if (emitExceptionAsLogs()) {
84+
if (testLatestDeps()) {
85+
assertHandlerExceptionLog(
86+
type ->
87+
type.isEqualTo(
88+
"org.springframework.web.reactive.resource.NoResourceFoundException"),
89+
message -> message.isEqualTo("404 NOT_FOUND \"No static resource notFound.\""));
90+
} else {
91+
assertHandlerExceptionLog(
92+
type ->
93+
type.isIn(
94+
"org.springframework.web.server.ResponseStatusException",
95+
"org.springframework.web.reactive.resource.NoResourceFoundException"),
96+
message -> message.contains("404"));
97+
}
98+
}
7699
}
77100
return span;
78101
}

instrumentation/spring/spring-webflux/spring-webflux-5.0/testing/src/main/java/io/opentelemetry/instrumentation/spring/webflux/server/AbstractHandlerSpringWebFluxServerTest.java

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package io.opentelemetry.instrumentation.spring.webflux.server;
77

8+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs;
9+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents;
810
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
911
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND;
1012
import static io.opentelemetry.instrumentation.testing.util.TestLatestDeps.testLatestDeps;
@@ -34,43 +36,64 @@ protected SpanDataAssert assertHandlerSpan(
3436
span.hasName(handlerSpanName).hasKind(SpanKind.INTERNAL);
3537
if (endpoint == EXCEPTION) {
3638
span.hasStatus(StatusData.error());
37-
span.hasEventsSatisfyingExactly(
38-
event ->
39-
event
40-
.hasName("exception")
41-
.hasAttributesSatisfyingExactly(
42-
equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"),
43-
equalTo(EXCEPTION_MESSAGE, EXCEPTION.getBody()),
44-
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
45-
} else if (endpoint == NOT_FOUND) {
46-
span.hasStatus(StatusData.error());
47-
if (testLatestDeps()) {
39+
if (emitExceptionAsSpanEvents()) {
4840
span.hasEventsSatisfyingExactly(
4941
event ->
5042
event
5143
.hasName("exception")
5244
.hasAttributesSatisfyingExactly(
53-
equalTo(
54-
EXCEPTION_TYPE,
55-
"org.springframework.web.reactive.resource.NoResourceFoundException"),
56-
equalTo(
57-
EXCEPTION_MESSAGE, "404 NOT_FOUND \"No static resource notFound.\""),
45+
equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"),
46+
equalTo(EXCEPTION_MESSAGE, EXCEPTION.getBody()),
5847
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
59-
} else {
60-
span.hasEventsSatisfyingExactly(
61-
event ->
62-
event
63-
.hasName("exception")
64-
.hasAttributesSatisfyingExactly(
65-
satisfies(
66-
EXCEPTION_TYPE,
67-
val ->
68-
val.isIn(
69-
// changed in spring 7+
70-
"org.springframework.web.server.ResponseStatusException",
71-
"org.springframework.web.reactive.resource.NoResourceFoundException")),
72-
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)),
73-
satisfies(EXCEPTION_MESSAGE, val -> val.contains("404"))));
48+
}
49+
} else if (endpoint == NOT_FOUND) {
50+
span.hasStatus(StatusData.error());
51+
if (emitExceptionAsSpanEvents()) {
52+
if (testLatestDeps()) {
53+
span.hasEventsSatisfyingExactly(
54+
event ->
55+
event
56+
.hasName("exception")
57+
.hasAttributesSatisfyingExactly(
58+
equalTo(
59+
EXCEPTION_TYPE,
60+
"org.springframework.web.reactive.resource.NoResourceFoundException"),
61+
equalTo(
62+
EXCEPTION_MESSAGE,
63+
"404 NOT_FOUND \"No static resource notFound.\""),
64+
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))));
65+
} else {
66+
span.hasEventsSatisfyingExactly(
67+
event ->
68+
event
69+
.hasName("exception")
70+
.hasAttributesSatisfyingExactly(
71+
satisfies(
72+
EXCEPTION_TYPE,
73+
val ->
74+
val.isIn(
75+
// changed in spring 7+
76+
"org.springframework.web.server.ResponseStatusException",
77+
"org.springframework.web.reactive.resource.NoResourceFoundException")),
78+
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)),
79+
satisfies(EXCEPTION_MESSAGE, val -> val.contains("404"))));
80+
}
81+
}
82+
if (emitExceptionAsLogs()) {
83+
if (testLatestDeps()) {
84+
assertHandlerExceptionLog(
85+
type ->
86+
type.isEqualTo(
87+
"org.springframework.web.reactive.resource.NoResourceFoundException"),
88+
message -> message.isEqualTo("404 NOT_FOUND \"No static resource notFound.\""));
89+
} else {
90+
assertHandlerExceptionLog(
91+
type ->
92+
type.isIn(
93+
"org.springframework.web.server.ResponseStatusException",
94+
"org.springframework.web.reactive.resource.NoResourceFoundException"),
95+
message -> message.contains("404"));
96+
}
7497
}
7598
}
7699
return span;

instrumentation/spring/spring-webflux/spring-webflux-5.0/testing/src/main/java/io/opentelemetry/instrumentation/spring/webflux/server/AbstractSpringWebFluxServerTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,35 @@
77

88
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND;
99
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM;
10+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
11+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
12+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE;
13+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE;
14+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE;
15+
import static java.util.stream.Collectors.toList;
16+
import static org.assertj.core.api.Assertions.assertThat;
1017

18+
import io.opentelemetry.api.logs.Severity;
1119
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
1220
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest;
1321
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
1422
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
1523
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint;
24+
import io.opentelemetry.sdk.logs.data.LogRecordData;
25+
import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.StringAssertConsumer;
1626
import java.util.HashMap;
27+
import java.util.List;
1728
import java.util.Map;
29+
import org.awaitility.Awaitility;
1830
import org.junit.jupiter.api.extension.RegisterExtension;
1931
import org.springframework.boot.SpringApplication;
2032
import org.springframework.context.ConfigurableApplicationContext;
2133

2234
public abstract class AbstractSpringWebFluxServerTest
2335
extends AbstractHttpServerTest<ConfigurableApplicationContext> {
2436

37+
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.0";
38+
2539
public static final ServerEndpoint NESTED_PATH =
2640
new ServerEndpoint("NESTED_PATH", "nestedPath/hello/world", 200, "nested path");
2741

@@ -64,4 +78,30 @@ protected void configure(HttpServerTestOptions options) {
6478
options.setTestPathParam(true);
6579
options.setHasHandlerSpan(unused -> true);
6680
}
81+
82+
protected static void assertHandlerExceptionLog(
83+
StringAssertConsumer exceptionTypeAssertion,
84+
StringAssertConsumer exceptionMessageAssertion) {
85+
Awaitility.await()
86+
.untilAsserted(
87+
() -> {
88+
List<LogRecordData> logs =
89+
testing.logRecords().stream()
90+
.filter(log -> "exception".equals(log.getEventName()))
91+
.filter(
92+
log ->
93+
INSTRUMENTATION_NAME.equals(
94+
log.getInstrumentationScopeInfo().getName()))
95+
.collect(toList());
96+
97+
assertThat(logs).hasSize(1);
98+
assertThat(logs.get(0))
99+
.hasSeverity(Severity.WARN)
100+
.hasEventName("exception")
101+
.hasAttributesSatisfyingExactly(
102+
satisfies(EXCEPTION_TYPE, exceptionTypeAssertion),
103+
satisfies(EXCEPTION_MESSAGE, exceptionMessageAssertion),
104+
satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)));
105+
});
106+
}
67107
}

0 commit comments

Comments
 (0)