Skip to content

Commit a8da0be

Browse files
committed
lambda topology issue fix
1 parent a2b1aac commit a8da0be

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsAttributeKeys.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ private AwsAttributeKeys() {}
3232
static final AttributeKey<String> AWS_REMOTE_SERVICE =
3333
AttributeKey.stringKey("aws.remote.service");
3434

35+
static final AttributeKey<String> AWS_REMOTE_ENVIRONMENT =
36+
AttributeKey.stringKey("aws.remote.environment");
37+
3538
static final AttributeKey<String> AWS_REMOTE_OPERATION =
3639
AttributeKey.stringKey("aws.remote.operation");
3740

@@ -64,6 +67,9 @@ private AwsAttributeKeys() {}
6467
static final AttributeKey<String> AWS_SECRET_ARN =
6568
AttributeKey.stringKey("aws.secretsmanager.secret.arn");
6669

70+
static final AttributeKey<String> AWS_LAMBDA_NAME =
71+
AttributeKey.stringKey("aws.lambda.function.name");
72+
6773
static final AttributeKey<String> AWS_LAMBDA_ARN =
6874
AttributeKey.stringKey("aws.lambda.function.arn");
6975

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsMetricAttributeGenerator.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@
5252
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_GUARDRAIL_ARN;
5353
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_GUARDRAIL_ID;
5454
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_KNOWLEDGE_BASE_ID;
55+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_ARN;
56+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_NAME;
5557
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_RESOURCE_ID;
5658
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_OPERATION;
5759
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_SERVICE;
5860
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_NAME;
5961
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_URL;
6062
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_DB_USER;
63+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_ENVIRONMENT;
6164
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_OPERATION;
6265
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_IDENTIFIER;
6366
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_TYPE;
@@ -518,6 +521,40 @@ private static void setRemoteResourceTypeAndIdentifier(SpanData span, Attributes
518521
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_SECRET_ARN))));
519522
cloudformationPrimaryIdentifier =
520523
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_SECRET_ARN)));
524+
} else if (isKeyPresent(span, AWS_LAMBDA_NAME)) {
525+
// Handling downstream Lambda as a service vs. an AWS resource:
526+
// - If the method call is "Invoke", we treat downstream Lambda as a service.
527+
// - Otherwise, we treat it as an AWS resource.
528+
//
529+
// This addresses a Lambda topology issue in Application Signals.
530+
// More context in PR:
531+
// https://github.com/aws-observability/aws-otel-python-instrumentation/pull/319
532+
//
533+
// NOTE: The environment variables LAMBDA_APPLICATION_SIGNALS_REMOTE_SERVICE and
534+
// LAMBDA_APPLICATION_SIGNALS_REMOTE_ENVIRONMENT were introduced as part of this fix.
535+
// They are optional and allow users to override the default values if needed.
536+
if ("Invoke".equals(getRemoteOperation(span, RPC_METHOD))) {
537+
String remoteService =
538+
Optional.ofNullable(System.getenv("LAMBDA_APPLICATION_SIGNALS_REMOTE_SERVICE"))
539+
.filter(s -> !s.isEmpty())
540+
.orElse(span.getAttributes().get(AWS_LAMBDA_NAME));
541+
if (remoteService != null) {
542+
builder.put(AWS_REMOTE_SERVICE, remoteService);
543+
}
544+
545+
String remoteEnvironment =
546+
Optional.ofNullable(System.getenv("LAMBDA_APPLICATION_SIGNALS_REMOTE_ENVIRONMENT"))
547+
.filter(s -> !s.isEmpty())
548+
.orElse("default");
549+
builder.put(AWS_REMOTE_ENVIRONMENT, "lambda:" + remoteEnvironment);
550+
} else {
551+
remoteResourceType = Optional.of(NORMALIZED_LAMBDA_SERVICE_NAME + "::Function");
552+
remoteResourceIdentifier =
553+
getLambdaFunctionNameFromArn(
554+
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_LAMBDA_NAME))));
555+
cloudformationPrimaryIdentifier =
556+
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_LAMBDA_ARN)));
557+
}
521558
} else if (isKeyPresent(span, AWS_LAMBDA_RESOURCE_ID)) {
522559
remoteResourceType = Optional.of(NORMALIZED_LAMBDA_SERVICE_NAME + "::EventSourceMapping");
523560
remoteResourceIdentifier =
@@ -539,6 +576,14 @@ private static void setRemoteResourceTypeAndIdentifier(SpanData span, Attributes
539576
}
540577
}
541578

579+
private static Optional<String> getLambdaFunctionNameFromArn(Optional<String> stringArn) {
580+
if (stringArn.isPresent() && stringArn.get().startsWith("arn:aws:lambda:")) {
581+
Arn resourceArn = Arn.fromString(stringArn.get());
582+
return Optional.of(resourceArn.getResource().toString().split(":")[1]);
583+
}
584+
return stringArn;
585+
}
586+
542587
private static Optional<String> getSecretsManagerResourceNameFromArn(Optional<String> stringArn) {
543588
Arn resourceArn = Arn.fromString(stringArn.get());
544589
return Optional.of(resourceArn.getResource().toString().split(":")[1]);

awsagentprovider/src/test/java/software/amazon/opentelemetry/javaagent/providers/AwsMetricAttributeGeneratorTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_DATA_SOURCE_ID;
2727
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_GUARDRAIL_ID;
2828
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_KNOWLEDGE_BASE_ID;
29+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_NAME;
2930
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_RESOURCE_ID;
3031
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_OPERATION;
3132
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_SERVICE;
@@ -874,6 +875,11 @@ public void testSdkClientSpanWithRemoteResourceAttributes() {
874875
validateRemoteResourceAttributes("AWS::SecretsManager::Secret", "secretName");
875876
mockAttribute(AWS_SECRET_ARN, null);
876877

878+
// Validate behaviour of AWS_LAMBDA_NAME, then remove it.
879+
mockAttribute(AWS_LAMBDA_NAME, "testLambdaName");
880+
validateRemoteResourceAttributes("AWS::Lambda::Function", "testLambdaName");
881+
mockAttribute(AWS_LAMBDA_NAME, null);
882+
877883
// Validate behaviour of AWS_LAMBDA_RESOURCE_ID
878884
mockAttribute(AWS_LAMBDA_RESOURCE_ID, "eventSourceId");
879885
validateRemoteResourceAttributes("AWS::Lambda::EventSourceMapping", "eventSourceId");

0 commit comments

Comments
 (0)