diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts index f15a91ad39..793d865f48 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts @@ -101,7 +101,9 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { case 'ConverseStream': return this.requestPreSpanHookConverse(request, config, diag, true); case 'InvokeModel': - return this.requestPreSpanHookInvokeModel(request, config, diag); + return this.requestPreSpanHookInvokeModel(request, config, diag, false); + case 'InvokeModelWithResponseStream': + return this.requestPreSpanHookInvokeModel(request, config, diag, true); } return { @@ -157,7 +159,8 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { private requestPreSpanHookInvokeModel( request: NormalizedRequest, config: AwsSdkInstrumentationConfig, - diag: DiagLogger + diag: DiagLogger, + isStream: boolean ): RequestMetadata { let spanName: string | undefined; const spanAttributes: Attributes = { @@ -312,6 +315,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { return { spanName, isIncoming: false, + isStream, spanAttributes, }; } @@ -346,6 +350,13 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { ); case 'InvokeModel': return this.responseHookInvokeModel(response, span, tracer, config); + case 'InvokeModelWithResponseStream': + return this.responseHookInvokeModelWithResponseStream( + response, + span, + tracer, + config + ); } } @@ -579,4 +590,134 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { } } } + + private async responseHookInvokeModelWithResponseStream( + response: NormalizedResponse, + span: Span, + tracer: Tracer, + config: AwsSdkInstrumentationConfig + ): Promise { + const stream = response.data?.body; + const modelId = response.request.commandInput?.modelId; + if (!stream || !span.isRecording()) return; + + const wrappedStream = instrumentAsyncIterable( + stream, + async (chunk: { chunk?: { bytes?: Uint8Array } }) => { + const parsedChunk = parseChunk(chunk?.chunk?.bytes); + + if (!parsedChunk) return; + + if (modelId.includes('amazon.titan')) { + recordTitanAttributes(parsedChunk); + } else if (modelId.includes('anthropic.claude')) { + recordClaudeAttributes(parsedChunk); + } else if (modelId.includes('amazon.nova')) { + recordNovaAttributes(parsedChunk); + } + } + ); + // Replace the original response body with our instrumented stream. + // - Defers span.end() until the entire stream is consumed + // This ensures downstream consumers still receive the full stream correctly, + // while OpenTelemetry can record span attributes from streamed data. + response.data.body = (async function* () { + try { + for await (const item of wrappedStream) { + yield item; + } + } finally { + span.end(); + } + })(); + return response.data; + + // Tap into the stream at the chunk level without modifying the chunk itself. + function instrumentAsyncIterable( + stream: AsyncIterable, + onChunk: (chunk: T) => void + ): AsyncIterable { + return { + [Symbol.asyncIterator]: async function* () { + for await (const chunk of stream) { + onChunk(chunk); + yield chunk; + } + }, + }; + } + + function parseChunk(bytes?: Uint8Array): any { + if (!bytes || !(bytes instanceof Uint8Array)) return null; + try { + const str = Buffer.from(bytes).toString('utf-8'); + return JSON.parse(str); + } catch (err) { + console.warn('Failed to parse streamed chunk', err); + return null; + } + } + + function recordNovaAttributes(parsedChunk: any) { + if (parsedChunk.metadata?.usage !== undefined) { + if (parsedChunk.metadata?.usage.inputTokens !== undefined) { + span.setAttribute( + ATTR_GEN_AI_USAGE_INPUT_TOKENS, + parsedChunk.metadata.usage.inputTokens + ); + } + if (parsedChunk.metadata?.usage.outputTokens !== undefined) { + span.setAttribute( + ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, + parsedChunk.metadata.usage.outputTokens + ); + } + } + if (parsedChunk.messageStop?.stopReason !== undefined) { + span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [ + parsedChunk.messageStop.stopReason, + ]); + } + } + + function recordClaudeAttributes(parsedChunk: any) { + if (parsedChunk.message?.usage?.input_tokens !== undefined) { + span.setAttribute( + ATTR_GEN_AI_USAGE_INPUT_TOKENS, + parsedChunk.message.usage.input_tokens + ); + } + if (parsedChunk.message?.usage?.output_tokens !== undefined) { + span.setAttribute( + ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, + parsedChunk.message.usage.output_tokens + ); + } + if (parsedChunk.delta?.stop_reason !== undefined) { + span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [ + parsedChunk.delta.stop_reason, + ]); + } + } + + function recordTitanAttributes(parsedChunk: any) { + if (parsedChunk.inputTextTokenCount !== undefined) { + span.setAttribute( + ATTR_GEN_AI_USAGE_INPUT_TOKENS, + parsedChunk.inputTextTokenCount + ); + } + if (parsedChunk.totalOutputTextTokenCount !== undefined) { + span.setAttribute( + ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, + parsedChunk.totalOutputTextTokenCount + ); + } + if (parsedChunk.completionReason !== undefined) { + span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [ + parsedChunk.completionReason, + ]); + } + } + } } diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts index b01ed09010..068507e4dd 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts @@ -36,6 +36,7 @@ import { ConverseStreamCommand, ConversationRole, InvokeModelCommand, + InvokeModelWithResponseStreamCommand, } from '@aws-sdk/client-bedrock-runtime'; import { AwsCredentialIdentity } from '@aws-sdk/types'; import * as path from 'path'; @@ -79,6 +80,7 @@ const sanitizeRecordings = (scopes: Definition[]) => { describe('Bedrock', () => { nockBack.fixtures = path.join(__dirname, 'mock-responses'); let credentials: AwsCredentialIdentity | undefined; + if (nockBack.currentMode === 'dryrun') { credentials = { accessKeyId: 'testing', @@ -642,4 +644,184 @@ describe('Bedrock', () => { }); }); }); + + describe('InvokeModelWithStreams', () => { + it('adds amazon titan model attributes to span', async () => { + const modelId = 'amazon.titan-text-lite-v1'; + const prompt = '\n\nHuman: Hello, How are you today? \n\nAssistant:'; + + const body = { + inputText: prompt, + textGenerationConfig: { + maxTokenCount: 10, + temperature: 0.8, + topP: 1, + stopSequences: ['|'], + }, + }; + const command = new InvokeModelWithResponseStreamCommand({ + modelId, + body: JSON.stringify(body), + contentType: 'application/json', + accept: 'application/json', + }); + + const response = await client.send(command); + console.log('response', response); + + let collectedText = ''; + if (!response.body) return; + for await (const chunk of response.body) { + if (chunk?.chunk?.bytes instanceof Uint8Array) { + const parsed = JSON.parse(decodeChunk(chunk)); + collectedText += parsed.outputText; + } + } + expect(collectedText).toBe(" Hello there! I'm doing well. Thank you"); + + const invokeModelSpans: ReadableSpan[] = + getInvokeModelWithResponseStreamSpans(); + + expect(invokeModelSpans.length).toBe(1); + expect(invokeModelSpans[0].attributes).toMatchObject({ + [ATTR_GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, + [ATTR_GEN_AI_REQUEST_MODEL]: modelId, + [ATTR_GEN_AI_REQUEST_MAX_TOKENS]: 10, + [ATTR_GEN_AI_REQUEST_TEMPERATURE]: 0.8, + [ATTR_GEN_AI_REQUEST_TOP_P]: 1, + [ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]: ['|'], + [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: 13, + [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: 10, + [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: ['LENGTH'], + }); + }); + it('adds claude model attributes to span', async () => { + const modelId = 'anthropic.claude-3-5-sonnet-20240620-v1:0'; + const prompt = '\n\nHuman: Hello, How are you today? \n\nAssistant:'; + + const body = { + anthropic_version: 'bedrock-2023-05-31', + max_tokens: 12, + top_k: 250, + stop_sequences: ['|'], + temperature: 0.8, + top_p: 1, + messages: [ + { + role: 'user', + content: [ + { + type: 'text', + text: prompt, + }, + ], + }, + ], + }; + + const command = new InvokeModelWithResponseStreamCommand({ + modelId, + body: JSON.stringify(body), + contentType: 'application/json', + accept: 'application/json', + }); + + const response = await client.send(command); + + let collectedText = ''; + if (!response.body) return; + for await (const chunk of response.body) { + if (chunk?.chunk?.bytes instanceof Uint8Array) { + const parsed = JSON.parse(decodeChunk(chunk)); + if ( + parsed.type === 'content_block_delta' && + parsed.delta?.type === 'text_delta' + ) { + collectedText += parsed.delta.text; + } + } + } + + expect(collectedText).toBe( + "Hello! I'm doing well, thank you for asking." + ); + + const invokeModelSpans: ReadableSpan[] = + getInvokeModelWithResponseStreamSpans(); + + expect(invokeModelSpans.length).toBe(1); + expect(invokeModelSpans[0].attributes).toMatchObject({ + [ATTR_GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, + [ATTR_GEN_AI_REQUEST_MODEL]: modelId, + [ATTR_GEN_AI_REQUEST_MAX_TOKENS]: 12, + [ATTR_GEN_AI_REQUEST_TEMPERATURE]: 0.8, + [ATTR_GEN_AI_REQUEST_TOP_P]: 1, + [ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]: ['|'], + [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: 22, + [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: 1, + [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: ['max_tokens'], + }); + }); + + it('adds amazon nova model attributes to span', async () => { + const modelId = 'amazon.nova-pro-v1:0'; + const prompt = 'Say this is a test'; + const nativeRequest: any = { + messages: [{ role: 'user', content: [{ text: prompt }] }], + inferenceConfig: { + max_new_tokens: 10, + temperature: 0.8, + top_p: 1, + stopSequences: ['|'], + }, + }; + const command = new InvokeModelWithResponseStreamCommand({ + modelId, + body: JSON.stringify(nativeRequest), + }); + + const response = await client.send(command); + + let collectedText = ''; + if (!response.body) return; + for await (const chunk of response.body) { + if (chunk?.chunk?.bytes instanceof Uint8Array) { + const parsed = JSON.parse(decodeChunk(chunk)); + if (parsed.contentBlockDelta?.delta) { + collectedText += parsed.contentBlockDelta?.delta.text; + } + } + } + + expect(collectedText).toBe( + "Certainly! If you're indicating that this interaction" + ); + + const invokeModelSpans: ReadableSpan[] = + getInvokeModelWithResponseStreamSpans(); + + expect(invokeModelSpans.length).toBe(1); + expect(invokeModelSpans[0].attributes).toMatchObject({ + [ATTR_GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, + [ATTR_GEN_AI_REQUEST_MODEL]: modelId, + [ATTR_GEN_AI_REQUEST_MAX_TOKENS]: 10, + [ATTR_GEN_AI_REQUEST_TEMPERATURE]: 0.8, + [ATTR_GEN_AI_REQUEST_TOP_P]: 1, + [ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]: ['|'], + [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: 5, + [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: 10, + [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: ['max_tokens'], + }); + }); + }); + + function getInvokeModelWithResponseStreamSpans(): ReadableSpan[] { + return getTestSpans().filter((s: ReadableSpan) => { + return s.name === 'BedrockRuntime.InvokeModelWithResponseStream'; + }); + } + + function decodeChunk(chunk: any) { + return Buffer.from(chunk.chunk.bytes).toString('utf-8'); + } }); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-amazon-nova-model-attributes-to-span.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-amazon-nova-model-attributes-to-span.json new file mode 100644 index 0000000000..9bf62b446c --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-amazon-nova-model-attributes-to-span.json @@ -0,0 +1,88 @@ +[ + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.nova-pro-v1%3A0/invoke-with-response-stream", + "body": { + "messages": [ + { + "role": "user", + "content": [ + { + "text": "Say this is a test" + } + ] + } + ], + "inferenceConfig": { + "max_new_tokens": 10, + "temperature": 0.8, + "top_p": 1, + "stopSequences": [ + "|" + ] + } + }, + "status": 403, + "response": { + "message": "Signature expired: 20250521T030814Z is now earlier than 20250521T074804Z (20250521T075304Z - 5 min.)" + }, + "rawHeaders": [ + "Date", + "Wed, 21 May 2025 07:53:04 GMT", + "Content-Type", + "application/json", + "Content-Length", + "114", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "46813d5b-e0f5-4df2-b02f-a1ddccb37d52", + "x-amzn-ErrorType", + "InvalidSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/" + ], + "responseIsBinary": false + }, + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.nova-pro-v1%3A0/invoke-with-response-stream", + "body": { + "messages": [ + { + "role": "user", + "content": [ + { + "text": "Say this is a test" + } + ] + } + ], + "inferenceConfig": { + "max_new_tokens": 10, + "temperature": 0.8, + "top_p": 1, + "stopSequences": [ + "|" + ] + } + }, + "status": 200, + "response": "000000b60000004b1babbac50b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a745a584e7a5957646c55335268636e51694f6e7369636d39735a534936496d467a63326c7a6447467564434a3966513d3d222c2270223a226162636465666768696a6b6c6d6e6f7071727374227dd3a6b277000000d70000004bbff9e4380b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d7876593274455a5778305953493665794a6b5a5778305953493665794a305a586830496a6f695132567964474670626d7835496e3073496d4e76626e526c626e52436247396a61306c755a475634496a6f776658303d222c2270223a226162636465227d2b96c4fe000000c60000004be2795a0a0b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d78765932745464473977496a7037496d4e76626e526c626e52436247396a61306c755a475634496a6f776658303d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142227d2f56b818000000db0000004b7a0909390b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d7876593274455a5778305953493665794a6b5a5778305953493665794a305a586830496a6f694953424a5a694a394c434a6a623235305a573530516d78765932744a626d526c654349364d583139222c2270223a226162636465666768696a6b6c6d6e6f7071227dbe57f5b7000000cf0000004bef69387b0b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d78765932745464473977496a7037496d4e76626e526c626e52436247396a61306c755a475634496a6f786658303d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b227d8c02cc2f000000f70000004b7e38cb3c0b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d7876593274455a5778305953493665794a6b5a5778305953493665794a305a586830496a6f6949486c76645364795a534270626d5270593246306157356e496e3073496d4e76626e526c626e52436247396a61306c755a475634496a6f796658303d222c2270223a226162636465666768696a6b6c6d6e6f70717273747576777879227d46a8e5d2000000b80000004ba49b04a40b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d78765932745464473977496a7037496d4e76626e526c626e52436247396a61306c755a475634496a6f796658303d222c2270223a226162636465666768696a6b6c6d6e227dac11916d000001030000004b08d0ee040b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d7876593274455a5778305953493665794a6b5a5778305953493665794a305a586830496a6f694948526f595851676447687063794270626e526c636d466a64476c7662694a394c434a6a623235305a573530516d78765932744a626d526c654349364d333139222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a41424344454647227dcbb9c378000000b70000004b26cb93750b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a6a623235305a573530516d78765932745464473977496a7037496d4e76626e526c626e52436247396a61306c755a475634496a6f7a6658303d222c2270223a226162636465666768696a6b6c6d227dc91669d4000000d30000004b4a7942f80b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a745a584e7a5957646c553352766343493665794a7a64473977556d566863323975496a6f6962574634583352766132567563794a3966513d3d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f227d38032f050000024c0000004b54e753320b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a745a5852685a4746305953493665794a316332466e5a53493665794a70626e42316446527661325675637949364e5377696233563063485630564739725a57357a496a6f784d4377695932466a614756535a57466b53573577645852556232746c626b4e7664573530496a6f774c434a6a59574e6f5a5664796158526c53573577645852556232746c626b4e7664573530496a6f776653776962575630636d6c6a6379493665333073496e527959574e6c496a703766583073496d467459587076626931695a57527962324e724c576c75646d396a595852706232354e5a58527961574e7a496a7037496d6c7563485630564739725a57354462335675644349364e5377696233563063485630564739725a57354462335675644349364d544173496d6c75646d396a595852706232354d5958526c626d4e35496a6f794d545573496d5a70636e4e30516e6c305a5578686447567559336b694f6a67784c434a6a59574e6f5a564a6c5957524a626e4231644652766132567551323931626e51694f6a4173496d4e685932686c56334a706447564a626e4231644652766132567551323931626e51694f6a423966513d3d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f50227d07773c15", + "rawHeaders": [ + "Date", + "Wed, 21 May 2025 07:53:05 GMT", + "Content-Type", + "application/vnd.amazon.eventstream", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "8e38e2e5-0910-4420-b028-60bbde456c2c", + "X-Amzn-Bedrock-Content-Type", + "application/json" + ], + "responseIsBinary": true + } +] \ No newline at end of file diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-amazon-titan-model-attributes-to-span.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-amazon-titan-model-attributes-to-span.json new file mode 100644 index 0000000000..8df07df607 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-amazon-titan-model-attributes-to-span.json @@ -0,0 +1,70 @@ +[ + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.titan-text-lite-v1/invoke-with-response-stream", + "body": { + "inputText": "\n\nHuman: Hello, How are you today? \n\nAssistant:", + "textGenerationConfig": { + "maxTokenCount": 10, + "temperature": 0.8, + "topP": 1, + "stopSequences": [ + "|" + ] + } + }, + "status": 403, + "response": { + "message": "Signature expired: 20250325T235114Z is now earlier than 20250521T072228Z (20250521T072728Z - 5 min.)" + }, + "rawHeaders": [ + "Date", + "Wed, 21 May 2025 07:27:28 GMT", + "Content-Type", + "application/json", + "Content-Length", + "114", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "f23a7276-5fad-4471-9faa-18da8cf88f0a", + "x-amzn-ErrorType", + "InvalidSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/" + ], + "responseIsBinary": false + }, + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.titan-text-lite-v1/invoke-with-response-stream", + "body": { + "inputText": "\n\nHuman: Hello, How are you today? \n\nAssistant:", + "textGenerationConfig": { + "maxTokenCount": 10, + "temperature": 0.8, + "topP": 1, + "stopSequences": [ + "|" + ] + } + }, + "status": 200, + "response": "0000020f0000004b4bb471ab0b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a7664585277645852555a586830496a6f694945686c624778764948526f5a584a6c4953424a4a3230675a473970626d6367643256736243346756476868626d736765573931496977696157356b5a5867694f6a4173496e527664474673543356306348563056475634644652766132567551323931626e51694f6a45774c434a6a623231776247563061573975556d566863323975496a6f695445564f523152494969776961573577645852555a586830564739725a57354462335675644349364d544d73496d467459587076626931695a57527962324e724c576c75646d396a595852706232354e5a58527961574e7a496a7037496d6c7563485630564739725a57354462335675644349364d544d73496d393164484231644652766132567551323931626e51694f6a45774c434a70626e5a765932463061573975544746305a57356a655349364e6a63344c434a6d61584a7a64454a356447564d5958526c626d4e35496a6f324e7a683966513d3d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f50515253227d0b0a144b", + "rawHeaders": [ + "Date", + "Wed, 21 May 2025 07:27:29 GMT", + "Content-Type", + "application/vnd.amazon.eventstream", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "fd539077-2d10-428c-8dba-f3b397e3f67b", + "X-Amzn-Bedrock-Content-Type", + "application/json" + ], + "responseIsBinary": true + } +] \ No newline at end of file diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-claude-model-attributes-to-span.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-claude-model-attributes-to-span.json new file mode 100644 index 0000000000..be5038b90a --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodelwithstreams-adds-claude-model-attributes-to-span.json @@ -0,0 +1,90 @@ +[ + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/anthropic.claude-3-5-sonnet-20240620-v1%3A0/invoke-with-response-stream", + "body": { + "anthropic_version": "bedrock-2023-05-31", + "max_tokens": 12, + "top_k": 250, + "stop_sequences": [ + "|" + ], + "temperature": 0.8, + "top_p": 1, + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "\n\nHuman: Hello, How are you today? \n\nAssistant:" + } + ] + } + ] + }, + "status": 403, + "response": { + "message": "Signature expired: 20250325T235114Z is now earlier than 20250521T030314Z (20250521T030814Z - 5 min.)" + }, + "rawHeaders": [ + "Date", + "Wed, 21 May 2025 03:08:14 GMT", + "Content-Type", + "application/json", + "Content-Length", + "114", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "9ea60ed1-a29e-41e6-9fcc-c9f343eda11c", + "x-amzn-ErrorType", + "InvalidSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/" + ], + "responseIsBinary": false + }, + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/anthropic.claude-3-5-sonnet-20240620-v1%3A0/invoke-with-response-stream", + "body": { + "anthropic_version": "bedrock-2023-05-31", + "max_tokens": 12, + "top_k": 250, + "stop_sequences": [ + "|" + ], + "temperature": 0.8, + "top_p": 1, + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "\n\nHuman: Hello, How are you today? \n\nAssistant:" + } + ] + } + ] + }, + "status": 200, + "response": "000001bf0000004bdde70b110b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f696257567a6332466e5a56397a6447467964434973496d316c63334e685a3255694f6e7369615751694f694a7463326466596d5279613138774d5668554d6c68465557354f596d52364f5446695956525256473569634445694c434a306558426c496a6f696257567a6332466e5a534973496e4a76624755694f694a6863334e7063335268626e51694c434a746232526c62434936496d4e735958566b5a53307a4c54557463323975626d56304c5449774d6a51774e6a49774969776959323975644756756443493657313073496e4e3062334266636d566863323975496a7075645778734c434a7a6447397758334e6c6358566c626d4e6c496a7075645778734c434a316332466e5a53493665794a70626e4231644639306232746c626e4d694f6a49794c434a766458527764585266644739725a57357a496a6f7866583139222c2270223a226162636465227d4a884b470000010f0000004bcd2003050b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f695932397564475675644639696247396a6131397a6447467964434973496d6c755a475634496a6f774c434a6a623235305a57353058324a7362324e72496a7037496e5235634755694f694a305a58683049697769644756346443493649694a3966513d3d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f5051525354555657227d2152ea6b0000011e0000004b90a0bd370b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f695932397564475675644639696247396a6131396b5a57783059534973496d6c755a475634496a6f774c434a6b5a5778305953493665794a306558426c496a6f69644756346446396b5a57783059534973496e526c654851694f694a495a57787362794a3966513d3d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f505152535455565758595a3031323334353637227d58245a65000001310000004bd33105e20b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f695932397564475675644639696247396a6131396b5a57783059534973496d6c755a475634496a6f774c434a6b5a5778305953493665794a306558426c496a6f69644756346446396b5a57783059534973496e526c654851694f69496849456b6e6253426b62326c755a7942335a5778734c4342306147467561794235623355696658303d222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f50515253545556575859227d7a6e8b52000000ff0000004b4e4880fd0b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f695932397564475675644639696247396a6131396b5a57783059534973496d6c755a475634496a6f774c434a6b5a5778305953493665794a306558426c496a6f69644756346446396b5a57783059534973496e526c654851694f6949675a6d39794947467a61326c755a7934696658303d222c2270223a226162636465666768696a6b6c6d6e6f707172737475227d59a1d9a9000000da0000004b476920890b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f695932397564475675644639696247396a6131397a64473977496977696157356b5a5867694f6a4239222c2270223a226162636465666768696a6b6c6d6e6f707172737475767778797a4142434445464748494a4b4c4d4e4f505152535455565758595a30313233227dfb6c29f4000001060000004bc03061740b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f696257567a6332466e5a56396b5a57783059534973496d526c62485268496a7037496e4e3062334266636d566863323975496a6f6962574634583352766132567563794973496e4e30623342666332567864575675593255694f6d3531624778394c434a316332466e5a53493665794a766458527764585266644739725a57357a496a6f784d6e3139222c2270223a2261626364227db7b0a8070000013e0000004b516192330b3a6576656e742d747970650700056368756e6b0d3a636f6e74656e742d747970650700106170706c69636174696f6e2f6a736f6e0d3a6d6573736167652d747970650700056576656e747b226279746573223a2265794a306558426c496a6f696257567a6332466e5a56397a644739774969776959573168656d39754c574a6c5a484a76593273746157353262324e6864476c76626b316c64484a7059334d694f6e736961573577645852556232746c626b4e7664573530496a6f794d6977696233563063485630564739725a57354462335675644349364d544973496d6c75646d396a595852706232354d5958526c626d4e35496a6f314d544973496d5a70636e4e30516e6c305a5578686447567559336b694f6a4d344f583139222c2270223a226162636465666768227df53a2a65", + "rawHeaders": [ + "Date", + "Wed, 21 May 2025 03:08:14 GMT", + "Content-Type", + "application/vnd.amazon.eventstream", + "Transfer-Encoding", + "chunked", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "4fa4bb62-6e9e-4e14-a559-62adc1bdfe22", + "X-Amzn-Bedrock-Content-Type", + "application/json" + ], + "responseIsBinary": true + } +] \ No newline at end of file