Skip to content

feat(boto3): Instrument Bedrock Runtime InvokeModel calls as gen_ai spans - #8187

Draft
sentry-junior[bot] wants to merge 2 commits into
junior/boto3-bedrock-conversefrom
junior/boto3-bedrock-invoke-model
Draft

sentry-junior[bot] wants to merge 2 commits into
junior/boto3-bedrock-conversefrom
junior/boto3-bedrock-invoke-model

Conversation

@sentry-junior

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

Copy link
Copy Markdown
Contributor

Description

This PR (2 of 3, stacked on #8186) records InvokeModel as a generate_content {modelId} span with op gen_ai.generate_content (new OP.GEN_AI_GENERATE_CONTENT). It matches the JS SDK.

The request and response bodies have a model-specific format. Like JS, this parses them per model family: Anthropic Claude (including inference profile IDs like us.anthropic...), Amazon Nova and Titan, Meta Llama, Cohere Command and Command R, and Mistral. Prompts and responses use the same gating as Converse: data_collection.gen_ai.inputs/outputs independently, else send_default_pii with include_prompts.

Decisions the diff doesn't show:

  • The SDK doesn't read the response body itself or replace the StreamingBody object. Instead, body.read, body.close, and body._raw_stream.close are patched on that instance, the same approach the S3 instrumentation on master uses. _patch_streaming_body() is extracted from it for this. The bytes are recorded as the caller reads them (read(), read(amt), iter_chunks()), and the span finishes when the body is fully read, closed, or a read fails. A new _ServiceExtension.instrument_response() hook lets an extension take over finishing the span.
  • Token usage falls back to Bedrock's x-amzn-bedrock-input/output-token-count response headers when the body has none (Cohere, Mistral, unknown models, early close). This replaces JS's chars / 6 estimates.
  • The request body is parsed once, in get_span_start_attributes(), for its parameters and input messages, so its parameters aren't visible to ignore_spans and spans it drops skip the parse.
  • Request bodies passed as file objects aren't read. Request and response bodies over 1 MB (MAX_INVOKE_MODEL_BODY_BYTES) aren't parsed, e.g. requests with images or image generation results; response usage still comes from the headers. Malformed JSON bodies are skipped quietly.
  • Media blocks (Claude image and document blocks, including images in tool_result, and Nova images) aren't recorded.
  • Unknown model families still get the span, op, model, and header usage.

Changelog note

InvokeModel spans change from http.client / auto.http.boto3 to gen_ai.generate_content / auto.ai.boto3, and their name changes from aws.bedrock-runtime.InvokeModel to generate_content <modelId>, which affects ignore_spans rules that match on the name. Boto3Integration is auto-enabled, so users with send_default_pii=True start sending InvokeModel prompts and responses unless they set Boto3Integration(include_prompts=False) or configure data_collection.

Issues

  • Refs AWS SDK Agent Support #5470. Follow-ups, both matching JS today: amazon.titan-embed models match the Titan text family, so they get a generate_content span rather than an embeddings span, and newer Mistral chat formats (messages/choices) aren't parsed.

via @dcramer.

--

View Session [Sentry]

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Coverage Results 📊

✅ 139002 passed | ⏭️ 7497 skipped | Total: 146499 | Pass Rate: 94.88% | Execution Time: 475m 40s

📊 Comparison with Base Branch

Metric Change
Total Tests 📈 +1829
Passed Tests 📈 +1788
Failed Tests —
Skipped Tests 📈 +41

All tests are passing successfully.

✅ Patch coverage is 96.00% (240 of 250 changed executable lines covered; target 80%).
Project statement coverage is 90.44% (up 0.11 percentage points from base (e8f6930) to head (b8c2634)).

Changed files with executable lines (5)
File Patch coverage Changed executable lines
sentry_sdk/integrations/boto3/_services/bedrock_runtime.py 96.85% 215/222 covered; missed: 47, 48, 247, 288, 380, 842, 847; partial branches: 246, 287, 379, 388, 421, 643, 651, 709, 841, 846, 858, 860, 862, 868, 876, 922, 924, 926
sentry_sdk/integrations/boto3/_instrumentation.py 85.71% 18/21 covered; missed: 368, 377, 390
sentry_sdk/consts.py 100.00% 1/1 covered
sentry_sdk/integrations/boto3/_client.py 100.00% 4/4 covered
sentry_sdk/integrations/boto3/_services/base.py 100.00% 2/2 covered
Coverage diff
@@            Coverage Diff             @@
##        master     #8187       +/-##
==========================================
+ Coverage    90.33%    90.44%    +0.11%
==========================================
  Files          203       204        +1
  Tracked lines     26905     27350      +445
  Branches     10048     10286      +238
==========================================
+ Hits         24302     24734      +432
- Misses        2603      2616       +13
- Partials      1516      1554       +38

Generated by Coverage Action

@sentry-junior
sentry-junior Bot force-pushed the junior/boto3-bedrock-invoke-model branch 4 times, most recently from 8400b94 to 79fee6a Compare November 5, 2026 00:29
@sentry-junior
sentry-junior Bot force-pushed the junior/boto3-bedrock-invoke-model branch 2 times, most recently from a029b59 to 77e635d Compare November 5, 2026 01:16
sentry-junior Bot and others added 2 commits November 5, 2026 01:29
…pans

Record InvokeModel calls as `gen_ai.generate_content` spans. Request and
response bodies are parsed per model family (Anthropic Claude, Amazon Nova
and Titan, Meta Llama, Cohere Command and Command R, Mistral), matching the
JavaScript SDK. The response body is recorded as the caller reads it, so it
isn't consumed or replaced, and the span finishes once it's read or closed.
Token usage falls back to Bedrock's usage response headers.

Refs #5470

Co-Authored-By: Sergiy Dybskiy <3760543+sergical@users.noreply.github.com>
Don't parse `InvokeModel` request bodies over 1 MB, e.g. requests with images,
and ignore malformed ones quietly, like response bodies.

Test that media content of Claude and Nova requests isn't recorded.

Refs #5470

Co-Authored-By: Sergiy Dybskiy <3760543+sergical@users.noreply.github.com>
@sentry-junior
sentry-junior Bot force-pushed the junior/boto3-bedrock-invoke-model branch from 77e635d to b8c2634 Compare November 5, 2026 01:41

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