Skip to content

feat(server-utils): Record Bedrock prompts, tools, and responses - #26118

Draft
sentry-junior[bot] wants to merge 5 commits into
developfrom
feat/bedrock-gen-ai-content
Draft

sentry-junior[bot] wants to merge 5 commits into
developfrom
feat/bedrock-gen-ai-content

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Why: Bedrock gen_ai spans carried only the model, params, and usage, while the other AI integrations also record prompts and responses. This PR records gen_ai.input.messages, gen_ai.system_instructions, gen_ai.tool.definitions, and gen_ai.output.messages for Converse, ConverseStream, InvokeModel, and InvokeModelWithResponseStream. It also sets the deprecated gen_ai.response.text and gen_ai.response.tool_calls, as endStreamSpan does.

Capture follows dataCollection.genAI, through resolveAIRecordingOptions like the other providers. Inputs and outputs are recorded by default (dataCollection.genAI defaults to on), so Bedrock prompts and responses become recorded by default once this ships. This needs an Important Changes note in the release. dataCollection: { genAI: { inputs: false } } turns off prompts, system instructions, and tool definitions, and outputs: false turns off responses. awsIntegration({ recordInputs, recordOutputs }) takes precedence over both and applies only to Bedrock spans. The setting is read per call, so it does not matter whether the client exists when the integration is built. Nothing else in dataCollection applies here. No other AI provider reads userInfo, and Bedrock records no user fields.

Converse and Nova messages are mapped to {role, parts}. Claude InvokeModel messages are recorded as sent, as the Anthropic integration does, except that image and document blocks (also inside tool_result) are replaced with blob parts so their base64 data is never recorded. Titan, Llama, Mistral, and Cohere prompts become a single user text part.

Bugs found along the way and fixed here:

  • InvokeModel with a non-JSON body or no modelId threw and dropped the span.
  • Prompt-cache read/write tokens were missing from input tokens.
  • Claude stream output tokens were read from the message_start placeholder.
  • Mistral and Cohere stream estimates used only the last chunk.
  • A failed stream left the span status ok, and a missing stream body left the span open.

The stream tests hand-encode AWS eventstream frames, so nock can mock streaming after all.

How to review: Start with bedrock-runtime-content.ts, which has the mapping, then read the response hooks in bedrock-runtime.ts. scenario-stream.mjs is mostly frame-encoding boilerplate. The integration tests run the plain and streaming scenarios against the default, inputs: false, outputs: false, and an integration option overriding dataCollection in each direction.

Unsure about:

  • The options are top-level recordInputs/recordOutputs on awsIntegration. They only affect Bedrock, but nesting them under bedrock felt heavier.
  • gen_ai.response.finish_reasons is now a JSON string ('["end_turn"]'), matching the conventions type and the other integrations. It used to be an array attribute.
  • Images, documents, and video are recorded as blob parts with a modality (and MIME type when known) and no bytes. Cache points and unknown Converse blocks are dropped. Streams only buffer response content when outputs are recorded.

via @sergical.

--

View Session [Sentry]

The Bedrock Runtime extension now records gen_ai.input.messages,
gen_ai.system_instructions, gen_ai.tool.definitions, and
gen_ai.output.messages for Converse, ConverseStream, InvokeModel, and
InvokeModelWithResponseStream, gated by dataCollection.genAI or the new
awsIntegration({ recordInputs, recordOutputs }) options.

Also fixes InvokeModel calls with a non-JSON body or no modelId that
skipped the span, prompt-cache tokens missing from input tokens, Claude
stream output tokens read from the message_start placeholder, Mistral
and Cohere stream token estimates that used only the last chunk, and
stream failures that left the span status ok or the span open.

Co-Authored-By: David Cramer <23610+dcramer@users.noreply.github.com>
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Compared: 706009f (PR test merge using develop at 88a5e3b)

Against: 88a5e3b (develop) · base run #65049

✅ Baseline matches: this diff contains only this PR's changes.

Path Size % Change Change
@sentry/browser 30.4 kB - -
@sentry/browser - with treeshaking flags 28.54 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 28.43 kB - -
@sentry/browser (incl. Tracing) 52.73 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 52.73 kB - -
@sentry/browser (incl. Tracing, Profiling) 55.7 kB - -
@sentry/browser (incl. Tracing, Replay) 93.03 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 81.63 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 97.78 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 110.77 kB - -
@sentry/browser (incl. Feedback) 47.98 kB - -
@sentry/browser (incl. sendFeedback) 35.5 kB - -
@sentry/browser (incl. FeedbackAsync) 40.61 kB - -
@sentry/browser (incl. Metrics) 31.44 kB - -
@sentry/browser (incl. Logs) 31.73 kB - -
@sentry/browser (incl. Metrics & Logs) 32.45 kB - -
@sentry/react 32.29 kB - -
@sentry/react (incl. Tracing) 55.1 kB - -
@sentry/vue 38.67 kB - -
@sentry/vue (incl. Tracing) 55.75 kB - -
@sentry/svelte 30.43 kB - -
@sentry/remix (Remix 3 client bundle) 57.82 kB - -
CDN Bundle 32.19 kB - -
CDN Bundle (incl. Tracing) 53.26 kB - -
CDN Bundle (incl. Logs, Metrics) 34.47 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 55.2 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 75.88 kB - -
CDN Bundle (incl. Tracing, Replay) 91.47 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 93.4 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 97.58 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 99.58 kB - -
CDN Bundle - uncompressed 94.67 kB - -
CDN Bundle (incl. Tracing) - uncompressed 157.67 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 101.14 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 163.41 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 232.71 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 279.36 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 285.08 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 293.06 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 298.77 kB - -
@sentry/nextjs (client) 58.05 kB - -
@sentry/sveltekit (client) 53.24 kB - -
@sentry/core/server 44.25 kB - -
@sentry/core/browser 13.93 kB - -
@sentry/node 158.08 kB +1.38% +2.14 kB 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 82.28 kB - -
@sentry/node - without tracing 96.91 kB +0.02% +16 B 🔺
@sentry/node - without channel injection 138.43 kB +1.58% +2.15 kB 🔺
@sentry/aws-serverless 107.72 kB +2.5% +2.62 kB 🔺
@sentry/cloudflare (withSentry) - minified 200.67 kB - -
@sentry/cloudflare (withSentry) 499.05 kB - -
@sentry/nextjs/cloudflare (withSentry) - minified 222.65 kB - -

