Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add framework info for Spring Webflux #3936

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Use subheadings with the "=====" level for adding notes for unreleased changes:
* Prevent NPE in OpenTelemetry metrics bridge in case of asynchronous agent start - {pull}3880[#3880]
* Fix random Weblogic ClassNotFoundException related to thread context classloader - {pull}3870[#3870]
* Skips using NOFOLLOW_LINKS file open option when running on OS/400 as it's unsupported there - {pull}3905[#3905]
* Add framework name and version for Spring Webflux transactions - {pull}3936[#3936]

[[release-notes-1.x]]
=== Java Agent version 1.x
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package co.elastic.apm.agent.springwebflux;

import co.elastic.apm.agent.testutils.Java17OnlyTest;
import org.junit.jupiter.api.BeforeEach;

public class Spring6ServerAnnotatedInstrumentationTest extends Java17OnlyTest {

Expand All @@ -27,5 +28,10 @@ public Spring6ServerAnnotatedInstrumentationTest() {
}

public static class Impl extends ServerAnnotatedInstrumentationTest {

@BeforeEach
void setUp() {
expectedFrameworkVersion = "6.2.0";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package co.elastic.apm.agent.springwebflux;

import co.elastic.apm.agent.testutils.Java17OnlyTest;
import org.junit.jupiter.api.BeforeEach;

public class Spring6ServerFunctionalInstrumentationTest extends Java17OnlyTest {

Expand All @@ -27,5 +28,9 @@ public Spring6ServerFunctionalInstrumentationTest() {
}

public static class Impl extends ServerFunctionalInstrumentationTest {
@BeforeEach
void setUp() {
expectedFrameworkVersion = "6.2.0";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@
*/
package co.elastic.apm.agent.springwebflux;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;

@EnabledForJreRange(min = JRE.JAVA_17)
public class Spring6ServletContainerTest extends ServletContainerTest {

@BeforeEach
void setUp() {
expectedFrameworkVersion = "6.2.0";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void onError(Throwable t) {
Transaction<?> transaction = getTransaction();
doEnter("onError", transaction);
try {

WebfluxHelper.setFrameworkInfo(transaction);
// We have to capture the transaction name just before it's actually ended to prevent
// concurrency issues as the transaction is accessed from multiple threads when created by a servlet.
WebfluxHelper.setTransactionName(transaction, exchange);
Expand All @@ -167,7 +167,7 @@ public void onComplete() {
Transaction<?> transaction = getTransaction();
doEnter("onComplete", transaction);
try {

WebfluxHelper.setFrameworkInfo(transaction);
// We have to capture the transaction name just before it's actually ended to prevent
// concurrency issues as the transaction is accessed from multiple threads when created by a servlet.
WebfluxHelper.setTransactionName(transaction, exchange);
Expand Down Expand Up @@ -209,7 +209,7 @@ private void cancelTransaction() {
if (transaction == null) {
return;
}

WebfluxHelper.setFrameworkInfo(transaction);
WebfluxHelper.setTransactionName(transaction, exchange);
WebfluxHelper.endTransaction(null, transaction, exchange);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package co.elastic.apm.agent.springwebflux;

import co.elastic.apm.agent.httpserver.HttpServerHelper;
import co.elastic.apm.agent.sdk.internal.util.VersionUtils;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.tracer.metadata.PotentiallyMultiValuedMap;
import co.elastic.apm.agent.tracer.util.ResultUtil;
Expand Down Expand Up @@ -65,6 +66,8 @@

public class WebfluxHelper {

private static final String FRAMEWORK_NAME = "Spring Webflux";

private static final Logger log = LoggerFactory.getLogger(WebfluxHelper.class);
private static final Logger oneTimeResponseCodeErrorLogger = LoggerUtils.logOnce(log);

Expand Down Expand Up @@ -182,6 +185,13 @@ public static void endTransaction(@Nullable Throwable thrown, @Nullable Transact
}
}

public static void setFrameworkInfo(@Nullable Transaction<?> transaction) {
if (transaction != null) {
transaction.setFrameworkName(FRAMEWORK_NAME);
transaction.setFrameworkVersion(VersionUtils.getVersion(HandlerMethod.class, "org.springframework", "webflux"));
}
}

public static void setTransactionName(@Nullable Transaction<?> transaction, ServerWebExchange exchange) {
if (transaction == null) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public abstract class AbstractServerInstrumentationTest extends AbstractInstrume
private static final String BASIC_AUTH_HEADER_VALUE = "Basic ZWxhc3RpYzpjaGFuZ2VtZQ==";

protected static WebFluxApplication.App app;
protected String expectedFrameworkVersion = "5.3.30";
protected GreetingWebClient client;

@BeforeAll
Expand Down Expand Up @@ -451,7 +452,11 @@ protected ErrorCaptureImpl getFirstError() {
return reporter.getFirstError(200);
}

static TransactionImpl checkTransaction(TransactionImpl transaction, String expectedName, String expectedMethod, int expectedStatus) {
TransactionImpl checkTransaction(TransactionImpl transaction, String expectedName, String expectedMethod, int expectedStatus) {
return checkTransaction(transaction, expectedName, expectedMethod, expectedStatus, expectedFrameworkVersion);
}

static TransactionImpl checkTransaction(TransactionImpl transaction, String expectedName, String expectedMethod, int expectedStatus, String expectedFrameworkVersion) {
assertThat(transaction.getType()).isEqualTo("request");
assertThat(transaction.getNameAsString()).isEqualTo(expectedName);

Expand All @@ -464,6 +469,12 @@ static TransactionImpl checkTransaction(TransactionImpl transaction, String expe
assertThat(transaction.getResult())
.isEqualTo(String.format("HTTP %dxx", expectedStatus / 100));

assertThat(transaction.getFrameworkName())
.isEqualTo("Spring Webflux");

assertThat(transaction.getFrameworkVersion())
.isEqualTo(expectedFrameworkVersion);

return transaction;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class ServletContainerTest extends AbstractInstrumentationTest {

protected static WebFluxApplication.App app;
protected static GreetingWebClient client;
protected String expectedFrameworkVersion = "5.3.30";

@BeforeAll
static void startApp() {
Expand Down Expand Up @@ -74,7 +75,7 @@ void shouldOnlyCreateOneTransaction() throws InterruptedException {
TransactionImpl transaction = reporter.getFirstTransaction(200);

// transaction naming should be set by webflux instrumentation
AbstractServerInstrumentationTest.checkTransaction(transaction, "GET /functional/with-parameters/{id}", "GET", 200);
AbstractServerInstrumentationTest.checkTransaction(transaction, "GET /functional/with-parameters/{id}", "GET", 200, expectedFrameworkVersion);
SylvainJuge marked this conversation as resolved.
Show resolved Hide resolved

// transaction HTTP part should be provided by servlet instrumentation
AbstractServerInstrumentationTest.checkUrl(client, transaction, "/with-parameters/42");
Expand Down
Loading