Skip to content

refactor: Added @smithy/smithy-client send subscriber with AWS Bedrock Middleware#3864

Open
amychisholm03 wants to merge 5 commits intonewrelic:mainfrom
amychisholm03:NR-3839/aws-bedrock-migration
Open

refactor: Added @smithy/smithy-client send subscriber with AWS Bedrock Middleware#3864
amychisholm03 wants to merge 5 commits intonewrelic:mainfrom
amychisholm03:NR-3839/aws-bedrock-migration

Conversation

@amychisholm03
Copy link
Copy Markdown
Contributor

@amychisholm03 amychisholm03 commented Mar 25, 2026

Description

This PR migrates the AWS Bedrock instrumentation from the shim-based (monkey-patching) architecture to the subscriber-based architecture.

A standalone bedrock middleware module (lib/subscribers/aws-sdk-v3/bedrock.js) exports an init/middleware/config object that creates segments, sets tracing context, and records LLM events for Bedrock API calls. The SmithyClientSendSubscriber in lib/subscribers/smithy-client/send.js uses a middlewareByClient dispatch map to register this bedrock middleware (plus common header/attribute middleware) when it detects a BedrockRuntime client.

To avoid double instrumentation during us refactoring the other AWS middlewares, the subscriber skips clients not in middlewareByClient, and the old shim in lib/instrumentation/aws-sdk/v3/smithy-client.js skips clients that the subscriber handles. This lets bedrock use the new subscriber path while all other AWS services (SNS, SQS, DynamoDB, Lambda) continue using the existing shim path.

Note: @aws-sdk/smithy-client just exports @smithy/smithy-client, so we only need to subscribe to the later.

How to Test

npm run versioned aws-sdk-v3

Related Issues

Closes #3839

Additional Info

To migrate another service (e.g., SNS, SQS, DynamoDB, Lambda):

  1. Create a middleware config module in lib/subscribers/aws-sdk-v3/<service>.js exporting { init, middleware, config } — use bedrock.js as the template
  2. Import it in send.js and add the client name to the middlewareByClient map (e.g., SNS: [snsMiddlewareConfig])
  3. Add the client name to subscriberHandledClients in lib/instrumentation/aws-sdk/v3/smithy-client.js, so the old shim skips it
  4. Once all services are migrated, the old shim and subscriberHandledClients set can be removed entirely

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 25, 2026

Codecov Report

❌ Patch coverage is 96.67250% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.69%. Comparing base (83adcc4) to head (7dbd716).

Files with missing lines Patch % Lines
...ib/subscribers/aws-sdk/middleware/bedrock/index.js 95.91% 15 Missing ⚠️
lib/subscribers/aws-sdk/send.js 97.10% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3864      +/-   ##
==========================================
- Coverage   97.82%   97.69%   -0.13%     
==========================================
  Files         471      473       +2     
  Lines       58670    58830     +160     
  Branches        1        1              
