diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts index f357a19f885d..d1e3cffceffa 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts @@ -47,6 +47,10 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-1.11:testing")) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts index 6cf49a21c49a..d3287a87d795 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts @@ -18,6 +18,10 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sqs:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") // last version that does not use json protocol latestDepTestLibrary("com.amazonaws:aws-java-sdk-sqs:1.12.583") diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts index bfe844e413c4..521e6a3dd9e0 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts @@ -17,6 +17,10 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") // last version that does not use json protocol latestDepTestLibrary("com.amazonaws:aws-java-sdk-sqs:1.12.583") diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsBedrockResourceType.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsBedrockResourceType.java new file mode 100644 index 000000000000..78194dcae8be --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsBedrockResourceType.java @@ -0,0 +1,133 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_DATASOURCE_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_KNOWLEDGEBASE_ID; + +import io.opentelemetry.api.common.AttributeKey; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +enum AwsBedrockResourceType { + AGENT_TYPE(AWS_AGENT_ID, RequestAccess::getAgentId), + DATA_SOURCE_TYPE(AWS_DATASOURCE_ID, RequestAccess::getDataSourceId), + KNOWLEDGE_BASE_TYPE(AWS_KNOWLEDGEBASE_ID, RequestAccess::getKnowledgeBaseId); + + @SuppressWarnings("ImmutableEnumChecker") + private final AttributeKey keyAttribute; + + @SuppressWarnings("ImmutableEnumChecker") + private final Function attributeValueAccessor; + + AwsBedrockResourceType( + AttributeKey keyAttribute, Function attributeValueAccessor) { + this.keyAttribute = keyAttribute; + this.attributeValueAccessor = attributeValueAccessor; + } + + public AttributeKey getKeyAttribute() { + return keyAttribute; + } + + public Function getAttributeValueAccessor() { + return attributeValueAccessor; + } + + public static AwsBedrockResourceType getRequestType(String requestClass) { + return AwsBedrockResourceTypeMap.BEDROCK_REQUEST_MAP.get(requestClass); + } + + public static AwsBedrockResourceType getResponseType(String responseClass) { + return AwsBedrockResourceTypeMap.BEDROCK_RESPONSE_MAP.get(responseClass); + } + + private static class AwsBedrockResourceTypeMap { + private static final Map BEDROCK_REQUEST_MAP = new HashMap<>(); + private static final Map BEDROCK_RESPONSE_MAP = new HashMap<>(); + + // Bedrock request/response mapping + // We only support operations that are related to the resource and where the context contains + // the AgentID/DataSourceID/KnowledgeBaseID. + // AgentID + private static final List agentRequestClasses = + Arrays.asList( + "CreateAgentActionGroupRequest", + "CreateAgentAliasRequest", + "DeleteAgentActionGroupRequest", + "DeleteAgentAliasRequest", + "DeleteAgentRequest", + "DeleteAgentVersionRequest", + "GetAgentActionGroupRequest", + "GetAgentAliasRequest", + "GetAgentRequest", + "GetAgentVersionRequest", + "ListAgentActionGroupsRequest", + "ListAgentAliasesRequest", + "ListAgentKnowledgeBasesRequest", + "ListAgentVersionsRequest", + "PrepareAgentRequest", + "UpdateAgentActionGroupRequest", + "UpdateAgentAliasRequest", + "UpdateAgentRequest"); + private static final List agentResponseClasses = + Arrays.asList( + "DeleteAgentAliasResult", + "DeleteAgentResult", + "DeleteAgentVersionResult", + "PrepareAgentResult"); + // DataSourceID + private static final List dataSourceRequestClasses = + Arrays.asList("DeleteDataSourceRequest", "GetDataSourceRequest", "UpdateDataSourceRequest"); + private static final List dataSourceResponseClasses = + Arrays.asList("DeleteDataSourceResult"); + // KnowledgeBaseID + private static final List knowledgeBaseRequestClasses = + Arrays.asList( + "AssociateAgentKnowledgeBaseRequest", + "CreateDataSourceRequest", + "DeleteKnowledgeBaseRequest", + "DisassociateAgentKnowledgeBaseRequest", + "GetAgentKnowledgeBaseRequest", + "GetKnowledgeBaseRequest", + "ListDataSourcesRequest", + "UpdateAgentKnowledgeBaseRequest"); + private static final List knowledgeBaseResponseClasses = + Arrays.asList("DeleteKnowledgeBaseResult"); + + private AwsBedrockResourceTypeMap() {} + + static { + // Populate the BEDROCK_REQUEST_MAP + for (String agentRequestClass : agentRequestClasses) { + BEDROCK_REQUEST_MAP.put(agentRequestClass, AwsBedrockResourceType.AGENT_TYPE); + } + for (String dataSourceRequestClass : dataSourceRequestClasses) { + BEDROCK_REQUEST_MAP.put(dataSourceRequestClass, AwsBedrockResourceType.DATA_SOURCE_TYPE); + } + for (String knowledgeBaseRequestClass : knowledgeBaseRequestClasses) { + BEDROCK_REQUEST_MAP.put( + knowledgeBaseRequestClass, AwsBedrockResourceType.KNOWLEDGE_BASE_TYPE); + } + + // Populate the BEDROCK_RESPONSE_MAP + for (String agentResponseClass : agentResponseClasses) { + BEDROCK_REQUEST_MAP.put(agentResponseClass, AwsBedrockResourceType.AGENT_TYPE); + } + for (String dataSourceResponseClass : dataSourceResponseClasses) { + BEDROCK_REQUEST_MAP.put(dataSourceResponseClass, AwsBedrockResourceType.DATA_SOURCE_TYPE); + } + for (String knowledgeBaseResponseClass : knowledgeBaseResponseClasses) { + BEDROCK_REQUEST_MAP.put( + knowledgeBaseResponseClass, AwsBedrockResourceType.KNOWLEDGE_BASE_TYPE); + } + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java index 3e8fddec5c15..99ffed80639d 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java @@ -18,6 +18,16 @@ final class AwsExperimentalAttributes { static final AttributeKey AWS_STREAM_NAME = stringKey("aws.stream.name"); static final AttributeKey AWS_TABLE_NAME = stringKey("aws.table.name"); static final AttributeKey AWS_REQUEST_ID = stringKey("aws.requestId"); + static final AttributeKey AWS_AGENT_ID = stringKey("aws.bedrock.agent.id"); + static final AttributeKey AWS_KNOWLEDGEBASE_ID = + stringKey("aws.bedrock.knowledgebase.id"); + static final AttributeKey AWS_DATASOURCE_ID = stringKey("aws.bedrock.datasource.id"); + static final AttributeKey AWS_GUARDRAIL_ID = stringKey("aws.bedrock.guardrail.id"); + + // TODO: Merge in gen_ai attributes in opentelemetry-semconv-incubating once upgrade to v1.26.0 + static final AttributeKey AWS_BEDROCK_RUNTIME_MODEL_ID = + stringKey("gen_ai.request.model"); + static final AttributeKey AWS_BEDROCK_SYSTEM = stringKey("gen_ai.system"); private AwsExperimentalAttributes() {} } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java index 245f09a5d8f5..0984d8d55245 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java @@ -6,8 +6,13 @@ package io.opentelemetry.instrumentation.awssdk.v1_11; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BEDROCK_RUNTIME_MODEL_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BEDROCK_SYSTEM; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BUCKET_NAME; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_ENDPOINT; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_GUARDRAIL_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_KNOWLEDGEBASE_ID; 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_REQUEST_ID; @@ -21,12 +26,17 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import java.util.Objects; import java.util.function.Function; import javax.annotation.Nullable; class AwsSdkExperimentalAttributesExtractor implements AttributesExtractor, Response> { private static final String COMPONENT_NAME = "java-aws-sdk"; + private static final String BEDROCK_SERVICE = "AmazonBedrock"; + private static final String BEDROCK_AGENT_SERVICE = "AWSBedrockAgent"; + private static final String BEDROCK_AGENT_RUNTIME_SERVICE = "AWSBedrockAgentRuntime"; + private static final String BEDROCK_RUNTIME_SERVICE = "AmazonBedrockRuntime"; @Override public void onStart(AttributesBuilder attributes, Context parentContext, Request request) { @@ -34,21 +44,18 @@ public void onStart(AttributesBuilder attributes, Context parentContext, Request attributes.put(AWS_ENDPOINT, request.getEndpoint().toString()); Object originalRequest = request.getOriginalRequest(); - setRequestAttribute(attributes, AWS_BUCKET_NAME, originalRequest, RequestAccess::getBucketName); - setRequestAttribute(attributes, AWS_QUEUE_URL, originalRequest, RequestAccess::getQueueUrl); - setRequestAttribute(attributes, AWS_QUEUE_NAME, originalRequest, RequestAccess::getQueueName); - setRequestAttribute(attributes, AWS_STREAM_NAME, originalRequest, RequestAccess::getStreamName); - setRequestAttribute(attributes, AWS_TABLE_NAME, originalRequest, RequestAccess::getTableName); - } + String requestClassName = originalRequest.getClass().getSimpleName(); + setAttribute(attributes, AWS_BUCKET_NAME, originalRequest, RequestAccess::getBucketName); + setAttribute(attributes, AWS_QUEUE_URL, originalRequest, RequestAccess::getQueueUrl); + setAttribute(attributes, AWS_QUEUE_NAME, originalRequest, RequestAccess::getQueueName); + setAttribute(attributes, AWS_STREAM_NAME, originalRequest, RequestAccess::getStreamName); + setAttribute(attributes, AWS_TABLE_NAME, originalRequest, RequestAccess::getTableName); - private static void setRequestAttribute( - AttributesBuilder attributes, - AttributeKey key, - Object request, - Function getter) { - String value = getter.apply(request); - if (value != null) { - attributes.put(key, value); + // Get serviceName defined in the AWS Java SDK V1 Request class. + String serviceName = request.getServiceName(); + // Extract request attributes only for Bedrock services. + if (isBedrockService(serviceName)) { + bedrockOnStart(attributes, originalRequest, requestClassName, serviceName); } } @@ -59,12 +66,108 @@ public void onEnd( Request request, @Nullable Response response, @Nullable Throwable error) { - if (response != null && response.getAwsResponse() instanceof AmazonWebServiceResponse) { - AmazonWebServiceResponse awsResp = (AmazonWebServiceResponse) response.getAwsResponse(); - String requestId = awsResp.getRequestId(); - if (requestId != null) { - attributes.put(AWS_REQUEST_ID, requestId); + if (response != null) { + Object awsResp = response.getAwsResponse(); + if (awsResp instanceof AmazonWebServiceResponse) { + AmazonWebServiceResponse awsWebServiceResponse = (AmazonWebServiceResponse) awsResp; + String requestId = awsWebServiceResponse.getRequestId(); + if (requestId != null) { + attributes.put(AWS_REQUEST_ID, requestId); + } + } + // Get serviceName defined in the AWS Java SDK V1 Request class. + String serviceName = request.getServiceName(); + // Extract response attributes for Bedrock services + if (awsResp != null && isBedrockService(serviceName)) { + bedrockOnEnd(attributes, awsResp, serviceName); } } } + + private static void bedrockOnStart( + AttributesBuilder attributes, + Object originalRequest, + String requestClassName, + String serviceName) { + switch (serviceName) { + case BEDROCK_SERVICE: + setAttribute(attributes, AWS_GUARDRAIL_ID, originalRequest, RequestAccess::getGuardrailId); + break; + case BEDROCK_AGENT_SERVICE: + AwsBedrockResourceType resourceType = + AwsBedrockResourceType.getRequestType(requestClassName); + if (resourceType != null) { + setAttribute( + attributes, + resourceType.getKeyAttribute(), + originalRequest, + resourceType.getAttributeValueAccessor()); + } + break; + case BEDROCK_AGENT_RUNTIME_SERVICE: + setAttribute(attributes, AWS_AGENT_ID, originalRequest, RequestAccess::getAgentId); + setAttribute( + attributes, AWS_KNOWLEDGEBASE_ID, originalRequest, RequestAccess::getKnowledgeBaseId); + break; + case BEDROCK_RUNTIME_SERVICE: + if (!Objects.equals(requestClassName, "InvokeModelRequest")) { + break; + } + attributes.put(AWS_BEDROCK_SYSTEM, "aws_bedrock"); + Function getter = RequestAccess::getModelId; + String modelId = getter.apply(originalRequest); + attributes.put(AWS_BEDROCK_RUNTIME_MODEL_ID, modelId); + break; + default: + break; + } + } + + private static void bedrockOnEnd( + AttributesBuilder attributes, Object awsResp, String serviceName) { + switch (serviceName) { + case BEDROCK_SERVICE: + setAttribute(attributes, AWS_GUARDRAIL_ID, awsResp, RequestAccess::getGuardrailId); + break; + case BEDROCK_AGENT_SERVICE: + String responseClassName = awsResp.getClass().getSimpleName(); + AwsBedrockResourceType resourceType = + AwsBedrockResourceType.getResponseType(responseClassName); + if (resourceType != null) { + setAttribute( + attributes, + resourceType.getKeyAttribute(), + awsResp, + resourceType.getAttributeValueAccessor()); + } + break; + case BEDROCK_AGENT_RUNTIME_SERVICE: + setAttribute(attributes, AWS_AGENT_ID, awsResp, RequestAccess::getAgentId); + setAttribute(attributes, AWS_KNOWLEDGEBASE_ID, awsResp, RequestAccess::getKnowledgeBaseId); + break; + default: + break; + } + } + + private static boolean isBedrockService(String serviceName) { + // Check if the serviceName belongs to Bedrock Services defined in AWS Java SDK V1. + // For example AmazonBedrock + return serviceName.equals(BEDROCK_SERVICE) + || serviceName.equals(BEDROCK_AGENT_SERVICE) + || serviceName.equals(BEDROCK_AGENT_RUNTIME_SERVICE) + || serviceName.equals(BEDROCK_RUNTIME_SERVICE); + } + + private static void setAttribute( + AttributesBuilder attributes, + AttributeKey key, + Object request, + Function getter) { + String value = getter.apply(request); + if (value != null) { + attributes.put(key, value); + } + } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java index bb2ae9266c5c..8cf71b6a38e6 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java @@ -50,6 +50,36 @@ static String getTableName(Object request) { return invokeOrNull(access.getTableName, request); } + @Nullable + static String getAgentId(Object request) { + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getAgentId, request); + } + + @Nullable + static String getKnowledgeBaseId(Object request) { + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getKnowledgeBaseId, request); + } + + @Nullable + static String getDataSourceId(Object request) { + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getDataSourceId, request); + } + + @Nullable + static String getGuardrailId(Object request) { + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getGuardrailId, request); + } + + @Nullable + static String getModelId(Object request) { + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getModelId, request); + } + @Nullable private static String invokeOrNull(@Nullable MethodHandle method, Object obj) { if (method == null) { @@ -67,6 +97,11 @@ private static String invokeOrNull(@Nullable MethodHandle method, Object obj) { @Nullable private final MethodHandle getQueueName; @Nullable private final MethodHandle getStreamName; @Nullable private final MethodHandle getTableName; + @Nullable private final MethodHandle getAgentId; + @Nullable private final MethodHandle getKnowledgeBaseId; + @Nullable private final MethodHandle getDataSourceId; + @Nullable private final MethodHandle getGuardrailId; + @Nullable private final MethodHandle getModelId; private RequestAccess(Class clz) { getBucketName = findAccessorOrNull(clz, "getBucketName"); @@ -74,6 +109,11 @@ private RequestAccess(Class clz) { getQueueName = findAccessorOrNull(clz, "getQueueName"); getStreamName = findAccessorOrNull(clz, "getStreamName"); getTableName = findAccessorOrNull(clz, "getTableName"); + getAgentId = findAccessorOrNull(clz, "getAgentId"); + getKnowledgeBaseId = findAccessorOrNull(clz, "getKnowledgeBaseId"); + getDataSourceId = findAccessorOrNull(clz, "getDataSourceId"); + getGuardrailId = findAccessorOrNull(clz, "getGuardrailId"); + getModelId = findAccessorOrNull(clz, "getModelId"); } @Nullable diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts index 548631e9f187..6223dd1df08f 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts @@ -14,6 +14,10 @@ dependencies { compileOnly("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") compileOnly("com.amazonaws:aws-java-sdk-sns:1.11.106") compileOnly("com.amazonaws:aws-java-sdk-sqs:1.11.106") + compileOnly("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + compileOnly("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + compileOnly("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + compileOnly("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") // needed for SQS - using emq directly as localstack references emq v0.15.7 ie WITHOUT AWS trace header propagation implementation("org.elasticmq:elasticmq-rest-sqs_2.12:1.0.0") diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy index 95e6ed8985d1..f904f21fb1bf 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy @@ -27,6 +27,14 @@ import com.amazonaws.services.rds.AmazonRDSClientBuilder import com.amazonaws.services.rds.model.DeleteOptionGroupRequest import com.amazonaws.services.s3.AmazonS3Client import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.amazonaws.services.bedrockagent.AWSBedrockAgentClientBuilder +import com.amazonaws.services.bedrockagent.model.GetAgentRequest +import com.amazonaws.services.bedrockagent.model.GetKnowledgeBaseRequest +import com.amazonaws.services.bedrockagent.model.GetDataSourceRequest +import com.amazonaws.services.bedrock.AmazonBedrockClientBuilder +import com.amazonaws.services.bedrock.model.GetGuardrailRequest +import com.amazonaws.services.bedrockruntime.AmazonBedrockRuntimeClientBuilder +import com.amazonaws.services.bedrockruntime.model.InvokeModelRequest import io.opentelemetry.api.trace.Span import io.opentelemetry.instrumentation.test.InstrumentationSpecification import io.opentelemetry.semconv.SemanticAttributes @@ -38,6 +46,7 @@ import spock.lang.Shared import spock.lang.Unroll import java.time.Duration +import java.nio.charset.StandardCharsets import static io.opentelemetry.api.trace.SpanKind.CLIENT import static io.opentelemetry.api.trace.SpanKind.PRODUCER @@ -156,6 +165,48 @@ abstract class AbstractAws1ClientTest extends InstrumentationSpecification { """ + "Bedrock" | "GetGuardrail" | "GET" | "/" | AmazonBedrockClientBuilder.standard() | { c -> c.getGuardrail(new GetGuardrailRequest().withGuardrailIdentifier("guardrailId")) } | ["aws.bedrock.guardrail.id": "guardrailId"] | """ + { + "blockedInputMessaging": "string", + "blockedOutputsMessaging": "string", + "contentPolicy": {}, + "createdAt": "2024-06-12T18:31:45Z", + "description": "string", + "guardrailArn": "string", + "guardrailId": "guardrailId", + "kmsKeyArn": "string", + "name": "string", + "sensitiveInformationPolicy": {}, + "status": "READY", + "topicPolicy": { + "topics": [ + { + "definition": "string", + "examples": [ "string" ], + "name": "string", + "type": "string" + } + ] + }, + "updatedAt": "2024-06-12T18:31:48Z", + "version": "DRAFT", + "wordPolicy": {} + } + """ + "AWSBedrockAgent" | "GetAgent" | "GET" | "/" | AWSBedrockAgentClientBuilder.standard() | { c -> c.getAgent(new GetAgentRequest().withAgentId("agentId")) } | ["aws.bedrock.agent.id": "agentId"] | "" + "AWSBedrockAgent" | "GetKnowledgeBase" | "GET" | "/" | AWSBedrockAgentClientBuilder.standard() | { c -> c.getKnowledgeBase(new GetKnowledgeBaseRequest().withKnowledgeBaseId("knowledgeBaseId")) } | ["aws.bedrock.knowledgebase.id": "knowledgeBaseId"] | "" + "AWSBedrockAgent" | "GetDataSource" | "GET" | "/" | AWSBedrockAgentClientBuilder.standard() | { c -> c.getDataSource(new GetDataSourceRequest().withDataSourceId("datasourceId").withKnowledgeBaseId("knowledgeBaseId")) } | ["aws.bedrock.datasource.id": "datasourceId"] | "" + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | AmazonBedrockRuntimeClientBuilder.standard() | + { c -> c.invokeModel( + new InvokeModelRequest().withModelId("anthropic.claude-v2").withBody(StandardCharsets.UTF_8.encode( + "{\"prompt\":\"Hello, world!\",\"temperature\":0.7,\"top_p\":0.9,\"max_tokens_to_sample\":100}\n" + ))) } | ["gen_ai.request.model": "anthropic.claude-v2", "gen_ai.system": "aws_bedrock"] | """ + { + "completion": " Here is a simple explanation of black ", + "stop_reason": "length", + "stop": "holes" + } + """ } def "send #operation request to closed port"() {