Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ private AwsAttributeKeys() {}
static final AttributeKey<String> AWS_REMOTE_SERVICE =
AttributeKey.stringKey("aws.remote.service");

static final AttributeKey<String> AWS_REMOTE_ENVIRONMENT =
AttributeKey.stringKey("aws.remote.environment");

static final AttributeKey<String> AWS_REMOTE_OPERATION =
AttributeKey.stringKey("aws.remote.operation");

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

static final AttributeKey<String> AWS_LAMBDA_NAME =
AttributeKey.stringKey("aws.lambda.function.name");

static final AttributeKey<String> AWS_LAMBDA_ARN =
AttributeKey.stringKey("aws.lambda.function.arn");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,15 @@
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_GUARDRAIL_ARN;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_GUARDRAIL_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_KNOWLEDGE_BASE_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_ARN;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_NAME;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_RESOURCE_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_OPERATION;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_SERVICE;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_NAME;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_URL;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_DB_USER;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_ENVIRONMENT;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_OPERATION;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_IDENTIFIER;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_TYPE;
Expand Down Expand Up @@ -518,6 +521,37 @@ private static void setRemoteResourceTypeAndIdentifier(SpanData span, Attributes
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_SECRET_ARN))));
cloudformationPrimaryIdentifier =
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_SECRET_ARN)));
} else if (isKeyPresent(span, AWS_LAMBDA_NAME)) {
// Handling downstream Lambda as a service vs. an AWS resource:
// - If the method call is "Invoke", we treat downstream Lambda as a service.
// - Otherwise, we treat it as an AWS resource.
//
// This addresses a Lambda topology issue in Application Signals.
// More context in PR:
// https://github.com/aws-observability/aws-otel-python-instrumentation/pull/319
//
// NOTE: The environment variables LAMBDA_APPLICATION_SIGNALS_REMOTE_ENVIRONMENT was
// introduced as part of this fix.
// It is optional and allows users to override the default value if needed.
if ("Invoke".equals(getRemoteOperation(span, RPC_METHOD))) {
Optional<String> remoteService =
getLambdaFunctionNameFromArn(
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_LAMBDA_NAME))));
builder.put(AWS_REMOTE_SERVICE, remoteService.get());

String remoteEnvironment =
Optional.ofNullable(System.getenv("LAMBDA_APPLICATION_SIGNALS_REMOTE_ENVIRONMENT"))
.filter(s -> !s.isEmpty())
.orElse("default");
builder.put(AWS_REMOTE_ENVIRONMENT, "lambda:" + remoteEnvironment);
} else {
remoteResourceType = Optional.of(NORMALIZED_LAMBDA_SERVICE_NAME + "::Function");
remoteResourceIdentifier =
getLambdaFunctionNameFromArn(
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_LAMBDA_NAME))));
cloudformationPrimaryIdentifier =
Optional.ofNullable(escapeDelimiters(span.getAttributes().get(AWS_LAMBDA_ARN)));
}
} else if (isKeyPresent(span, AWS_LAMBDA_RESOURCE_ID)) {
remoteResourceType = Optional.of(NORMALIZED_LAMBDA_SERVICE_NAME + "::EventSourceMapping");
remoteResourceIdentifier =
Expand All @@ -539,6 +573,14 @@ private static void setRemoteResourceTypeAndIdentifier(SpanData span, Attributes
}
}

private static Optional<String> getLambdaFunctionNameFromArn(Optional<String> stringArn) {
if (stringArn.isPresent() && stringArn.get().startsWith("arn:aws:lambda:")) {
Arn resourceArn = Arn.fromString(stringArn.get());
return Optional.of(resourceArn.getResource().toString().split(":")[1]);
}
return stringArn;
}

private static Optional<String> getSecretsManagerResourceNameFromArn(Optional<String> stringArn) {
Arn resourceArn = Arn.fromString(stringArn.get());
return Optional.of(resourceArn.getResource().toString().split(":")[1]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_DATA_SOURCE_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_GUARDRAIL_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_KNOWLEDGE_BASE_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_NAME;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LAMBDA_RESOURCE_ID;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_OPERATION;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_SERVICE;
Expand Down Expand Up @@ -874,6 +875,11 @@ public void testSdkClientSpanWithRemoteResourceAttributes() {
validateRemoteResourceAttributes("AWS::SecretsManager::Secret", "secretName");
mockAttribute(AWS_SECRET_ARN, null);

// Validate behaviour of AWS_LAMBDA_NAME, then remove it.
mockAttribute(AWS_LAMBDA_NAME, "testLambdaName");
validateRemoteResourceAttributes("AWS::Lambda::Function", "testLambdaName");
mockAttribute(AWS_LAMBDA_NAME, null);

// Validate behaviour of AWS_LAMBDA_RESOURCE_ID
mockAttribute(AWS_LAMBDA_RESOURCE_ID, "eventSourceId");
validateRemoteResourceAttributes("AWS::Lambda::EventSourceMapping", "eventSourceId");
Expand Down
Loading