View base workflow run

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

One or more gzipped bundles increased by more than 500 bytes. If this increase is intentional, add the Accept Bundlesize Increase label to this PR to rerun and accept the check.

…ions for Bedrock

Runs both the plain and the streaming Bedrock scenarios against the
default (recorded), `dataCollection.genAI.inputs: false`,
`dataCollection.genAI.outputs: false`, and `awsIntegration()` options
overriding `dataCollection.genAI` in both directions. Also checks that
the setting is read from the client current at call time.

Co-Authored-By: Sergiy Dybskiy <3760543+sergical@users.noreply.github.com>
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Optional E2E tests

Some optional checks were not successful. They do not block the merge. 4 not successful, 50 successful. See the run.

Check Status
❌ CI: Optional E2E Tests / E2E cloudflare-flue-send-to-sentry Test (optional) Failing after 3m Details
❌ CI: Optional E2E Tests / E2E cloudflare-pi-durable (latest) Test (optional) Failing after 3m Details
❌ CI: Optional E2E Tests / E2E nextjs-16-cacheComponents (cloudflare) Test (optional) Failing after 10m Details
❌ CI: Optional E2E Tests / E2E node-flue (latest) Test (optional) Failing after 1m Details
Successful checks
Check Status
✅ CI: Optional E2E Tests / E2E astro-7-static Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nuxt-5 (tunnel-dev) Test (optional) Successful in 5m Details
✅ CI: Optional E2E Tests / E2E cloudflare-think (ai v6) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-mastra (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nestjs-12 (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E cloudflare-think Test (optional) Successful in 58s Details
✅ CI: Optional E2E Tests / E2E cloudflare-mastra Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nextjs-15 (turbo) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nextjs-14 (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E cloudflare-workers-send-to-sentry Test (optional) Successful in 5m Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries (cloudflare) Test (optional) Successful in 53s Details
✅ CI: Optional E2E Tests / E2E nextjs-15 (latest) Test (optional) Successful in 3m Details
✅ CI: Optional E2E Tests / E2E deno (latest) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (cloudflare, latest) Test (optional) Successful in 6m Details
✅ CI: Optional E2E Tests / E2E cloudflare-agent Test (optional) Successful in 53s Details
✅ CI: Optional E2E Tests / E2E cloudflare-pi-durable Test (optional) Successful in 48s Details
✅ CI: Optional E2E Tests / E2E node-express-mcp-v1 Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E nextjs-16-tunnel (cloudflare) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-pi-durable Test (optional) Successful in 58s Details
✅ CI: Optional E2E Tests / E2E node-mastra Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E debug-id-sourcemaps Test (optional) Successful in 41s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (deno) Test (optional) Successful in 6m Details
✅ CI: Optional E2E Tests / E2E node-pi-durable (latest) Test (optional) Successful in 53s Details
✅ CI: Optional E2E Tests / E2E node-eve (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-flue Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E node-express-send-to-sentry-static Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nextjs-orpc Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E astro-7 Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-eve (orchestrion) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-eve Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-openai-decisions (latest) Test (optional) Successful in 4m Details
✅ CI: Optional E2E Tests / E2E node-openai-decisions Test (optional) Successful in 46s Details
✅ CI: Optional E2E Tests / E2E supabase-nextjs Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E node-express-send-to-sentry Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (vinext) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E react-router-7-framework-instrumentation Test (optional) Successful in 3m Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react-cloudflare Test (optional) Successful in 52s Details
✅ CI: Optional E2E Tests / E2E node-fastify-6 Test (optional) Successful in 48s Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps (static / nuxt generate) Test (optional) Successful in 43s Details
✅ CI: Optional E2E Tests / E2E node-express-mcp-v2 Test (optional) Successful in 56s Details
✅ CI: Optional E2E Tests / E2E node-fastify-6 (tracer provider) Test (optional) Successful in 47s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (vinext, bun) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react-sourcemaps Test (optional) Successful in 47s Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react (latest) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps Test (optional) Successful in 46s Details
✅ CI: Optional E2E Tests / E2E nuxt-5 Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps (client source maps kept) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E solidstart-2 Test (optional) Successful in 1m Details

…without outputs

Claude InvokeModel bodies carry images and documents as base64 source data,
including inside tool results. Record them as blob parts instead. Streams no
longer buffer response content when outputs are not recorded; token
approximation counts characters without keeping the text.

Co-Authored-By: Sergiy Dybskiy <3760543+sergical@users.noreply.github.com>
sentry-junior Bot and others added 2 commits November 4, 2026 23:34
…ral stream totals

The input estimate went onto the span in the request hook but never reached the
stream state, so the total for a streamed Cohere or Mistral call only counted
output tokens.

Co-Authored-By: Sergiy Dybskiy <3760543+sergical@users.noreply.github.com>
…Cohere and Mistral

Co-Authored-By: Sergiy Dybskiy <3760543+sergical@users.noreply.github.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant