diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/package.json b/aws-distro-opentelemetry-node-autoinstrumentation/package.json
index 6cbd8cac..195a8e70 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/package.json
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/package.json
@@ -38,6 +38,10 @@
"url": "https://github.com/aws-observability/aws-otel-js-instrumentation/issues"
},
"devDependencies": {
+ "@aws-sdk/client-bedrock": "3.632.0",
+ "@aws-sdk/client-bedrock-agent": "3.632.0",
+ "@aws-sdk/client-bedrock-agent-runtime": "3.632.0",
+ "@aws-sdk/client-bedrock-runtime": "3.632.0",
"@aws-sdk/client-kinesis": "3.632.0",
"@aws-sdk/client-s3": "3.632.0",
"@aws-sdk/client-sqs": "3.632.0",
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-attribute-keys.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-attribute-keys.ts
index 53ee92a7..e2378272 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-attribute-keys.ts
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-attribute-keys.ts
@@ -31,4 +31,8 @@ export const AWS_ATTRIBUTE_KEYS: { [key: string]: string } = {
AWS_SQS_QUEUE_NAME: 'aws.sqs.queue.name',
AWS_KINESIS_STREAM_NAME: 'aws.kinesis.stream.name',
AWS_DYNAMODB_TABLE_NAMES: SEMATTRS_AWS_DYNAMODB_TABLE_NAMES,
+ AWS_BEDROCK_DATA_SOURCE_ID: 'aws.bedrock.data_source.id',
+ AWS_BEDROCK_KNOWLEDGE_BASE_ID: 'aws.bedrock.knowledge_base.id',
+ AWS_BEDROCK_AGENT_ID: 'aws.bedrock.agent.id',
+ AWS_BEDROCK_GUARDRAIL_ID: 'aws.bedrock.guardrail.id',
};
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-metric-attribute-generator.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-metric-attribute-generator.ts
index daf90d7a..e58b600d 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-metric-attribute-generator.ts
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-metric-attribute-generator.ts
@@ -55,6 +55,8 @@ const NORMALIZED_DYNAMO_DB_SERVICE_NAME: string = 'AWS::DynamoDB';
const NORMALIZED_KINESIS_SERVICE_NAME: string = 'AWS::Kinesis';
const NORMALIZED_S3_SERVICE_NAME: string = 'AWS::S3';
const NORMALIZED_SQS_SERVICE_NAME: string = 'AWS::SQS';
+const NORMALIZED_BEDROCK_SERVICE_NAME: string = 'AWS::Bedrock';
+const NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME: string = 'AWS::BedrockRuntime';
const DB_CONNECTION_RESOURCE_TYPE: string = 'DB::Connection';
// As per https://opentelemetry.io/docs/specs/semconv/resource/#service, if service name is not specified, SDK defaults
@@ -317,10 +319,19 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
* Cloud Control resource format as much as possible, with special attention to services we
* can detect remote resource information for. Long term, we would like to normalize service name
* in the upstream.
+ *
+ * For Bedrock, Bedrock Agent, and Bedrock Agent Runtime, we can align with AWS Cloud Control and use
+ * AWS::Bedrock for RemoteService. For BedrockRuntime, we are using AWS::BedrockRuntime
+ * as the associated remote resource (Model) is not listed in Cloud Control.
*/
private static normalizeRemoteServiceName(span: ReadableSpan, serviceName: string): string {
if (AwsSpanProcessingUtil.isAwsSDKSpan(span)) {
- return 'AWS::' + serviceName;
+ const awsSdkServiceMapping: { [key: string]: string } = {
+ BedrockAgent: NORMALIZED_BEDROCK_SERVICE_NAME,
+ BedrockAgentRuntime: NORMALIZED_BEDROCK_SERVICE_NAME,
+ BedrockRuntime: NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME,
+ };
+ return awsSdkServiceMapping[serviceName] || 'AWS::' + serviceName;
}
return serviceName;
}
@@ -369,6 +380,31 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
remoteResourceIdentifier = SqsUrlParser.getQueueName(
AwsMetricAttributeGenerator.escapeDelimiters(span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL])
);
+ } else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID)) {
+ remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Agent';
+ remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
+ span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]
+ );
+ } else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID)) {
+ remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::DataSource';
+ remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
+ span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]
+ );
+ } else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID)) {
+ remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Guardrail';
+ remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
+ span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID]
+ );
+ } else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID)) {
+ remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::KnowledgeBase';
+ remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
+ span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]
+ );
+ } else if (AwsSpanProcessingUtil.isKeyPresent(span, AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL)) {
+ remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Model';
+ remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
+ span.attributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL]
+ );
}
} else if (AwsSpanProcessingUtil.isDBSpan(span)) {
remoteResourceType = DB_CONNECTION_RESOURCE_TYPE;
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-processing-util.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-processing-util.ts
index 72974e79..d67a5d5c 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-processing-util.ts
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-processing-util.ts
@@ -38,6 +38,10 @@ export class AwsSpanProcessingUtil {
static MAX_KEYWORD_LENGTH: number = 27;
static SQL_DIALECT_PATTERN: string = '^(?:' + AwsSpanProcessingUtil.getDialectKeywords().join('|') + ')\\b';
+ // TODO: Use Semantic Conventions once upgraded
+ static GEN_AI_REQUEST_MODEL: string = 'gen_ai.request.model';
+ static GEN_AI_SYSTEM: string = 'gen_ai.system';
+
static getDialectKeywords(): string[] {
return SQL_DIALECT_KEYWORDS_JSON.keywords;
}
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/aws/services/bedrock.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/aws/services/bedrock.ts
new file mode 100644
index 00000000..ffeafacd
--- /dev/null
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/aws/services/bedrock.ts
@@ -0,0 +1,221 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { Attributes, DiagLogger, Span, SpanKind, Tracer } from '@opentelemetry/api';
+import {
+ AwsSdkInstrumentationConfig,
+ NormalizedRequest,
+ NormalizedResponse,
+} from '@opentelemetry/instrumentation-aws-sdk';
+import { AWS_ATTRIBUTE_KEYS } from '../../../aws-attribute-keys';
+import { RequestMetadata, ServiceExtension } from '../../../third-party/otel/aws/services/ServiceExtension';
+import { AwsSpanProcessingUtil } from '../../../aws-span-processing-util';
+
+const AGENT_ID: string = 'agentId';
+const KNOWLEDGE_BASE_ID: string = 'knowledgeBaseId';
+const DATA_SOURCE_ID: string = 'dataSourceId';
+const GUARDRAIL_ID: string = 'guardrailId';
+const MODEL_ID: string = 'modelId';
+const AWS_BEDROCK_SYSTEM: string = 'aws_bedrock';
+
+const AGENT_OPERATIONS = [
+ 'CreateAgentActionGroup',
+ 'CreateAgentAlias',
+ 'DeleteAgentActionGroup',
+ 'DeleteAgentAlias',
+ 'DeleteAgent',
+ 'DeleteAgentVersion',
+ 'GetAgentActionGroup',
+ 'GetAgentAlias',
+ 'GetAgent',
+ 'GetAgentVersion',
+ 'ListAgentActionGroups',
+ 'ListAgentAliases',
+ 'ListAgentKnowledgeBases',
+ 'ListAgentVersions',
+ 'PrepareAgent',
+ 'UpdateAgentActionGroup',
+ 'UpdateAgentAlias',
+ 'UpdateAgent',
+];
+
+const KNOWLEDGE_BASE_OPERATIONS = [
+ 'AssociateAgentKnowledgeBase',
+ 'CreateDataSource',
+ 'DeleteKnowledgeBase',
+ 'DisassociateAgentKnowledgeBase',
+ 'GetAgentKnowledgeBase',
+ 'GetKnowledgeBase',
+ 'ListDataSources',
+ 'UpdateAgentKnowledgeBase',
+];
+
+const DATA_SOURCE_OPERATIONS = ['DeleteDataSource', 'GetDataSource', 'UpdateDataSource'];
+
+// The following constants map the way we present the data in telemetry to how they appear in request/responses
+// e.g. we put `aws.bedrock.knowledge_base.id` into trace data by finding `knowledgeBaseId`
+const agentOperationAttributeKeyMapping = { [AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]: AGENT_ID };
+const knowledgeBaseOperationAttributeKeyMapping = {
+ [AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]: KNOWLEDGE_BASE_ID,
+};
+const dataSourceOperationAttributeKeyMapping = {
+ [AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]: DATA_SOURCE_ID,
+};
+
+// This map allows us to get all relevant attribute key mappings for a given operation
+const operationToBedrockAgentAttributesMap: { [key: string]: { [key: string]: string } } = {};
+for (const operation of AGENT_OPERATIONS) {
+ operationToBedrockAgentAttributesMap[operation] = agentOperationAttributeKeyMapping;
+}
+for (const operation of KNOWLEDGE_BASE_OPERATIONS) {
+ operationToBedrockAgentAttributesMap[operation] = knowledgeBaseOperationAttributeKeyMapping;
+}
+for (const operation of DATA_SOURCE_OPERATIONS) {
+ operationToBedrockAgentAttributesMap[operation] = dataSourceOperationAttributeKeyMapping;
+}
+
+// This class is an extension for
+// Agents for Amazon Bedrock.
+// This class primarily identify three types of resource based operations: AGENT_OPERATIONS,
+// KNOWLEDGE_BASE_OPERATIONS, and DATA_SOURCE_OPERATIONS. We only support operations that are related to
+// the resource and where the context contains the resource ID.
+export class BedrockAgentServiceExtension implements ServiceExtension {
+ requestPreSpanHook(
+ request: NormalizedRequest,
+ config: AwsSdkInstrumentationConfig,
+ diag: DiagLogger
+ ): RequestMetadata {
+ const spanAttributes: Attributes = {};
+ const isIncoming = false;
+ const spanKind: SpanKind = SpanKind.CLIENT;
+ let spanName: string | undefined;
+
+ const operation: string = request.commandName;
+ if (operation && operationToBedrockAgentAttributesMap[operation]) {
+ const bedrockAgentServiceInfo = operationToBedrockAgentAttributesMap[operation];
+ for (const serviceInfo of Object.entries(bedrockAgentServiceInfo)) {
+ const [attributeKey, requestParamKey] = serviceInfo;
+ const requestParamValue = request.commandInput?.[requestParamKey];
+
+ if (requestParamValue) {
+ spanAttributes[attributeKey] = requestParamValue;
+ }
+ }
+ }
+
+ return {
+ isIncoming,
+ spanAttributes,
+ spanKind,
+ spanName,
+ };
+ }
+
+ responseHook(response: NormalizedResponse, span: Span, tracer: Tracer, config: AwsSdkInstrumentationConfig): void {
+ const operation: string = response.request.commandName;
+ if (operation && operationToBedrockAgentAttributesMap[operation]) {
+ const bedrockAgentServiceInfo = operationToBedrockAgentAttributesMap[operation];
+ for (const serviceInfo of Object.entries(bedrockAgentServiceInfo)) {
+ const [attributeKey, responseParamKey] = serviceInfo;
+ const responseParamValue = response.data[responseParamKey];
+
+ if (responseParamValue) {
+ span.setAttribute(attributeKey, responseParamValue);
+ }
+ }
+ }
+ }
+}
+
+// This class is an extension for
+// Agents for Amazon Bedrock Runtime.
+export class BedrockAgentRuntimeServiceExtension implements ServiceExtension {
+ requestPreSpanHook(
+ request: NormalizedRequest,
+ config: AwsSdkInstrumentationConfig,
+ diag: DiagLogger
+ ): RequestMetadata {
+ const spanAttributes: Attributes = {};
+ const isIncoming = false;
+ const spanKind: SpanKind = SpanKind.CLIENT;
+ let spanName: string | undefined;
+
+ const agentId = request.commandInput?.[AGENT_ID];
+ const knowledgeBaseId = request.commandInput?.[KNOWLEDGE_BASE_ID];
+
+ if (agentId) {
+ spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID] = agentId;
+ }
+ if (knowledgeBaseId) {
+ spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID] = knowledgeBaseId;
+ }
+
+ return {
+ isIncoming,
+ spanAttributes,
+ spanKind,
+ spanName,
+ };
+ }
+}
+
+// This class is an extension for Bedrock.
+export class BedrockServiceExtension implements ServiceExtension {
+ // Must be implemented, returning empty metadata
+ requestPreSpanHook(
+ request: NormalizedRequest,
+ config: AwsSdkInstrumentationConfig,
+ diag: DiagLogger
+ ): RequestMetadata {
+ const spanAttributes: Attributes = {};
+ const isIncoming = false;
+ const spanKind: SpanKind = SpanKind.CLIENT;
+ let spanName: string | undefined;
+ return {
+ isIncoming,
+ spanAttributes,
+ spanKind,
+ spanName,
+ };
+ }
+ responseHook(response: NormalizedResponse, span: Span, tracer: Tracer, config: AwsSdkInstrumentationConfig): void {
+ const guardrail_id = response.data[GUARDRAIL_ID];
+
+ if (guardrail_id) {
+ span.setAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, guardrail_id);
+ }
+ }
+}
+
+// This class is an extension for
+// Amazon Bedrock Runtime.
+export class BedrockRuntimeServiceExtension implements ServiceExtension {
+ requestPreSpanHook(
+ request: NormalizedRequest,
+ config: AwsSdkInstrumentationConfig,
+ diag: DiagLogger
+ ): RequestMetadata {
+ const spanAttributes: Attributes = {};
+ const isIncoming = false;
+ const spanKind: SpanKind = SpanKind.CLIENT;
+ let spanName: string | undefined;
+
+ const modelId = request.commandInput?.[MODEL_ID];
+
+ spanAttributes[AwsSpanProcessingUtil.GEN_AI_SYSTEM] = AWS_BEDROCK_SYSTEM;
+ if (modelId) {
+ spanAttributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL] = modelId;
+ }
+
+ return {
+ isIncoming,
+ spanAttributes,
+ spanKind,
+ spanName,
+ };
+ }
+}
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/instrumentation-patch.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/instrumentation-patch.ts
index 47ba01c4..776d4c3d 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/instrumentation-patch.ts
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/patches/instrumentation-patch.ts
@@ -18,6 +18,12 @@ import { AWSXRAY_TRACE_ID_HEADER, AWSXRayPropagator } from '@opentelemetry/propa
import { APIGatewayProxyEventHeaders, Context } from 'aws-lambda';
import { AWS_ATTRIBUTE_KEYS } from '../aws-attribute-keys';
import { RequestMetadata } from '../third-party/otel/aws/services/ServiceExtension';
+import {
+ BedrockAgentRuntimeServiceExtension,
+ BedrockAgentServiceExtension,
+ BedrockRuntimeServiceExtension,
+ BedrockServiceExtension,
+} from './aws/services/bedrock';
import { KinesisServiceExtension } from './aws/services/kinesis';
import { S3ServiceExtension } from './aws/services/s3';
@@ -51,6 +57,10 @@ export function applyInstrumentationPatches(instrumentations: Instrumentation[])
if (services) {
services.set('S3', new S3ServiceExtension());
services.set('Kinesis', new KinesisServiceExtension());
+ services.set('Bedrock', new BedrockServiceExtension());
+ services.set('BedrockAgent', new BedrockAgentServiceExtension());
+ services.set('BedrockAgentRuntime', new BedrockAgentRuntimeServiceExtension());
+ services.set('BedrockRuntime', new BedrockRuntimeServiceExtension());
patchSqsServiceExtension(services.get('SQS'));
}
} else if (instrumentation.instrumentationName === '@opentelemetry/instrumentation-aws-lambda') {
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-metric-attribute-generator.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-metric-attribute-generator.test.ts
index 69e24423..e74eda35 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-metric-attribute-generator.test.ts
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-metric-attribute-generator.test.ts
@@ -33,6 +33,7 @@ import { expect } from 'expect';
import { AWS_ATTRIBUTE_KEYS } from '../src/aws-attribute-keys';
import { AwsMetricAttributeGenerator } from '../src/aws-metric-attribute-generator';
import { AttributeMap, DEPENDENCY_METRIC, SERVICE_METRIC } from '../src/metric-attribute-generator';
+import { AwsSpanProcessingUtil } from '../src/aws-span-processing-util';
// Does not exist in @opentelemetry/semantic-conventions
const _SERVER_SOCKET_ADDRESS: string = 'server.socket.address';
@@ -784,6 +785,56 @@ describe('AwsMetricAttributeGeneratorTest', () => {
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES, ['aws_table^name']);
validateRemoteResourceAttributes('AWS::DynamoDB::Table', 'aws_table^^name');
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_AGENT_ID attribute, then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID, 'test_agent_id');
+ validateRemoteResourceAttributes('AWS::Bedrock::Agent', 'test_agent_id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_AGENT_ID attribute with special chars(^), then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID, 'test_agent_^id');
+ validateRemoteResourceAttributes('AWS::Bedrock::Agent', 'test_agent_^^id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_DATA_SOURCE_ID attribute, then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID, 'test_datasource_id');
+ validateRemoteResourceAttributes('AWS::Bedrock::DataSource', 'test_datasource_id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_DATA_SOURCE_ID attribute with special chars(^), then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID, 'test_datasource_^id');
+ validateRemoteResourceAttributes('AWS::Bedrock::DataSource', 'test_datasource_^^id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_GUARDRAIL_ID attribute, then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, 'test_guardrail_id');
+ validateRemoteResourceAttributes('AWS::Bedrock::Guardrail', 'test_guardrail_id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_GUARDRAIL_ID attribute with special chars(^), then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, 'test_guardrail_^id');
+ validateRemoteResourceAttributes('AWS::Bedrock::Guardrail', 'test_guardrail_^^id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_KNOWLEDGE_BASE_ID attribute, then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID, 'test_knowledgeBase_id');
+ validateRemoteResourceAttributes('AWS::Bedrock::KnowledgeBase', 'test_knowledgeBase_id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID, undefined);
+
+ // Validate behaviour of AWS_BEDROCK_KNOWLEDGE_BASE_ID attribute with special chars(^), then remove it.
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID, 'test_knowledgeBase_^id');
+ validateRemoteResourceAttributes('AWS::Bedrock::KnowledgeBase', 'test_knowledgeBase_^^id');
+ mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID, undefined);
+
+ // Validate behaviour of GEN_AI_REQUEST_MODEL attribute, then remove it.
+ mockAttribute(AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL, 'test.service_id');
+ validateRemoteResourceAttributes('AWS::Bedrock::Model', 'test.service_id');
+ mockAttribute(AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL, undefined);
+
+ // Validate behaviour of GEN_AI_REQUEST_MODEL attribute with special chars(^), then remove it.
+ mockAttribute(AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL, 'test.service_^id');
+ validateRemoteResourceAttributes('AWS::Bedrock::Model', 'test.service_^^id');
+ mockAttribute(AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL, undefined);
});
it('testDBClientSpanWithRemoteResourceAttributes', () => {
@@ -1116,6 +1167,10 @@ describe('AwsMetricAttributeGeneratorTest', () => {
testAwsSdkServiceNormalization('Kinesis', 'AWS::Kinesis');
testAwsSdkServiceNormalization('S3', 'AWS::S3');
testAwsSdkServiceNormalization('SQS', 'AWS::SQS');
+ testAwsSdkServiceNormalization('Bedrock', 'AWS::Bedrock');
+ testAwsSdkServiceNormalization('BedrockAgent', 'AWS::Bedrock');
+ testAwsSdkServiceNormalization('BedrockAgentRuntime', 'AWS::Bedrock');
+ testAwsSdkServiceNormalization('BedrockRuntime', 'AWS::BedrockRuntime');
});
function testAwsSdkServiceNormalization(serviceName: string, expectedRemoteService: string): void {
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/aws/services/bedrock.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/aws/services/bedrock.test.ts
new file mode 100644
index 00000000..23edc001
--- /dev/null
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/aws/services/bedrock.test.ts
@@ -0,0 +1,308 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { getTestSpans, registerInstrumentationTesting } from '@opentelemetry/contrib-test-utils';
+import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';
+import { applyInstrumentationPatches } from './../../../../src/patches/instrumentation-patch';
+
+const instrumentations: AwsInstrumentation[] = [new AwsInstrumentation()];
+applyInstrumentationPatches(instrumentations);
+registerInstrumentationTesting(instrumentations[0]);
+
+import { Bedrock } from '@aws-sdk/client-bedrock';
+import { BedrockAgent } from '@aws-sdk/client-bedrock-agent';
+import { BedrockAgentRuntime } from '@aws-sdk/client-bedrock-agent-runtime';
+import { BedrockRuntime } from '@aws-sdk/client-bedrock-runtime';
+import * as nock from 'nock';
+
+import { SpanKind } from '@opentelemetry/api';
+import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
+import { expect } from 'expect';
+import { AWS_ATTRIBUTE_KEYS } from '../../../../src/aws-attribute-keys';
+import { AwsSpanProcessingUtil } from '../../../../src/aws-span-processing-util';
+
+// This file's contents are being contributed to upstream
+// - https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2361
+
+const region = 'us-east-1';
+
+describe('BedrockAgent', () => {
+ let bedrock: BedrockAgent;
+ beforeEach(() => {
+ bedrock = new BedrockAgent({
+ region: region,
+ credentials: {
+ accessKeyId: 'abcde',
+ secretAccessKey: 'abcde',
+ },
+ });
+ });
+
+ describe('GetPrompt', () => {
+ it('adds no info to span', async () => {
+ const dummyPromptName: string = 'dummy-prompt-name';
+
+ nock(`https://bedrock-agent.${region}.amazonaws.com`)
+ .get(`/prompts/${dummyPromptName}`)
+ .reply(200, { promptIdentifier: dummyPromptName });
+
+ await bedrock.getPrompt({ promptIdentifier: dummyPromptName }).catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const getPromptSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockAgent.GetPrompt';
+ });
+ expect(getPromptSpans.length).toBe(1);
+ const getPromptSpan = getPromptSpans[0];
+ expect(getPromptSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBeUndefined();
+ expect(getPromptSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBeUndefined();
+ expect(getPromptSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(getPromptSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+
+ describe('GetAgent', () => {
+ it('adds agentId to span', async () => {
+ const dummyAgentId: string = 'ABCDEFGH';
+
+ nock(`https://bedrock-agent.${region}.amazonaws.com`)
+ .get(`/agents/${dummyAgentId}`)
+ .reply(200, {
+ agentId: dummyAgentId,
+ request: {
+ operation: 'GetAgent',
+ },
+ });
+
+ await bedrock.getAgent({ agentId: dummyAgentId }).catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const getAgentSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockAgent.GetAgent';
+ });
+ expect(getAgentSpans.length).toBe(1);
+ const getAgentSpan = getAgentSpans[0];
+ expect(getAgentSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBe(dummyAgentId);
+ expect(getAgentSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBeUndefined();
+ expect(getAgentSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(getAgentSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+
+ describe('GetKnowledgeBase', () => {
+ it('adds knowledgeBaseId to span', async () => {
+ const dummyKnowledgeBaseId: string = 'ABCDEFGH';
+
+ nock(`https://bedrock-agent.${region}.amazonaws.com`)
+ .get(`/knowledgebases/${dummyKnowledgeBaseId}`)
+ .reply(200, { knowledgeBaseId: dummyKnowledgeBaseId });
+
+ await bedrock.getKnowledgeBase({ knowledgeBaseId: dummyKnowledgeBaseId }).catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const getKnowledgeBaseSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockAgent.GetKnowledgeBase';
+ });
+ expect(getKnowledgeBaseSpans.length).toBe(1);
+ const getKnowledgeBaseSpan = getKnowledgeBaseSpans[0];
+ expect(getKnowledgeBaseSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBeUndefined();
+ expect(getKnowledgeBaseSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBe(
+ dummyKnowledgeBaseId
+ );
+ expect(getKnowledgeBaseSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(getKnowledgeBaseSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+
+ describe('GetDataSource', () => {
+ it('adds dataSourceId to span', async () => {
+ const dummyDataSourceId: string = 'ABCDEFGH';
+ const dummyKnowledgeBaseId: string = 'HGFEDCBA';
+
+ nock(`https://bedrock-agent.${region}.amazonaws.com`)
+ .get(`/knowledgebases/${dummyKnowledgeBaseId}/datasources/${dummyDataSourceId}`)
+ .reply(200, { dataSourceId: dummyDataSourceId, knowledgeBaseId: dummyKnowledgeBaseId });
+
+ await bedrock
+ .getDataSource({ dataSourceId: dummyDataSourceId, knowledgeBaseId: dummyKnowledgeBaseId })
+ .catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const getDataSourceSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockAgent.GetDataSource';
+ });
+ expect(getDataSourceSpans.length).toBe(1);
+ const getDataSourceSpan = getDataSourceSpans[0];
+ expect(getDataSourceSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBeUndefined();
+ expect(getDataSourceSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBeUndefined();
+ expect(getDataSourceSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBe(dummyDataSourceId);
+ expect(getDataSourceSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+});
+
+describe('BedrockAgentRuntime', () => {
+ let bedrock: BedrockAgentRuntime;
+ beforeEach(() => {
+ bedrock = new BedrockAgentRuntime({
+ region: region,
+ credentials: {
+ accessKeyId: 'abcde',
+ secretAccessKey: 'abcde',
+ },
+ });
+ });
+
+ describe('Retrieve', () => {
+ it('adds knowledgeBaseId to span', async () => {
+ const dummyKnowledgeBaseId: string = 'ABCDEFGH';
+ const dummyQuery: string = 'dummy-query';
+
+ nock(`https://bedrock-agent-runtime.${region}.amazonaws.com`)
+ .post(`/knowledgebases/${dummyKnowledgeBaseId}/retrieve`)
+ .reply(200, {
+ knowledgeBaseId: dummyKnowledgeBaseId,
+ retrievalQuery: { text: dummyQuery },
+ });
+
+ await bedrock
+ .retrieve({
+ knowledgeBaseId: dummyKnowledgeBaseId,
+ retrievalQuery: { text: dummyQuery },
+ })
+ .catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const retrieveSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockAgentRuntime.Retrieve';
+ });
+ expect(retrieveSpans.length).toBe(1);
+ const retrieveSpan = retrieveSpans[0];
+ expect(retrieveSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBeUndefined();
+ expect(retrieveSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBe(dummyKnowledgeBaseId);
+ expect(retrieveSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(retrieveSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+
+ describe('InvokeAgent', () => {
+ it('adds agentId to span', async () => {
+ const dummyAgentId: string = 'ABCDEFGH';
+ const dummyAgentAliasId: string = 'HGFEDCBA';
+ const dummySessionId: string = 'ABC123AB';
+
+ nock(`https://bedrock-agent-runtime.${region}.amazonaws.com`)
+ .post(`/agents/${dummyAgentId}/agentAliases/${dummyAgentAliasId}/sessions/${dummySessionId}/text`)
+ .reply(200, {
+ agentId: dummyAgentId,
+ agentAliasId: dummyAgentAliasId,
+ sessionId: dummySessionId,
+ });
+
+ await bedrock
+ .invokeAgent({
+ agentId: dummyAgentId,
+ agentAliasId: dummyAgentAliasId,
+ sessionId: dummySessionId,
+ })
+ .catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const invokeAgentSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockAgentRuntime.InvokeAgent';
+ });
+ expect(invokeAgentSpans.length).toBe(1);
+ const invokeAgentSpan = invokeAgentSpans[0];
+ expect(invokeAgentSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBe(dummyAgentId);
+ expect(invokeAgentSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBeUndefined();
+ expect(invokeAgentSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(invokeAgentSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+});
+
+describe('Bedrock', () => {
+ let bedrock: Bedrock;
+ beforeEach(() => {
+ bedrock = new Bedrock({
+ region: region,
+ credentials: {
+ accessKeyId: 'abcde',
+ secretAccessKey: 'abcde',
+ },
+ });
+ });
+
+ describe('GetGuardrail', () => {
+ it('adds guardrailId to span', async () => {
+ const dummyGuardrailIdentifier: string = 'ABCDEFGH';
+
+ nock(`https://bedrock.${region}.amazonaws.com`).get(`/guardrails/${dummyGuardrailIdentifier}`).reply(200, {
+ guardrailId: dummyGuardrailIdentifier,
+ });
+
+ await bedrock
+ .getGuardrail({
+ guardrailIdentifier: dummyGuardrailIdentifier,
+ })
+ .catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const getGuardrailSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'Bedrock.GetGuardrail';
+ });
+ expect(getGuardrailSpans.length).toBe(1);
+ const getGuardrailSpan = getGuardrailSpans[0];
+
+ expect(getGuardrailSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBeUndefined();
+ expect(getGuardrailSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBeUndefined();
+ expect(getGuardrailSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(getGuardrailSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID]).toBe(dummyGuardrailIdentifier);
+ expect(getGuardrailSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+});
+
+describe('BedrockRuntime', () => {
+ let bedrock: BedrockRuntime;
+ beforeEach(() => {
+ bedrock = new BedrockRuntime({
+ region: region,
+ credentials: {
+ accessKeyId: 'abcde',
+ secretAccessKey: 'abcde',
+ },
+ });
+ });
+
+ describe('InvokeModel', () => {
+ it('adds modelId to span', async () => {
+ const dummyModelId: string = 'ABCDEFGH';
+ const dummyBody: string = 'HGFEDCBA';
+
+ nock(`https://bedrock-runtime.${region}.amazonaws.com`).post(`/model/${dummyModelId}/invoke`).reply(200, {
+ modelId: dummyModelId,
+ body: dummyBody,
+ });
+
+ await bedrock
+ .invokeModel({
+ modelId: dummyModelId,
+ body: dummyBody,
+ })
+ .catch((err: any) => {});
+
+ const testSpans: ReadableSpan[] = getTestSpans();
+ const invokeModelSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
+ return s.name === 'BedrockRuntime.InvokeModel';
+ });
+ expect(invokeModelSpans.length).toBe(1);
+ const invokeModelSpan = invokeModelSpans[0];
+ expect(invokeModelSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toBeUndefined();
+ expect(invokeModelSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toBeUndefined();
+ expect(invokeModelSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]).toBeUndefined();
+ expect(invokeModelSpan.attributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_MODEL]).toBe(dummyModelId);
+ expect(invokeModelSpan.kind).toBe(SpanKind.CLIENT);
+ });
+ });
+});
diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/instrumentation-patch.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/instrumentation-patch.test.ts
index 0265b7da..385c7d75 100644
--- a/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/instrumentation-patch.test.ts
+++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/patches/instrumentation-patch.test.ts
@@ -1,10 +1,19 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
-import { Attributes, diag, Context as OtelContext, trace, propagation, Span } from '@opentelemetry/api';
+import {
+ Attributes,
+ diag,
+ Context as OtelContext,
+ trace,
+ propagation,
+ Span,
+ Tracer,
+ AttributeValue,
+} from '@opentelemetry/api';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { Instrumentation } from '@opentelemetry/instrumentation';
-import { AwsInstrumentation, NormalizedRequest } from '@opentelemetry/instrumentation-aws-sdk';
+import { AwsInstrumentation, NormalizedRequest, NormalizedResponse } from '@opentelemetry/instrumentation-aws-sdk';
import { AwsLambdaInstrumentation, AwsLambdaInstrumentationConfig } from '@opentelemetry/instrumentation-aws-lambda';
import { expect } from 'expect';
import { AWS_ATTRIBUTE_KEYS } from '../../src/aws-attribute-keys';
@@ -19,6 +28,12 @@ const _STREAM_NAME: string = 'streamName';
const _BUCKET_NAME: string = 'bucketName';
const _QUEUE_NAME: string = 'queueName';
const _QUEUE_URL: string = 'https://sqs.us-east-1.amazonaws.com/123412341234/queueName';
+const _BEDROCK_AGENT_ID: string = 'agentId';
+const _BEDROCK_DATASOURCE_ID: string = 'DataSourceId';
+const _BEDROCK_GUARDRAIL_ID: string = 'GuardrailId';
+const _BEDROCK_KNOWLEDGEBASE_ID: string = 'KnowledgeBaseId';
+const _GEN_AI_SYSTEM: string = 'aws_bedrock';
+const _GEN_AI_REQUEST_MODEL: string = 'genAiReuqestModelId';
const mockHeaders = {
'x-test-header': 'test-value',
@@ -45,6 +60,10 @@ describe('InstrumentationPatchTest', () => {
expect(services.has('Kinesis')).toBeFalsy();
expect(services.get('SQS')._requestPreSpanHook).toBeFalsy();
expect(services.get('SQS').requestPreSpanHook).toBeTruthy();
+ expect(services.has('Bedrock')).toBeFalsy();
+ expect(services.has('BedrockAgent')).toBeFalsy();
+ expect(services.get('BedrockAgentRuntime')).toBeFalsy();
+ expect(services.get('BedrockRuntime')).toBeFalsy();
});
it('PatchesAwsSdkInstrumentation', () => {
@@ -64,6 +83,10 @@ describe('InstrumentationPatchTest', () => {
expect(services.has('Kinesis')).toBeTruthy();
expect(services.get('SQS')._requestPreSpanHook).toBeTruthy();
expect(services.get('SQS').requestPreSpanHook).toBeTruthy();
+ expect(services.has('Bedrock')).toBeTruthy();
+ expect(services.has('BedrockAgent')).toBeTruthy();
+ expect(services.get('BedrockAgentRuntime')).toBeTruthy();
+ expect(services.get('BedrockRuntime')).toBeTruthy();
// Sanity check
expect(services.has('InvalidService')).toBeFalsy();
});
@@ -94,6 +117,12 @@ describe('InstrumentationPatchTest', () => {
expect(sqsAttributes[AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME]).toBeUndefined();
});
+ it('Bedrock without patching', () => {
+ const unpatchedAwsSdkInstrumentation: AwsInstrumentation = extractAwsSdkInstrumentation(UNPATCHED_INSTRUMENTATIONS);
+ const services: Map = extractServicesFromAwsSdkInstrumentation(unpatchedAwsSdkInstrumentation);
+ expect(() => doExtractBedrockAttributes(services, 'Bedrock')).toThrow();
+ });
+
it('S3 with patching', () => {
const patchedAwsSdkInstrumentation: AwsInstrumentation = extractAwsSdkInstrumentation(PATCHED_INSTRUMENTATIONS);
const services: Map = extractServicesFromAwsSdkInstrumentation(patchedAwsSdkInstrumentation);
@@ -124,6 +153,88 @@ describe('InstrumentationPatchTest', () => {
expect(sqsAttributes[AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME]).toEqual(_QUEUE_NAME);
});
+ it('Bedrock with patching', () => {
+ const patchedAwsSdkInstrumentation: AwsInstrumentation = extractAwsSdkInstrumentation(PATCHED_INSTRUMENTATIONS);
+ const services: Map = extractServicesFromAwsSdkInstrumentation(patchedAwsSdkInstrumentation);
+ const bedrockAttributes: Attributes = doExtractBedrockAttributes(services, 'Bedrock');
+ // Expect no-op from attribute extraction in Bedrock
+ expect(Object.entries(bedrockAttributes).length).toEqual(0);
+ const bedrockAttributesAfterResponse: Attributes = doResponseHookBedrock(services, 'Bedrock');
+ expect(Object.entries(bedrockAttributesAfterResponse).length).toBe(1);
+ expect(bedrockAttributesAfterResponse[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID]).toEqual(_BEDROCK_GUARDRAIL_ID);
+ });
+
+ it('Bedrock Agent with patching', () => {
+ const patchedAwsSdkInstrumentation: AwsInstrumentation = extractAwsSdkInstrumentation(PATCHED_INSTRUMENTATIONS);
+ const services: Map = extractServicesFromAwsSdkInstrumentation(patchedAwsSdkInstrumentation);
+
+ const operation_to_expected_attribute: Object = {
+ CreateAgentActionGroup: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ CreateAgentAlias: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ DeleteAgentActionGroup: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ DeleteAgentAlias: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ DeleteAgent: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ DeleteAgentVersion: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ GetAgentActionGroup: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ GetAgentAlias: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ GetAgent: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ GetAgentVersion: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ ListAgentActionGroups: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ ListAgentAliases: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ ListAgentKnowledgeBases: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ ListAgentVersions: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ PrepareAgent: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ UpdateAgentActionGroup: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ UpdateAgentAlias: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ UpdateAgent: { 'aws.bedrock.agent.id': _BEDROCK_AGENT_ID },
+ AssociateAgentKnowledgeBase: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ CreateDataSource: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ DeleteKnowledgeBase: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ DisassociateAgentKnowledgeBase: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ GetAgentKnowledgeBase: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ GetKnowledgeBase: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ ListDataSources: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ UpdateAgentKnowledgeBase: { 'aws.bedrock.knowledge_base.id': _BEDROCK_KNOWLEDGEBASE_ID },
+ DeleteDataSource: { 'aws.bedrock.data_source.id': _BEDROCK_DATASOURCE_ID },
+ GetDataSource: { 'aws.bedrock.data_source.id': _BEDROCK_DATASOURCE_ID },
+ UpdateDataSource: { 'aws.bedrock.data_source.id': _BEDROCK_DATASOURCE_ID },
+ };
+
+ for (const [operation, attribute_tuple] of Object.entries(operation_to_expected_attribute)) {
+ const bedrockAttributes: Attributes = doExtractBedrockAttributes(services, 'BedrockAgent', operation);
+ const [attribute_key, attribute_value] = Object.entries(attribute_tuple)[0];
+ expect(Object.entries(bedrockAttributes).length).toBe(1);
+ expect(bedrockAttributes[attribute_key]).toEqual(attribute_value);
+ const bedrockAgentSuccessAttributes: Attributes = doResponseHookBedrock(services, 'BedrockAgent', operation);
+ expect(Object.entries(bedrockAgentSuccessAttributes).length).toBe(1);
+ expect(bedrockAgentSuccessAttributes[attribute_key]).toEqual(attribute_value);
+ }
+ });
+
+ it('Bedrock Agent Runtime with patching', () => {
+ const patchedAwsSdkInstrumentation: AwsInstrumentation = extractAwsSdkInstrumentation(PATCHED_INSTRUMENTATIONS);
+ const services: Map = extractServicesFromAwsSdkInstrumentation(patchedAwsSdkInstrumentation);
+ const bedrockAttributes: Attributes = doExtractBedrockAttributes(services, 'BedrockAgentRuntime');
+ expect(Object.entries(bedrockAttributes).length).toBe(2);
+ expect(bedrockAttributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID]).toEqual(_BEDROCK_AGENT_ID);
+ expect(bedrockAttributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]).toEqual(_BEDROCK_KNOWLEDGEBASE_ID);
+ const bedrockAttributesAfterResponse: Attributes = doResponseHookBedrock(services, 'BedrockAgentRuntime');
+ expect(Object.entries(bedrockAttributesAfterResponse).length).toBe(0);
+ });
+
+ it('Bedrock Runtime with patching', () => {
+ const patchedAwsSdkInstrumentation: AwsInstrumentation = extractAwsSdkInstrumentation(PATCHED_INSTRUMENTATIONS);
+ const services: Map = extractServicesFromAwsSdkInstrumentation(patchedAwsSdkInstrumentation);
+ const bedrockAttributes: Attributes = doExtractBedrockAttributes(services, 'BedrockRuntime');
+
+ expect(Object.entries(bedrockAttributes).length).toBe(2);
+ expect(bedrockAttributes['gen_ai.system']).toEqual(_GEN_AI_SYSTEM);
+ expect(bedrockAttributes['gen_ai.request.model']).toEqual(_GEN_AI_REQUEST_MODEL);
+
+ const bedrockAttributesAfterResponse: Attributes = doResponseHookBedrock(services, 'BedrockRuntime');
+ expect(Object.entries(bedrockAttributesAfterResponse).length).toBe(0);
+ });
+
it('Lambda with custom eventContextExtractor patching', () => {
const patchedAwsSdkInstrumentation: AwsLambdaInstrumentation =
extractLambdaInstrumentation(PATCHED_INSTRUMENTATIONS);
@@ -192,6 +303,25 @@ describe('InstrumentationPatchTest', () => {
return doExtractAttributes(services, serviceName, params);
}
+ function doExtractBedrockAttributes(
+ services: Map,
+ serviceName: string,
+ operation?: string
+ ): Attributes {
+ const params: NormalizedRequest = {
+ serviceName: serviceName,
+ commandName: operation ? operation : 'mockCommandName',
+ commandInput: {
+ agentId: _BEDROCK_AGENT_ID,
+ dataSourceId: _BEDROCK_DATASOURCE_ID,
+ knowledgeBaseId: _BEDROCK_KNOWLEDGEBASE_ID,
+ guardrailId: _BEDROCK_GUARDRAIL_ID,
+ modelId: _GEN_AI_REQUEST_MODEL,
+ },
+ };
+ return doExtractAttributes(services, serviceName, params);
+ }
+
function doExtractAttributes(
services: Map,
serviceName: string,
@@ -205,6 +335,52 @@ describe('InstrumentationPatchTest', () => {
return requestMetadata.spanAttributes || {};
}
+ function doResponseHookBedrock(
+ services: Map,
+ serviceName: string,
+ operation?: string
+ ): Attributes {
+ const results: Partial = {
+ data: {
+ agentId: _BEDROCK_AGENT_ID,
+ dataSourceId: _BEDROCK_DATASOURCE_ID,
+ knowledgeBaseId: _BEDROCK_KNOWLEDGEBASE_ID,
+ guardrailId: _BEDROCK_GUARDRAIL_ID,
+ modelId: _GEN_AI_REQUEST_MODEL,
+ },
+ request: {
+ commandInput: {},
+ commandName: operation || 'dummy_operation',
+ serviceName: serviceName,
+ },
+ };
+
+ return doResponseHook(services, serviceName, results as NormalizedResponse);
+ }
+
+ function doResponseHook(
+ services: Map,
+ serviceName: string,
+ params: NormalizedResponse,
+ operation?: string
+ ): Attributes {
+ const serviceExtension: ServiceExtension = services.get(serviceName)!;
+ if (serviceExtension === undefined) {
+ throw new Error(`serviceExtension for ${serviceName} is not defined in the provided Map of services`);
+ }
+
+ const spanAttributes: Attributes = {};
+ const mockSpan: Partial = {};
+ // Make span update test version of span attributes
+ mockSpan.setAttribute = (key: string, value: AttributeValue) => {
+ spanAttributes[key] = value;
+ return mockSpan as Span;
+ };
+ serviceExtension.responseHook?.(params, mockSpan as Span, {} as Tracer, {});
+
+ return spanAttributes;
+ }
+
function extractLambdaInstrumentation(instrumentations: Instrumentation[]): AwsLambdaInstrumentation {
const filteredInstrumentations: Instrumentation[] = instrumentations.filter(
instrumentation => instrumentation.instrumentationName === '@opentelemetry/instrumentation-aws-lambda'
diff --git a/package-lock.json b/package-lock.json
index ec261d79..351bfa73 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -57,6 +57,10 @@
"@opentelemetry/semantic-conventions": "1.27.0"
},
"devDependencies": {
+ "@aws-sdk/client-bedrock": "3.632.0",
+ "@aws-sdk/client-bedrock-agent": "3.632.0",
+ "@aws-sdk/client-bedrock-agent-runtime": "3.632.0",
+ "@aws-sdk/client-bedrock-runtime": "3.632.0",
"@aws-sdk/client-kinesis": "3.632.0",
"@aws-sdk/client-s3": "3.632.0",
"@aws-sdk/client-sqs": "3.632.0",
@@ -77,6 +81,167 @@
"node": ">=14"
}
},
+ "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@aws-sdk/client-bedrock": {
+ "version": "3.632.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock/-/client-bedrock-3.632.0.tgz",
+ "integrity": "sha512-MSzhFQ1RqSJ/t6bqFZTqm6rGq/g/qLwacn3zy0p2b+hKwAyUZH0sPJMisPhslm6Mm2NyNWraQoY1tRdpgWxXkw==",
+ "dev": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/client-sso-oidc": "3.632.0",
+ "@aws-sdk/client-sts": "3.632.0",
+ "@aws-sdk/core": "3.629.0",
+ "@aws-sdk/credential-provider-node": "3.632.0",
+ "@aws-sdk/middleware-host-header": "3.620.0",
+ "@aws-sdk/middleware-logger": "3.609.0",
+ "@aws-sdk/middleware-recursion-detection": "3.620.0",
+ "@aws-sdk/middleware-user-agent": "3.632.0",
+ "@aws-sdk/region-config-resolver": "3.614.0",
+ "@aws-sdk/types": "3.609.0",
+ "@aws-sdk/util-endpoints": "3.632.0",
+ "@aws-sdk/util-user-agent-browser": "3.609.0",
+ "@aws-sdk/util-user-agent-node": "3.614.0",
+ "@smithy/config-resolver": "^3.0.5",
+ "@smithy/core": "^2.3.2",
+ "@smithy/fetch-http-handler": "^3.2.4",
+ "@smithy/hash-node": "^3.0.3",
+ "@smithy/invalid-dependency": "^3.0.3",
+ "@smithy/middleware-content-length": "^3.0.5",
+ "@smithy/middleware-endpoint": "^3.1.0",
+ "@smithy/middleware-retry": "^3.0.14",
+ "@smithy/middleware-serde": "^3.0.3",
+ "@smithy/middleware-stack": "^3.0.3",
+ "@smithy/node-config-provider": "^3.1.4",
+ "@smithy/node-http-handler": "^3.1.4",
+ "@smithy/protocol-http": "^4.1.0",
+ "@smithy/smithy-client": "^3.1.12",
+ "@smithy/types": "^3.3.0",
+ "@smithy/url-parser": "^3.0.3",
+ "@smithy/util-base64": "^3.0.0",
+ "@smithy/util-body-length-browser": "^3.0.0",
+ "@smithy/util-body-length-node": "^3.0.0",
+ "@smithy/util-defaults-mode-browser": "^3.0.14",
+ "@smithy/util-defaults-mode-node": "^3.0.14",
+ "@smithy/util-endpoints": "^2.0.5",
+ "@smithy/util-middleware": "^3.0.3",
+ "@smithy/util-retry": "^3.0.3",
+ "@smithy/util-utf8": "^3.0.0",
+ "tslib": "^2.6.2",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@aws-sdk/client-bedrock-agent": {
+ "version": "3.632.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agent/-/client-bedrock-agent-3.632.0.tgz",
+ "integrity": "sha512-09zZFgL870USDvUtjnFEep6usI8y1BHP5KCyv5OSDr0ZDLOmCs2hvFa7aWVryjOl1niPg7cDuQUT6ga4L1Td3Q==",
+ "dev": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/client-sso-oidc": "3.632.0",
+ "@aws-sdk/client-sts": "3.632.0",
+ "@aws-sdk/core": "3.629.0",
+ "@aws-sdk/credential-provider-node": "3.632.0",
+ "@aws-sdk/middleware-host-header": "3.620.0",
+ "@aws-sdk/middleware-logger": "3.609.0",
+ "@aws-sdk/middleware-recursion-detection": "3.620.0",
+ "@aws-sdk/middleware-user-agent": "3.632.0",
+ "@aws-sdk/region-config-resolver": "3.614.0",
+ "@aws-sdk/types": "3.609.0",
+ "@aws-sdk/util-endpoints": "3.632.0",
+ "@aws-sdk/util-user-agent-browser": "3.609.0",
+ "@aws-sdk/util-user-agent-node": "3.614.0",
+ "@smithy/config-resolver": "^3.0.5",
+ "@smithy/core": "^2.3.2",
+ "@smithy/fetch-http-handler": "^3.2.4",
+ "@smithy/hash-node": "^3.0.3",
+ "@smithy/invalid-dependency": "^3.0.3",
+ "@smithy/middleware-content-length": "^3.0.5",
+ "@smithy/middleware-endpoint": "^3.1.0",
+ "@smithy/middleware-retry": "^3.0.14",
+ "@smithy/middleware-serde": "^3.0.3",
+ "@smithy/middleware-stack": "^3.0.3",
+ "@smithy/node-config-provider": "^3.1.4",
+ "@smithy/node-http-handler": "^3.1.4",
+ "@smithy/protocol-http": "^4.1.0",
+ "@smithy/smithy-client": "^3.1.12",
+ "@smithy/types": "^3.3.0",
+ "@smithy/url-parser": "^3.0.3",
+ "@smithy/util-base64": "^3.0.0",
+ "@smithy/util-body-length-browser": "^3.0.0",
+ "@smithy/util-body-length-node": "^3.0.0",
+ "@smithy/util-defaults-mode-browser": "^3.0.14",
+ "@smithy/util-defaults-mode-node": "^3.0.14",
+ "@smithy/util-endpoints": "^2.0.5",
+ "@smithy/util-middleware": "^3.0.3",
+ "@smithy/util-retry": "^3.0.3",
+ "@smithy/util-utf8": "^3.0.0",
+ "tslib": "^2.6.2",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@aws-sdk/client-bedrock-agent-runtime": {
+ "version": "3.632.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agent-runtime/-/client-bedrock-agent-runtime-3.632.0.tgz",
+ "integrity": "sha512-oA2O04motlB74YjIPXWPOOrnlL6LwpJOcCbv0ghc+MirptKN+a9ZagwHA1nbr4/lwvyVH1N6om+OrgIIDkNKiA==",
+ "dev": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/client-sso-oidc": "3.632.0",
+ "@aws-sdk/client-sts": "3.632.0",
+ "@aws-sdk/core": "3.629.0",
+ "@aws-sdk/credential-provider-node": "3.632.0",
+ "@aws-sdk/middleware-host-header": "3.620.0",
+ "@aws-sdk/middleware-logger": "3.609.0",
+ "@aws-sdk/middleware-recursion-detection": "3.620.0",
+ "@aws-sdk/middleware-user-agent": "3.632.0",
+ "@aws-sdk/region-config-resolver": "3.614.0",
+ "@aws-sdk/types": "3.609.0",
+ "@aws-sdk/util-endpoints": "3.632.0",
+ "@aws-sdk/util-user-agent-browser": "3.609.0",
+ "@aws-sdk/util-user-agent-node": "3.614.0",
+ "@smithy/config-resolver": "^3.0.5",
+ "@smithy/core": "^2.3.2",
+ "@smithy/eventstream-serde-browser": "^3.0.6",
+ "@smithy/eventstream-serde-config-resolver": "^3.0.3",
+ "@smithy/eventstream-serde-node": "^3.0.5",
+ "@smithy/fetch-http-handler": "^3.2.4",
+ "@smithy/hash-node": "^3.0.3",
+ "@smithy/invalid-dependency": "^3.0.3",
+ "@smithy/middleware-content-length": "^3.0.5",
+ "@smithy/middleware-endpoint": "^3.1.0",
+ "@smithy/middleware-retry": "^3.0.14",
+ "@smithy/middleware-serde": "^3.0.3",
+ "@smithy/middleware-stack": "^3.0.3",
+ "@smithy/node-config-provider": "^3.1.4",
+ "@smithy/node-http-handler": "^3.1.4",
+ "@smithy/protocol-http": "^4.1.0",
+ "@smithy/smithy-client": "^3.1.12",
+ "@smithy/types": "^3.3.0",
+ "@smithy/url-parser": "^3.0.3",
+ "@smithy/util-base64": "^3.0.0",
+ "@smithy/util-body-length-browser": "^3.0.0",
+ "@smithy/util-body-length-node": "^3.0.0",
+ "@smithy/util-defaults-mode-browser": "^3.0.14",
+ "@smithy/util-defaults-mode-node": "^3.0.14",
+ "@smithy/util-endpoints": "^2.0.5",
+ "@smithy/util-middleware": "^3.0.3",
+ "@smithy/util-retry": "^3.0.3",
+ "@smithy/util-utf8": "^3.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
"aws-distro-opentelemetry-node-autoinstrumentation/node_modules/typescript": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
@@ -91,6 +256,19 @@
"node": ">=4.2.0"
}
},
+ "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -323,6 +501,62 @@
"node": ">=14.0.0"
}
},
+ "node_modules/@aws-sdk/client-bedrock-runtime": {
+ "version": "3.632.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.632.0.tgz",
+ "integrity": "sha512-iODVrsWvAaBOdXWrSxEajD2Hq1N94AJ2PBDiaDUjOwNg+TkGiR1ifSil4b0xFhNHUYhE76T5kJXOvdY+rTYwnw==",
+ "dev": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/client-sso-oidc": "3.632.0",
+ "@aws-sdk/client-sts": "3.632.0",
+ "@aws-sdk/core": "3.629.0",
+ "@aws-sdk/credential-provider-node": "3.632.0",
+ "@aws-sdk/middleware-host-header": "3.620.0",
+ "@aws-sdk/middleware-logger": "3.609.0",
+ "@aws-sdk/middleware-recursion-detection": "3.620.0",
+ "@aws-sdk/middleware-user-agent": "3.632.0",
+ "@aws-sdk/region-config-resolver": "3.614.0",
+ "@aws-sdk/types": "3.609.0",
+ "@aws-sdk/util-endpoints": "3.632.0",
+ "@aws-sdk/util-user-agent-browser": "3.609.0",
+ "@aws-sdk/util-user-agent-node": "3.614.0",
+ "@smithy/config-resolver": "^3.0.5",
+ "@smithy/core": "^2.3.2",
+ "@smithy/eventstream-serde-browser": "^3.0.6",
+ "@smithy/eventstream-serde-config-resolver": "^3.0.3",
+ "@smithy/eventstream-serde-node": "^3.0.5",
+ "@smithy/fetch-http-handler": "^3.2.4",
+ "@smithy/hash-node": "^3.0.3",
+ "@smithy/invalid-dependency": "^3.0.3",
+ "@smithy/middleware-content-length": "^3.0.5",
+ "@smithy/middleware-endpoint": "^3.1.0",
+ "@smithy/middleware-retry": "^3.0.14",
+ "@smithy/middleware-serde": "^3.0.3",
+ "@smithy/middleware-stack": "^3.0.3",
+ "@smithy/node-config-provider": "^3.1.4",
+ "@smithy/node-http-handler": "^3.1.4",
+ "@smithy/protocol-http": "^4.1.0",
+ "@smithy/smithy-client": "^3.1.12",
+ "@smithy/types": "^3.3.0",
+ "@smithy/url-parser": "^3.0.3",
+ "@smithy/util-base64": "^3.0.0",
+ "@smithy/util-body-length-browser": "^3.0.0",
+ "@smithy/util-body-length-node": "^3.0.0",
+ "@smithy/util-defaults-mode-browser": "^3.0.14",
+ "@smithy/util-defaults-mode-node": "^3.0.14",
+ "@smithy/util-endpoints": "^2.0.5",
+ "@smithy/util-middleware": "^3.0.3",
+ "@smithy/util-retry": "^3.0.3",
+ "@smithy/util-stream": "^3.1.3",
+ "@smithy/util-utf8": "^3.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
"node_modules/@aws-sdk/client-kinesis": {
"version": "3.632.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-kinesis/-/client-kinesis-3.632.0.tgz",
@@ -5388,7 +5622,6 @@
"resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz",
"integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5423,7 +5656,6 @@
"resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.8.tgz",
"integrity": "sha512-Tv1obAC18XOd2OnDAjSWmmthzx6Pdeh63FbLin8MlPiuJ2ATpKkq0NcNOJFr0dO+JmZXnwu8FQxKJ3TKJ3Hulw==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/node-config-provider": "^3.1.7",
"@smithy/types": "^3.4.2",
@@ -5440,7 +5672,6 @@
"resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.3.tgz",
"integrity": "sha512-4LTusLqFMRVQUfC3RNuTg6IzYTeJNpydRdTKq7J5wdEyIRQSu3rGIa3s80mgG2hhe6WOZl9IqTSo1pgbn6EHhA==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/middleware-endpoint": "^3.1.3",
"@smithy/middleware-retry": "^3.0.18",
@@ -5462,7 +5693,6 @@
"resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.3.tgz",
"integrity": "sha512-VoxMzSzdvkkjMJNE38yQgx4CfnmT+Z+5EUXkg4x7yag93eQkVQgZvN3XBSHC/ylfBbLbAtdu7flTCChX9I+mVg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/node-config-provider": "^3.1.7",
"@smithy/property-provider": "^3.1.6",
@@ -5479,7 +5709,6 @@
"resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.5.tgz",
"integrity": "sha512-6pu+PT2r+5ZnWEV3vLV1DzyrpJ0TmehQlniIDCSpZg6+Ji2SfOI38EqUyQ+O8lotVElCrfVc9chKtSMe9cmCZQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
"@smithy/types": "^3.4.2",
@@ -5492,7 +5721,6 @@
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.9.tgz",
"integrity": "sha512-PiQLo6OQmZAotJweIcObL1H44gkvuJACKMNqpBBe5Rf2Ax1DOcGi/28+feZI7yTe1ERHlQQaGnm8sSkyDUgsMg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/eventstream-serde-universal": "^3.0.8",
"@smithy/types": "^3.4.2",
@@ -5507,7 +5735,6 @@
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.6.tgz",
"integrity": "sha512-iew15It+c7WfnVowWkt2a7cdPp533LFJnpjDQgfZQcxv2QiOcyEcea31mnrk5PVbgo0nNH3VbYGq7myw2q/F6A==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5521,7 +5748,6 @@
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.8.tgz",
"integrity": "sha512-6m+wI+fT0na+6oao6UqALVA38fsScCpoG5UO/A8ZSyGLnPM2i4MS1cFUhpuALgvLMxfYoTCh7qSeJa0aG4IWpQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/eventstream-serde-universal": "^3.0.8",
"@smithy/types": "^3.4.2",
@@ -5536,7 +5762,6 @@
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.8.tgz",
"integrity": "sha512-09tqzIQ6e+7jLqGvRji1yJoDbL/zob0OFhq75edgStWErGLf16+yI5hRc/o9/YAybOhUZs/swpW2SPn892G5Gg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/eventstream-codec": "^3.1.5",
"@smithy/types": "^3.4.2",
@@ -5551,7 +5776,6 @@
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.7.tgz",
"integrity": "sha512-Ra6IPI1spYLO+t62/3jQbodjOwAbto9wlpJdHZwkycm0Kit+GVpzHW/NMmSgY4rK1bjJ4qLAmCnaBzePO5Nkkg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/protocol-http": "^4.1.3",
"@smithy/querystring-builder": "^3.0.6",
@@ -5578,7 +5802,6 @@
"resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.6.tgz",
"integrity": "sha512-c/FHEdKK/7DU2z6ZE91L36ahyXWayR3B+FzELjnYq7wH5YqIseM24V+pWCS9kFn1Ln8OFGTf+pyYPiHZuX0s/Q==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"@smithy/util-buffer-from": "^3.0.0",
@@ -5609,7 +5832,6 @@
"resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.6.tgz",
"integrity": "sha512-czM7Ioq3s8pIXht7oD+vmgy4Wfb4XavU/k/irO8NdXFFOx7YAlsCCcKOh/lJD1mJSYQqiR7NmpZ9JviryD/7AQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5645,7 +5867,6 @@
"resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.8.tgz",
"integrity": "sha512-VuyszlSO49WKh3H9/kIO2kf07VUwGV80QRiaDxUfP8P8UKlokz381ETJvwLhwuypBYhLymCYyNhB3fLAGBX2og==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/protocol-http": "^4.1.3",
"@smithy/types": "^3.4.2",
@@ -5660,7 +5881,6 @@
"resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz",
"integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/middleware-serde": "^3.0.6",
"@smithy/node-config-provider": "^3.1.7",
@@ -5679,7 +5899,6 @@
"resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.18.tgz",
"integrity": "sha512-YU1o/vYob6vlqZdd97MN8cSXRToknLXhFBL3r+c9CZcnxkO/rgNZ++CfgX2vsmnEKvlqdi26+SRtSzlVp5z6Mg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/node-config-provider": "^3.1.7",
"@smithy/protocol-http": "^4.1.3",
@@ -5700,7 +5919,6 @@
"resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz",
"integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5714,7 +5932,6 @@
"resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz",
"integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5728,7 +5945,6 @@
"resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz",
"integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/property-provider": "^3.1.6",
"@smithy/shared-ini-file-loader": "^3.1.7",
@@ -5744,7 +5960,6 @@
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.2.tgz",
"integrity": "sha512-42Cy4/oT2O+00aiG1iQ7Kd7rE6q8j7vI0gFfnMlUiATvyo8vefJkhb7O10qZY0jAqo5WZdUzfl9IV6wQ3iMBCg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/abort-controller": "^3.1.4",
"@smithy/protocol-http": "^4.1.3",
@@ -5761,7 +5976,6 @@
"resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz",
"integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5775,7 +5989,6 @@
"resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz",
"integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5789,7 +6002,6 @@
"resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz",
"integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"@smithy/util-uri-escape": "^3.0.0",
@@ -5804,7 +6016,6 @@
"resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz",
"integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5818,7 +6029,6 @@
"resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz",
"integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2"
},
@@ -5831,7 +6041,6 @@
"resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz",
"integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -5845,7 +6054,6 @@
"resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.3.tgz",
"integrity": "sha512-YD2KYSCEEeFHcWZ1E3mLdAaHl8T/TANh6XwmocQ6nPcTdBfh4N5fusgnblnWDlnlU1/cUqEq3PiGi22GmT2Lkg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^3.0.0",
"@smithy/protocol-http": "^4.1.3",
@@ -5865,7 +6073,6 @@
"resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.2.tgz",
"integrity": "sha512-RKDfhF2MTwXl7jan5d7QfS9eCC6XJbO3H+EZAvLQN8A5in4ib2Ml4zoeLo57w9QrqFekBPcsoC2hW3Ekw4vQ9Q==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/middleware-endpoint": "^3.1.3",
"@smithy/middleware-stack": "^3.0.6",
@@ -5883,7 +6090,6 @@
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz",
"integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -5896,7 +6102,6 @@
"resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz",
"integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/querystring-parser": "^3.0.6",
"@smithy/types": "^3.4.2",
@@ -5973,7 +6178,6 @@
"resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.18.tgz",
"integrity": "sha512-/eveCzU6Z6Yw8dlYQLA4rcK30XY0E4L3lD3QFHm59mzDaWYelrXE1rlynuT3J6qxv+5yNy3a1JuzhG5hk5hcmw==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/property-provider": "^3.1.6",
"@smithy/smithy-client": "^3.3.2",
@@ -5990,7 +6194,6 @@
"resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.18.tgz",
"integrity": "sha512-9cfzRjArtOFPlTYRREJk00suUxVXTgbrzVncOyMRTUeMKnecG/YentLF3cORa+R6mUOMSrMSnT18jos1PKqK6Q==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/config-resolver": "^3.0.8",
"@smithy/credential-provider-imds": "^3.2.3",
@@ -6009,7 +6212,6 @@
"resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.2.tgz",
"integrity": "sha512-FEISzffb4H8DLzGq1g4MuDpcv6CIG15fXoQzDH9SjpRJv6h7J++1STFWWinilG0tQh9H1v2UKWG19Jjr2B16zQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/node-config-provider": "^3.1.7",
"@smithy/types": "^3.4.2",
@@ -6037,7 +6239,6 @@
"resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz",
"integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.4.2",
"tslib": "^2.6.2"
@@ -6051,7 +6252,6 @@
"resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz",
"integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/service-error-classification": "^3.0.6",
"@smithy/types": "^3.4.2",
@@ -6066,7 +6266,6 @@
"resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.6.tgz",
"integrity": "sha512-lQEUfTx1ht5CRdvIjdAN/gUL6vQt2wSARGGLaBHNe+iJSkRHlWzY+DOn0mFTmTgyU3jcI5n9DkT5gTzYuSOo6A==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@smithy/fetch-http-handler": "^3.2.7",
"@smithy/node-http-handler": "^3.2.2",