Skip to content

Commit 74b1117

Browse files
committed
Add test for Spring @EnableAsync
1 parent 5972f4d commit 74b1117

File tree

7 files changed

+95
-0
lines changed

7 files changed

+95
-0
lines changed

instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webmvc/v3_1/boot/SpringBootBasedTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ protected void configure(HttpServerTestOptions options) {
5959
Boolean.getBoolean("testLatestDeps") ? 500 : 200);
6060
options.setExpectedException(new RuntimeException(EXCEPTION.getBody()));
6161
}
62+
63+
@Override
64+
protected boolean shouldTestDeferredResult() {
65+
return Boolean.getBoolean("testLatestDeps");
66+
}
6267
}

instrumentation/spring/spring-webmvc/spring-webmvc-common/testing/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/boot/AbstractSpringBootBasedTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil.codeFunctionSuffixAssertions;
1010
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.AUTH_ERROR;
1111
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS;
12+
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.DEFERRED_RESULT;
1213
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
1314
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD;
1415
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.LOGIN;
@@ -22,6 +23,7 @@
2223
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE;
2324
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE;
2425
import static org.assertj.core.api.Assertions.assertThat;
26+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
2527

2628
import io.opentelemetry.api.common.AttributeKey;
2729
import io.opentelemetry.api.trace.SpanKind;
@@ -58,6 +60,10 @@ public abstract class AbstractSpringBootBasedTest
5860

5961
protected abstract Class<?> securityConfigClass();
6062

63+
protected boolean shouldTestDeferredResult() {
64+
return true;
65+
}
66+
6167
@Override
6268
protected void stopServer(ConfigurableApplicationContext ctx) {
6369
ctx.close();
@@ -144,6 +150,39 @@ void testCharacterEncodingOfTestPassword(String testPassword) {
144150
.hasKind(SpanKind.INTERNAL)));
145151
}
146152

153+
@Test
154+
void deferredResult() {
155+
assumeTrue(shouldTestDeferredResult());
156+
157+
AggregatedHttpResponse response =
158+
client.execute(request(DEFERRED_RESULT, "GET")).aggregate().join();
159+
160+
assertThat(response.status().code()).isEqualTo(DEFERRED_RESULT.getStatus());
161+
assertThat(response.contentUtf8()).isEqualTo(DEFERRED_RESULT.getBody());
162+
163+
testing()
164+
.waitAndAssertTraces(
165+
trace ->
166+
trace.hasSpansSatisfyingExactly(
167+
span -> {
168+
assertServerSpan(span, "GET", DEFERRED_RESULT, DEFERRED_RESULT.getStatus());
169+
span.hasNoParent();
170+
},
171+
span ->
172+
assertHandlerSpan(span, "GET", DEFERRED_RESULT).hasParent(trace.getSpan(0)),
173+
span ->
174+
span.hasName("deferred-result-child")
175+
.hasKind(SpanKind.INTERNAL)
176+
.hasParent(trace.getSpan(1))
177+
.hasTotalAttributeCount(0),
178+
// Handler method runs once for the initial request and again for the async
179+
// redispatch when DeferredResult completes, so we expect two spans with the
180+
// same name. The second handler span is parented to the async child span.
181+
span ->
182+
assertHandlerSpan(span, "GET", DEFERRED_RESULT)
183+
.hasParent(trace.getSpan(2))));
184+
}
185+
147186
@Override
148187
protected List<Consumer<SpanDataAssert>> errorPageSpanAssertions(
149188
String method, ServerEndpoint endpoint) {
@@ -228,6 +267,8 @@ private static String getHandlerSpanName(ServerEndpoint endpoint) {
228267
return "TestController.captureHeaders";
229268
} else if (INDEXED_CHILD.equals(endpoint)) {
230269
return "TestController.indexedChild";
270+
} else if (DEFERRED_RESULT.equals(endpoint)) {
271+
return "TestController.deferredResult";
231272
}
232273
return "TestController." + endpoint.name().toLowerCase(Locale.ROOT);
233274
}

