From 3c4a753619c4bb9ec0b2f98bd0a5da3eedeb1f8b Mon Sep 17 00:00:00 2001 From: Nugusbayev Kanagat <48118512+videnkz@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:02:36 +0500 Subject: [PATCH] differentiate Lambda url from api gateway (#3417) --------- Co-authored-by: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> --- CHANGELOG.asciidoc | 4 ++++ .../APIGatewayProxyV1TransactionHelper.java | 9 +++++++++ .../APIGatewayProxyV2TransactionHelper.java | 19 +++++++++++++------ .../AbstractAPIGatewayTransactionHelper.java | 18 +++++++++++++++++- .../awslambda/ApiGatewayV1LambdaTest.java | 11 +++++++++++ .../awslambda/ApiGatewayV2LambdaTest.java | 12 ++++++++++++ 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index c989a23500..6f863ba558 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -35,6 +35,10 @@ Use subheadings with the "=====" level for adding notes for unreleased changes: ===== Bug fixes * Fixed problems with public API annotation inheritance - {pull}3551[#3551] +[float] +===== Features +* Differentiate Lambda URLs from API Gateway in AWS Lambda integration - {pull}3417[#3417] + [[release-notes-1.x]] === Java Agent version 1.x diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java index 20cbe4c828..3d13b5f35c 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java @@ -111,6 +111,15 @@ protected void setTransactionTriggerData(Transaction transaction, APIGatewayP } } + @Override + public String getDomainName(APIGatewayProxyRequestEvent apiGatewayRequest) { + APIGatewayProxyRequestEvent.ProxyRequestContext rContext = apiGatewayRequest.getRequestContext(); + if (null == rContext) { + return null; + } + return rContext.getDomainName(); + } + @Override protected String getApiGatewayVersion() { return "1.0"; diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java index db3edf620b..f912577f92 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java @@ -19,10 +19,10 @@ package co.elastic.apm.agent.awslambda.helper; import co.elastic.apm.agent.awslambda.MapTextHeaderGetter; -import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse; @@ -45,8 +45,8 @@ public static APIGatewayProxyV2TransactionHelper getInstance() { } @Override - protected Transaction doStartTransaction(APIGatewayV2HTTPEvent apiGatewayEvent, Context lambdaContext) { - Transaction transaction = tracer.startChildTransaction(apiGatewayEvent.getHeaders(), MapTextHeaderGetter.INSTANCE, PrivilegedActionUtils.getClassLoader(apiGatewayEvent.getClass())); + protected Transaction doStartTransaction(APIGatewayV2HTTPEvent apiGatewayEvent, Context lambdaContext) { + Transaction transaction = tracer.startChildTransaction(apiGatewayEvent.getHeaders(), MapTextHeaderGetter.INSTANCE, PrivilegedActionUtils.getClassLoader(apiGatewayEvent.getClass())); APIGatewayV2HTTPEvent.RequestContext requestContext = apiGatewayEvent.getRequestContext(); if (transaction != null) { @@ -60,12 +60,12 @@ protected Transaction doStartTransaction(APIGatewayV2HTTPEvent apiGatewayEven } @Override - public void captureOutputForTransaction(Transaction transaction, APIGatewayV2HTTPResponse responseEvent) { + public void captureOutputForTransaction(Transaction transaction, APIGatewayV2HTTPResponse responseEvent) { fillHttpResponseData(transaction, responseEvent.getHeaders(), responseEvent.getStatusCode()); } @Override - protected void setTransactionTriggerData(Transaction transaction, APIGatewayV2HTTPEvent apiGatewayRequest) { + protected void setTransactionTriggerData(Transaction transaction, APIGatewayV2HTTPEvent apiGatewayRequest) { super.setTransactionTriggerData(transaction, apiGatewayRequest); APIGatewayV2HTTPEvent.RequestContext rContext = apiGatewayRequest.getRequestContext(); setApiGatewayContextData(transaction, rContext.getRequestId(), rContext.getApiId(), @@ -112,4 +112,11 @@ protected String getResourcePath(APIGatewayV2HTTPEvent event) { } return routeKey; } + + @Nullable + @Override + String getDomainName(APIGatewayV2HTTPEvent apiGatewayRequest) { + APIGatewayV2HTTPEvent.RequestContext requestContext = apiGatewayRequest.getRequestContext(); + return requestContext != null ? requestContext.getDomainName() : null; + } } diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java index b30ba86151..542eed68f6 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java @@ -30,6 +30,7 @@ import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.AbstractSpan; import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import javax.annotation.Nullable; import java.nio.CharBuffer; @@ -124,12 +125,27 @@ private boolean hasBody(@Nullable String contentTypeHeader, @Nullable String met protected void setTransactionTriggerData(Transaction transaction, I apiGatewayRequest) { transaction.withType(TRANSACTION_TYPE); CloudOrigin cloudOrigin = transaction.getContext().getCloudOrigin(); - cloudOrigin.withServiceName("api gateway"); + if (isLambdaUrl(apiGatewayRequest)) { + cloudOrigin.withServiceName("lambda url"); + } else { + cloudOrigin.withServiceName("api gateway"); + } cloudOrigin.withProvider("aws"); transaction.getFaas().getTrigger().withType("http"); transaction.getContext().getServiceOrigin().withVersion(getApiGatewayVersion()); } + private boolean isLambdaUrl(I apiGatewayRequest) { + String domainName = getDomainName(apiGatewayRequest); + if (null == domainName) { + return false; + } + return domainName.contains(".lambda-url."); + } + + @Nullable + abstract String getDomainName(I apiGatewayRequest); + protected void setApiGatewayContextData(Transaction transaction, @Nullable String requestId, @Nullable String apiId, @Nullable String domainName, @Nullable String accountId) { transaction.getFaas().getTrigger().withRequestId(requestId); diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV1LambdaTest.java b/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV1LambdaTest.java index c6e0be6e30..6aa7f622b0 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV1LambdaTest.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV1LambdaTest.java @@ -256,6 +256,17 @@ public void testTransactionNameWithUsePathAsName() { assertThat(reporter.getFirstTransaction().getNameAsString()).isEqualTo("PUT /prod/proxy-test/12345"); } + @Test + public void testServiceNameAsLambdaUrl() { + APIGatewayProxyRequestEvent event = createInput(); + event.getRequestContext().setDomainName("myurl.lambda-url.us-west-2.on.aws"); + getFunction().handleRequest(event, context); + reporter.awaitTransactionCount(1); + reporter.awaitSpanCount(1); + Transaction transaction = reporter.getFirstTransaction(); + assertThat(transaction.getContext().getCloudOrigin().getServiceName()).isEqualTo("lambda url"); + } + @Override protected AbstractFunction createHandler() { return new ApiGatewayV1LambdaFunction(); diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV2LambdaTest.java b/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV2LambdaTest.java index d2a7cd73b4..d98e652551 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV2LambdaTest.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/test/java/co/elastic/apm/agent/awslambda/ApiGatewayV2LambdaTest.java @@ -31,6 +31,7 @@ import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.tracer.Outcome; import co.elastic.apm.agent.tracer.metadata.PotentiallyMultiValuedMap; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse; import org.junit.BeforeClass; @@ -249,6 +250,17 @@ public void testTransactionNameWithUsePathAsName() { assertThat(reporter.getFirstTransaction().getNameAsString()).isEqualTo("PUT /prod/proxy-test/12345"); } + @Test + public void testServiceNameAsLambdaUrl() { + APIGatewayV2HTTPEvent event = createInput(); + event.getRequestContext().setDomainName("myurl.lambda-url.us-west-2.on.aws"); + getFunction().handleRequest(event, context); + reporter.awaitTransactionCount(1); + reporter.awaitSpanCount(1); + Transaction transaction = reporter.getFirstTransaction(); + assertThat(transaction.getContext().getCloudOrigin().getServiceName()).isEqualTo("lambda url"); + } + @Override protected AbstractFunction createHandler() { return new ApiGatewayV2LambdaFunction();