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 @@ -44,6 +44,7 @@ dependencies {
testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-ec2:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-lambda:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-rds:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-s3:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;

import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractLambdaClientTest;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import org.junit.jupiter.api.extension.RegisterExtension;

class LambdaClientTest extends AbstractLambdaClientTest {
@RegisterExtension
static final InstrumentationExtension testing = AgentInstrumentationExtension.create();

@Override
protected InstrumentationExtension testing() {
return testing;
}

@Override
public AWSLambdaClientBuilder configureClient(AWSLambdaClientBuilder clientBuilder) {
return clientBuilder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-ec2:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-lambda:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-rds:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-s3:1.11.106")
testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,11 @@ final class AwsExperimentalAttributes {
static final AttributeKey<String> AWS_STREAM_NAME = stringKey("aws.stream.name");
static final AttributeKey<String> AWS_TABLE_NAME = stringKey("aws.table.name");

// Work is underway to add these two keys to the SemConv AWS registry, in line with other AWS
// resources.
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/registry/attributes/aws.md#amazon-lambda-attributes
static final AttributeKey<String> AWS_LAMBDA_ARN = stringKey("aws.lambda.function.arn");
static final AttributeKey<String> AWS_LAMBDA_NAME = stringKey("aws.lambda.function.name");

private AwsExperimentalAttributes() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class AwsSdkAttributesExtractor implements AttributesExtractor<Request<?>, Respo
// Copied from AwsIncubatingAttributes
private static final AttributeKey<String> AWS_SECRETSMANAGER_SECRET_ARN =
stringKey("aws.secretsmanager.secret.arn");
private static final AttributeKey<String> AWS_LAMBDA_RESOURCE_MAPPING_ID =
stringKey("aws.lambda.resource_mapping.id");
private static final AttributeKey<String> AWS_SNS_TOPIC_ARN = stringKey("aws.sns.topic.arn");
private static final AttributeKey<String> AWS_STEP_FUNCTIONS_ACTIVITY_ARN =
stringKey("aws.step_functions.activity.arn");
Expand All @@ -46,6 +48,11 @@ private static boolean canGetResponseMetadata() {
@Override
public void onStart(AttributesBuilder attributes, Context parentContext, Request<?> request) {
Object originalRequest = request.getOriginalRequest();
setAttribute(
attributes,
AWS_LAMBDA_RESOURCE_MAPPING_ID,
originalRequest,
RequestAccess::getLambdaResourceMappingId);
setAttribute(attributes, AWS_SNS_TOPIC_ARN, originalRequest, RequestAccess::getSnsTopicArn);
setAttribute(
attributes,
Expand All @@ -69,6 +76,11 @@ public void onEnd(
Object awsResp = getAwsResponse(response);
if (awsResp != null) {
setAttribute(attributes, AWS_SECRETSMANAGER_SECRET_ARN, awsResp, RequestAccess::getSecretArn);
setAttribute(
attributes,
AWS_LAMBDA_RESOURCE_MAPPING_ID,
awsResp,
RequestAccess::getLambdaResourceMappingId);
setAttribute(attributes, AWS_SNS_TOPIC_ARN, awsResp, RequestAccess::getSnsTopicArn);
setAttribute(
attributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT;
import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BUCKET_NAME;
import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_LAMBDA_ARN;
import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_LAMBDA_NAME;
import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_QUEUE_NAME;
import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_QUEUE_URL;
import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_STREAM_NAME;
Expand Down Expand Up @@ -35,6 +37,7 @@ public void onStart(AttributesBuilder attributes, Context parentContext, Request
setRequestAttribute(attributes, AWS_QUEUE_NAME, originalRequest, RequestAccess::getQueueName);
setRequestAttribute(attributes, AWS_STREAM_NAME, originalRequest, RequestAccess::getStreamName);
setRequestAttribute(attributes, AWS_TABLE_NAME, originalRequest, RequestAccess::getTableName);
setRequestAttribute(attributes, AWS_LAMBDA_NAME, originalRequest, RequestAccess::getLambdaName);
}

private static void setRequestAttribute(
Expand All @@ -54,5 +57,17 @@ public void onEnd(
Context context,
Request<?> request,
@Nullable Response<?> response,
@Nullable Throwable error) {}
@Nullable Throwable error) {
Object awsResponse = getAwsResponse(response);
if (awsResponse != null) {
setRequestAttribute(attributes, AWS_LAMBDA_ARN, awsResponse, RequestAccess::getLambdaArn);
}
}

private static Object getAwsResponse(Response<?> response) {
if (response == null) {
return null;
}
return response.getAwsResponse();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import javax.annotation.Nullable;

final class RequestAccess {
private static final String LAMBDA_REQUEST_CLASS_PREFIX = "com.amazonaws.services.lambda.model.";
private static final String SECRETS_MANAGER_REQUEST_CLASS_PREFIX =
"com.amazonaws.services.secretsmanager.model.";
private static final String STEP_FUNCTIONS_REQUEST_CLASS_PREFIX =
Expand All @@ -24,6 +25,30 @@ protected RequestAccess computeValue(Class<?> type) {
}
};

@Nullable
static String getLambdaArn(Object request) {
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
if (access.getLambdaConfiguration == null) {
return null;
}
Object config = invokeOrNull(access.getLambdaConfiguration, request, Object.class);
return config != null
? invokeOrNull(LambdaFunctionConfigurationAccess.getLambdaArnFromConfiguration, config)
: null;
}

@Nullable
static String getLambdaName(Object request) {
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
return invokeOrNull(access.getLambdaName, request);
}

@Nullable
static String getLambdaResourceMappingId(Object request) {
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
return invokeOrNull(access.getLambdaResourceMappingId, request);
}

@Nullable
static String getSecretArn(Object request) {
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
Expand Down Expand Up @@ -86,17 +111,26 @@ static String getTargetArn(Object request) {

@Nullable
private static String invokeOrNull(@Nullable MethodHandle method, Object obj) {
return invokeOrNull(method, obj, String.class);
}

@Nullable
private static <T> T invokeOrNull(
@Nullable MethodHandle method, Object obj, Class<T> returnType) {
if (method == null) {
return null;
}
try {
return (String) method.invoke(obj);
return returnType.cast(method.invoke(obj));
} catch (Throwable t) {
return null;
}
}

@Nullable private final MethodHandle getBucketName;
@Nullable private final MethodHandle getLambdaConfiguration;
@Nullable private final MethodHandle getLambdaName;
@Nullable private final MethodHandle getLambdaResourceMappingId;
@Nullable private final MethodHandle getQueueUrl;
@Nullable private final MethodHandle getQueueName;
@Nullable private final MethodHandle getSecretArn;
Expand All @@ -116,6 +150,10 @@ private RequestAccess(Class<?> clz) {
getTopicArn = findAccessorOrNull(clz, "getTopicArn");
getTargetArn = findAccessorOrNull(clz, "getTargetArn");

boolean isLambda = clz.getName().startsWith(LAMBDA_REQUEST_CLASS_PREFIX);
getLambdaConfiguration = isLambda ? findLambdaGetConfigurationMethod(clz) : null;
getLambdaName = isLambda ? findAccessorOrNull(clz, "getFunctionName") : null;
getLambdaResourceMappingId = isLambda ? findAccessorOrNull(clz, "getUUID") : null;
boolean isSecretsManager = clz.getName().startsWith(SECRETS_MANAGER_REQUEST_CLASS_PREFIX);
getSecretArn = isSecretsManager ? findAccessorOrNull(clz, "getARN") : null;
boolean isStepFunction = clz.getName().startsWith(STEP_FUNCTIONS_REQUEST_CLASS_PREFIX);
Expand All @@ -125,11 +163,43 @@ private RequestAccess(Class<?> clz) {

@Nullable
private static MethodHandle findAccessorOrNull(Class<?> clz, String methodName) {
return findAccessorOrNull(clz, methodName, String.class);
}

@Nullable
private static MethodHandle findAccessorOrNull(
Class<?> clz, String methodName, Class<?> returnType) {
try {
return MethodHandles.publicLookup()
.findVirtual(clz, methodName, MethodType.methodType(String.class));
.findVirtual(clz, methodName, MethodType.methodType(returnType));
} catch (Throwable t) {
return null;
}
}

@Nullable
private static MethodHandle findLambdaGetConfigurationMethod(Class<?> clz) {
try {
Class<?> returnType =
Class.forName("com.amazonaws.services.lambda.model.FunctionConfiguration");
return findAccessorOrNull(clz, "getConfiguration", returnType);
} catch (Throwable t) {
return null;
}
}

private static class LambdaFunctionConfigurationAccess {
static final MethodHandle getLambdaArnFromConfiguration = findGetLambdaArnMethod();

@Nullable
private static MethodHandle findGetLambdaArnMethod() {
try {
Class<?> lambdaConfigurationClass =
Class.forName("com.amazonaws.services.lambda.model.FunctionConfiguration");
return findAccessorOrNull(lambdaConfigurationClass, "getFunctionArn");
} catch (Throwable t) {
return null;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.awssdk.v1_11;

import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
import org.junit.jupiter.api.extension.RegisterExtension;

class LambdaClientTest extends AbstractLambdaClientTest {
@RegisterExtension
private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();

@Override
protected InstrumentationExtension testing() {
return testing;
}

@Override
public AWSLambdaClientBuilder configureClient(AWSLambdaClientBuilder clientBuilder) {
return clientBuilder.withRequestHandlers(
AwsSdkTelemetry.builder(testing().getOpenTelemetry())
.setCaptureExperimentalSpanAttributes(true)
.build()
.newRequestHandler());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
compileOnly("com.amazonaws:aws-java-sdk-dynamodb:1.11.106")
compileOnly("com.amazonaws:aws-java-sdk-ec2:1.11.106")
compileOnly("com.amazonaws:aws-java-sdk-kinesis:1.11.106")
compileOnly("com.amazonaws:aws-java-sdk-lambda:1.11.106")
compileOnly("com.amazonaws:aws-java-sdk-rds:1.11.106")
compileOnly("com.amazonaws:aws-java-sdk-s3:1.11.106")
compileOnly("com.amazonaws:aws-java-sdk-secretsmanager:1.12.80")
Expand Down
Loading
Loading