instrumentation/spring/spring-webmvc/spring-webmvc-common/testing/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/boot/AppConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package io.opentelemetry.instrumentation.spring.webmvc.boot;
77

88
import org.springframework.boot.autoconfigure.SpringBootApplication;
9+
import org.springframework.scheduling.annotation.EnableAsync;
910

1011
@SpringBootApplication
12+
@EnableAsync
1113
public class AppConfig {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.spring.webmvc.boot;
7+
8+
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.DEFERRED_RESULT;
9+
10+
import io.opentelemetry.api.GlobalOpenTelemetry;
11+
import io.opentelemetry.api.trace.Span;
12+
import io.opentelemetry.api.trace.Tracer;
13+
import io.opentelemetry.context.Scope;
14+
import org.springframework.scheduling.annotation.Async;
15+
import org.springframework.stereotype.Service;
16+
import org.springframework.web.context.request.async.DeferredResult;
17+
18+
@Service
19+
public class TestBean {
20+
21+
private static final Tracer tracer = GlobalOpenTelemetry.getTracer("test");
22+
23+
@Async
24+
public void asyncDependencyCall(DeferredResult<String> deferredResult) {
25+
Span span = tracer.spanBuilder("deferred-result-child").startSpan();
26+
try (Scope ignored = span.makeCurrent()) {
27+
deferredResult.setResult(DEFERRED_RESULT.getBody());
28+
} finally {
29+
span.end();
30+
}
31+
}
32+
}

instrumentation/spring/spring-webmvc/spring-webmvc-common/testing/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/boot/TestController.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS;
1717

1818
import java.util.Objects;
19+
import org.springframework.beans.factory.annotation.Autowired;
1920
import org.springframework.http.HttpStatus;
2021
import org.springframework.http.ResponseEntity;
2122
import org.springframework.stereotype.Controller;
@@ -25,11 +26,14 @@
2526
import org.springframework.web.bind.annotation.RequestMapping;
2627
import org.springframework.web.bind.annotation.RequestParam;
2728
import org.springframework.web.bind.annotation.ResponseBody;
29+
import org.springframework.web.context.request.async.DeferredResult;
2830
import org.springframework.web.servlet.view.RedirectView;
2931

3032
@Controller
3133
public class TestController {
3234

35+
@Autowired private TestBean testBean;
36+
3337
@RequestMapping("/basicsecured/endpoint")
3438
@ResponseBody
3539
String secureEndpoint() {
@@ -100,6 +104,14 @@ String indexedChild(@RequestParam("id") String id) {
100104
});
101105
}
102106

107+
@RequestMapping("/deferred-result")
108+
@ResponseBody
109+
DeferredResult<String> deferredResult() {
110+
DeferredResult<String> deferredResult = new DeferredResult<>();
111+
testBean.asyncDependencyCall(deferredResult);
112+
return deferredResult;
113+
}
114+
103115
@ExceptionHandler
104116
ResponseEntity<String> handleException(Throwable throwable) {
105117
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR.value())

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/AdditionalLibraryIgnoredTypesConfigurer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public void configure(IgnoredTypesBuilder builder) {
5353

5454
builder
5555
.ignoreClass("org.springframework.aop.")
56+
.allowClass("org.springframework.aop.interceptor.AsyncExecutionInterceptor$")
5657
.ignoreClass("org.springframework.cache.")
5758
.ignoreClass("org.springframework.dao.")
5859
.ignoreClass("org.springframework.ejb.")

testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/ServerEndpoint.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public class ServerEndpoint {
4848
new ServerEndpoint("AUTH_ERROR", "basicsecured/endpoint", 401, null);
4949
public static final ServerEndpoint INDEXED_CHILD =
5050
new ServerEndpoint("INDEXED_CHILD", "child", 200, "success");
51+
public static final ServerEndpoint DEFERRED_RESULT =
52+
new ServerEndpoint("DEFERRED_RESULT", "deferred-result", 200, "deferred result");
5153

5254
public static final String ID_ATTRIBUTE_NAME = "test.request.id";
5355
public static final String ID_PARAMETER_NAME = "id";

0 commit comments

Comments
 (0)