==========================================
+ Hits        57391    57472      +81     
- Misses       1279     1358      +79     
Flag Coverage Δ
integration-tests-cjs-20.x 74.69% <37.65%> (-0.12%) ⬇️
integration-tests-cjs-22.x 74.72% <37.65%> (-0.12%) ⬇️
integration-tests-cjs-24.x 75.47% <37.65%> (-0.12%) ⬇️
integration-tests-esm-20.x 53.78% <37.65%> (-0.07%) ⬇️
integration-tests-esm-22.x 53.82% <37.65%> (-0.07%) ⬇️
integration-tests-esm-24.x 54.93% <37.65%> (-0.07%) ⬇️
unit-tests-20.x 89.89% <37.65%> (-0.16%) ⬇️
unit-tests-22.x 89.91% <37.65%> (-0.16%) ⬇️
unit-tests-24.x 89.91% <37.65%> (-0.16%) ⬇️
versioned-tests-20.x 80.67% <96.67%> (-0.26%) ⬇️
versioned-tests-22.x 80.68% <96.67%> (-0.26%) ⬇️
versioned-tests-24.x 80.58% <96.67%> (-0.26%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@amychisholm03 amychisholm03 changed the title refactor: @smithy/smithy-client send subscriber with AWS Bedrock Middleware refactor: Added @smithy/smithy-client send subscriber with AWS Bedrock Middleware Mar 25, 2026
@amychisholm03 amychisholm03 marked this pull request as ready for review March 25, 2026 22:15
Copy link
Copy Markdown
Contributor

@jsumners-nr jsumners-nr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not looked at the code yet. I want address organization first. I understand the thinking behind lib/subscribers/smithy-client/ and lib/subscribers/aws-sdk-v3/. But I think that will lead to some difficulty in understanding where things are when reviewing things in the future.

I'd like to suggest we organize things as so:

  • lib/subscribers/aws-sdk/
  • lib/subscribers/aws-sdk/v3/
  • lib/subscribers/aws-sdk/v3/bedrock.js
  • lib/subscribers/aws-sdk/smithy-client/

@bizob2828
Copy link
Copy Markdown
Member

I have not looked at the code yet. I want address organization first. I understand the thinking behind lib/subscribers/smithy-client/ and lib/subscribers/aws-sdk-v3/. But I think that will lead to some difficulty in understanding where things are when reviewing things in the future.

I'd like to suggest we organize things as so:

  • lib/subscribers/aws-sdk/
  • lib/subscribers/aws-sdk/v3/
  • lib/subscribers/aws-sdk/v3/bedrock.js
  • lib/subscribers/aws-sdk/smithy-client/

technically the only subscriber is smithy-client. The rest are middleware/helpers.

@jsumners-nr
Copy link
Copy Markdown
Contributor

I have not looked at the code yet. I want address organization first. I understand the thinking behind lib/subscribers/smithy-client/ and lib/subscribers/aws-sdk-v3/. But I think that will lead to some difficulty in understanding where things are when reviewing things in the future.
I'd like to suggest we organize things as so:

  • lib/subscribers/aws-sdk/
  • lib/subscribers/aws-sdk/v3/
  • lib/subscribers/aws-sdk/v3/bedrock.js
  • lib/subscribers/aws-sdk/smithy-client/

technically the only subscriber is smithy-client. The rest are middleware/helpers.

Do you disagree with my suggestion?

@bizob2828
Copy link
Copy Markdown
Member

bizob2828 commented Mar 26, 2026

I have not looked at the code yet. I want address organization first. I understand the thinking behind lib/subscribers/smithy-client/ and lib/subscribers/aws-sdk-v3/. But I think that will lead to some difficulty in understanding where things are when reviewing things in the future.
I'd like to suggest we organize things as so:

  • lib/subscribers/aws-sdk/
  • lib/subscribers/aws-sdk/v3/
  • lib/subscribers/aws-sdk/v3/bedrock.js
  • lib/subscribers/aws-sdk/smithy-client/

technically the only subscriber is smithy-client. The rest are middleware/helpers.

Do you disagree with my suggestion?

Not really. Looking at the current code, I could see the structure as this:

  • lib/subscribers/aws-sdk - config.js, smithy-client.js
  • lib/subsribers/aws-sdk/middleware- common, dynamodb, lambda, sns, sqs
  • lib/subscribers/aws-sdk/middleware/bedrock - index.js(current middleware), converse-stream-handler.js, stream-handler.js

Not wedded to this but that's my take on it. No need for v3 as we will not be supporting v2. Put all the middleware in a middleware folder. Expand bedrock to a folder as there are helpers for instrumenting streams.

},
{
channelName: 'nr_send',
module: { name: '@smithy/smithy-client', versionRange: '>=1.0.0 <4.0.0', filePath: 'dist-es/index.js' },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is @aws-sdk/smithy-client no longer valid? We were instrumenting that before

Copy link
Copy Markdown
Contributor Author

@amychisholm03 amychisholm03 Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I said in my PR description, @aws-sdk/smithy-client is like a 3-liner package that just exports @smithy/smithy-client, so we only need to subscribe to the later.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it do so across all versions of these libraries that we support?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For npm run versioned aws-sdk-v3 it appears so.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll test more versions with AGENT_PATH="$(pwd)" ./node_modules/.bin/versioned-tests --patch --print pretty -i 100 --all --strict test/versioned/aws-sdk-v3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to our tests:

{"name": "@aws-sdk/smithy-client", "minSupported": "3.47.0", "minAgentVersion": "8.7.1"},

The minimum version of @aws-sdk/smithy-client we support is 3.47.0. That version's manifest does not reference @smithy/smithy-client:

https://npmx.dev/package-code/@aws-sdk/smithy-client/v/3.47.0/package.json#L21-L25

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least for @aws-sdk/client-bedrock-runtime >=3.474.0, it does not have @aws-sdk/smithy-client as a dependency, only @smithy/smithy-client. Now with other @aws-sdk/* packages, there may be older versions that used @aws-sdk/smithy-client and adding the subscriber config for that could be addressed in that future PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying that the subscriber implementation only works with @aws-sdk/* >= v3.474.0?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the smithy client subscriber should instrument Client.send (or _Client.send depending on version) for @smithy/smithy-client: >=1, but it is only being tested currently with the AWS Bedrock middleware which is @aws-sdk/client-bedrock-runtime versions >=3.474.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I can't see any direct dependents of 3.47 that we are concerned with. So maybe this isn't a problem.

@amychisholm03
Copy link
Copy Markdown
Contributor Author

amychisholm03 commented Mar 26, 2026

I have not looked at the code yet. I want address organization first. I understand the thinking behind lib/subscribers/smithy-client/ and lib/subscribers/aws-sdk-v3/. But I think that will lead to some difficulty in understanding where things are when reviewing things in the future.
I'd like to suggest we organize things as so:

  • lib/subscribers/aws-sdk/
  • lib/subscribers/aws-sdk/v3/
  • lib/subscribers/aws-sdk/v3/bedrock.js
  • lib/subscribers/aws-sdk/smithy-client/

technically the only subscriber is smithy-client. The rest are middleware/helpers.

Do you disagree with my suggestion?

Not really. Looking at the current code, I could see the structure as this:

  • lib/subscribers/aws-sdk - config.js, smithy-client.js
  • lib/subsribers/aws-sdk/middleware- common, dynamodb, lambda, sns, sqs
  • lib/subscribers/aws-sdk/middleware/bedrock - index.js(current middleware), converse-stream-handler.js, stream-handler.js

Not wedded to this but that's my take on it. No need for v3 as we will not be supporting v2. Put all the middleware in a middleware folder. Expand bedrock to a folder as there are helpers for instrumenting streams.

Makes sense - I did aws-sdk-v3 to maintain parity with versioned test folder names. Also, I thought it may be confusing if @smithy/smithy-client was in a folder that wasn't smithy, but I could always add comments.

@amychisholm03 amychisholm03 force-pushed the NR-3839/aws-bedrock-migration branch from 4058bca to 9a98df1 Compare March 26, 2026 15:13
@amychisholm03 amychisholm03 force-pushed the NR-3839/aws-bedrock-migration branch from f7a7ad5 to bc42729 Compare March 26, 2026 16:01
@amychisholm03 amychisholm03 requested a review from bizob2828 March 26, 2026 20:39

// Enter the segment's context so downstream middleware (e.g. HTTP outbound)
// creates child segments under this bedrock segment.
agent.tracer.setSegment({ segment })
Copy link
Copy Markdown
Member

@bizob2828 bizob2828 Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want to avoid manually setting the context. This wrapped middleware should follow our standard processes where you bind the original next function to the context via agent.tracer.bindFunction(next, ctx, true).apply(this, arguments) and then run your afterHookstuff. also by passing intrue`. it will start the function and touch it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs PR Review

Development

Successfully merging this pull request may close these issues.

Refactor @aws-sdk/client-bedrock-runtime to subscribe to events emitted

4 participants