Skip to content

Commit

Permalink
support bedrock and bedrock runtime resources Java SDK V2(open-teleme…
Browse files Browse the repository at this point in the history
…try#5)

This PR add AWS Bedrock and BedrockRuntime support for AWS Java SDK V2 with the following change:

A. **Bedrock**:
Extract `guardrailId` from API response, and add into `"aws.bedrock.guardrail.id"` span attribute.

B. **Bedrock Agent**:
Extract `agentId` from both API request and response, and add into `"aws.bedrock.agent.id"` span attribute.
Extract `knowledgeBaseId` from API request, and add into `"aws.bedrock.knowledgebase.id"` span attribute.
Extract `dataSourceId` from both API request and response,, and add into `"aws.bedrock.datasource.id"` span attribute.

The instrumentation is on API operation level, we make sure only one attribute is extracted per API call, there will be no overlap/conflict  to identify the resouce.

C. **Bedrock Agent Runtime**:
Extract `agentId` from API request, and add into `"aws.bedrock.agent.id"` span attribute.
Extract `knowledgeBaseId` from API request, and add into `"aws.bedrock.knowledgebase.id"` span attribute.

D. **Bedrock Runtime**:
Extract the following attributes and add into span according to [ Gen AI semantic-conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/gen-ai.md):

```
gen_ai.request.model
gen_ai.system
```
  • Loading branch information
mxiamxia authored Jul 9, 2024
1 parent 359d60f commit debb9be
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.awssdk.v2_2;

import static io.opentelemetry.api.common.AttributeKey.stringKey;

import io.opentelemetry.api.common.AttributeKey;

final class AwsExperimentalAttributes {
static final AttributeKey<String> AWS_BUCKET_NAME = stringKey("aws.bucket.name");
static final AttributeKey<String> AWS_QUEUE_URL = stringKey("aws.queue.url");
static final AttributeKey<String> AWS_QUEUE_NAME = stringKey("aws.queue.name");
static final AttributeKey<String> AWS_STREAM_NAME = stringKey("aws.stream.name");
static final AttributeKey<String> AWS_TABLE_NAME = stringKey("aws.table.name");
static final AttributeKey<String> AWS_BEDROCK_GUARDRAIL_ID =
stringKey("aws.bedrock.guardrail.id");
static final AttributeKey<String> AWS_BEDROCK_AGENT_ID = stringKey("aws.bedrock.agent.id");
static final AttributeKey<String> AWS_BEDROCK_DATASOURCE_ID =
stringKey("aws.bedrock.data_source.id");
static final AttributeKey<String> AWS_BEDROCK_KNOWLEDGEBASE_ID =
stringKey("aws.bedrock.knowledge_base.id");

// TODO: Merge in gen_ai attributes in opentelemetry-semconv-incubating once upgrade to v1.26.0
static final AttributeKey<String> GEN_AI_MODEL = stringKey("gen_ai.request.model");
static final AttributeKey<String> GEN_AI_SYSTEM = stringKey("gen_ai.system");

private AwsExperimentalAttributes() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

package io.opentelemetry.instrumentation.awssdk.v2_2;

import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCK;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKAGENTOPERATION;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKDATASOURCEOPERATION;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKKNOWLEDGEBASEOPERATION;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKRUNTIME;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.DYNAMODB;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.KINESIS;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.S3;
Expand Down Expand Up @@ -32,6 +37,45 @@ enum AwsSdkRequest {
S3Request(S3, "S3Request"),
SqsRequest(SQS, "SqsRequest"),
KinesisRequest(KINESIS, "KinesisRequest"),
BedrockRequest(BEDROCK, "BedrockRequest"),
BedrockAgentRuntimeRequest(BEDROCKAGENTOPERATION, "BedrockAgentRuntimeRequest"),
BedrockRuntimeRequest(BEDROCKRUNTIME, "BedrockRuntimeRequest"),
// BedrockAgent API based requests. We only support operations that are related to
// Agent/DataSources/KnowledgeBases
// resources and the request/response context contains the resource ID.
BedrockCreateAgentActionGroupRequest(BEDROCKAGENTOPERATION, "CreateAgentActionGroupRequest"),
BedrockCreateAgentAliasRequest(BEDROCKAGENTOPERATION, "CreateAgentAliasRequest"),
BedrockDeleteAgentActionGroupRequest(BEDROCKAGENTOPERATION, "DeleteAgentActionGroupRequest"),
BedrockDeleteAgentAliasRequest(BEDROCKAGENTOPERATION, "DeleteAgentAliasRequest"),
BedrockDeleteAgentVersionRequest(BEDROCKAGENTOPERATION, "DeleteAgentVersionRequest"),
BedrockGetAgentActionGroupRequest(BEDROCKAGENTOPERATION, "GetAgentActionGroupRequest"),
BedrockGetAgentAliasRequest(BEDROCKAGENTOPERATION, "GetAgentAliasRequest"),
BedrockGetAgentRequest(BEDROCKAGENTOPERATION, "GetAgentRequest"),
BedrockGetAgentVersionRequest(BEDROCKAGENTOPERATION, "GetAgentVersionRequest"),
BedrockListAgentActionGroupsRequest(BEDROCKAGENTOPERATION, "ListAgentActionGroupsRequest"),
BedrockListAgentAliasesRequest(BEDROCKAGENTOPERATION, "ListAgentAliasesRequest"),
BedrockListAgentKnowledgeBasesRequest(BEDROCKAGENTOPERATION, "ListAgentKnowledgeBasesRequest"),
BedrocListAgentVersionsRequest(BEDROCKAGENTOPERATION, "ListAgentVersionsRequest"),
BedrockPrepareAgentRequest(BEDROCKAGENTOPERATION, "PrepareAgentRequest"),
BedrockUpdateAgentActionGroupRequest(BEDROCKAGENTOPERATION, "UpdateAgentActionGroupRequest"),
BedrockUpdateAgentAliasRequest(BEDROCKAGENTOPERATION, "UpdateAgentAliasRequest"),
BedrockUpdateAgentRequest(BEDROCKAGENTOPERATION, "UpdateAgentRequest"),
BedrockBedrockAgentRequest(BEDROCKAGENTOPERATION, "BedrockAgentRequest"),
BedrockDeleteDataSourceRequest(BEDROCKDATASOURCEOPERATION, "DeleteDataSourceRequest"),
BedrockGetDataSourceRequest(BEDROCKDATASOURCEOPERATION, "GetDataSourceRequest"),
BedrockUpdateDataSourceRequest(BEDROCKDATASOURCEOPERATION, "UpdateDataSourceRequest"),
BedrocAssociateAgentKnowledgeBaseRequest(
BEDROCKKNOWLEDGEBASEOPERATION, "AssociateAgentKnowledgeBaseRequest"),
BedrockCreateDataSourceRequest(BEDROCKKNOWLEDGEBASEOPERATION, "CreateDataSourceRequest"),
BedrockDeleteKnowledgeBaseRequest(BEDROCKKNOWLEDGEBASEOPERATION, "DeleteKnowledgeBaseRequest"),
BedrockDisassociateAgentKnowledgeBaseRequest(
BEDROCKKNOWLEDGEBASEOPERATION, "DisassociateAgentKnowledgeBaseRequest"),
BedrockGetAgentKnowledgeBaseRequest(
BEDROCKKNOWLEDGEBASEOPERATION, "GetAgentKnowledgeBaseRequest"),
BedrockGetKnowledgeBaseRequest(BEDROCKKNOWLEDGEBASEOPERATION, "GetKnowledgeBaseRequest"),
BedrockListDataSourcesRequest(BEDROCKKNOWLEDGEBASEOPERATION, "ListDataSourcesRequest"),
BedrockUpdateAgentKnowledgeBaseRequest(
BEDROCKKNOWLEDGEBASEOPERATION, "UpdateAgentKnowledgeBaseRequest"),
// specific requests
BatchGetItem(
DYNAMODB,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,39 @@

package io.opentelemetry.instrumentation.awssdk.v2_2;

import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_BEDROCK_AGENT_ID;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_BEDROCK_DATASOURCE_ID;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_BEDROCK_GUARDRAIL_ID;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_BEDROCK_KNOWLEDGEBASE_ID;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_BUCKET_NAME;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_QUEUE_NAME;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_QUEUE_URL;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_STREAM_NAME;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_TABLE_NAME;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_MODEL;
import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.request;
import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.response;

import java.util.Collections;
import java.util.List;
import java.util.Map;

enum AwsSdkRequestType {
S3(request("aws.bucket.name", "Bucket")),
SQS(request("aws.queue.url", "QueueUrl"), request("aws.queue.name", "QueueName")),
KINESIS(request("aws.stream.name", "StreamName")),
DYNAMODB(request("aws.table.name", "TableName"));
S3(request(AWS_BUCKET_NAME.getKey(), "Bucket")),
SQS(request(AWS_QUEUE_URL.getKey(), "QueueUrl"), request(AWS_QUEUE_NAME.getKey(), "QueueName")),
KINESIS(request(AWS_STREAM_NAME.getKey(), "StreamName")),
DYNAMODB(request(AWS_TABLE_NAME.getKey(), "TableName")),
BEDROCK(request(AWS_BEDROCK_GUARDRAIL_ID.getKey(), "guardrailIdentifier")),
BEDROCKAGENTOPERATION(
request(AWS_BEDROCK_AGENT_ID.getKey(), "agentId"),
response(AWS_BEDROCK_AGENT_ID.getKey(), "agentId")),
BEDROCKDATASOURCEOPERATION(
request(AWS_BEDROCK_DATASOURCE_ID.getKey(), "dataSourceId"),
response(AWS_BEDROCK_DATASOURCE_ID.getKey(), "dataSourceId")),
BEDROCKKNOWLEDGEBASEOPERATION(
request(AWS_BEDROCK_KNOWLEDGEBASE_ID.getKey(), "knowledgeBaseId"),
response(AWS_BEDROCK_KNOWLEDGEBASE_ID.getKey(), "knowledgeBaseId")),
BEDROCKRUNTIME(request(GEN_AI_MODEL.getKey(), "modelId"));

// Wrapping in unmodifiableMap
@SuppressWarnings("ImmutableEnumChecker")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package io.opentelemetry.instrumentation.awssdk.v2_2;

import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_SYSTEM;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKRUNTIME;
import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.DYNAMODB;

import io.opentelemetry.api.common.AttributeKey;
Expand Down Expand Up @@ -42,6 +44,7 @@

/** AWS request execution interceptor. */
final class TracingExecutionInterceptor implements ExecutionInterceptor {
private static final String GEN_AI_SYSTEM_BEDROCK = "aws_bedrock";

// the class name is part of the attribute name, so that it will be shaded when used in javaagent
// instrumentation, and won't conflict with usage outside javaagent instrumentation
Expand Down Expand Up @@ -317,6 +320,10 @@ private void populateRequestAttributes(
span.setAttribute(SemanticAttributes.DB_OPERATION, operation);
}
}

if (awsSdkRequest.type() == BEDROCKRUNTIME) {
span.setAttribute(GEN_AI_SYSTEM, GEN_AI_SYSTEM_BEDROCK);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,19 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
"$SemanticAttributes.MESSAGING_SYSTEM" "AmazonSQS"
} else if (service == "Kinesis") {
"aws.stream.name" "somestream"
} else if (service == "Bedrock" && operation == "GetGuardrail") {
"aws.bedrock.guardrail.id" "guardrailId"
} else if (service == "BedrockAgent" && operation == "GetAgent") {
"aws.bedrock.agent.id" "agentId"
} else if (service == "BedrockAgent" && operation == "GetKnowledgeBase") {
"aws.bedrock.knowledge_base.id" "knowledgeBaseId"
} else if (service == "BedrockAgent" && operation == "GetDataSource") {
"aws.bedrock.data_source.id" "datasourceId"
} else if (service == "BedrockRuntime" && operation == "InvokeModel") {
"gen_ai.request.model" "meta.llama2-13b-chat-v1"
"gen_ai.system" "aws_bedrock"
}

}
}
}
Expand Down

0 comments on commit debb9be

Please sign in to comment.