[opentelemetry-instrumentation-genai-bedrock] Add inference spans for Converse and ConverseStream methods - #488
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces and wires up a new opentelemetry-instrumentation-genai-bedrock package that instruments AWS Bedrock (via boto3/botocore) to emit GenAI inference (“chat”) spans for the Converse and ConverseStream APIs, including basic request/response extraction and streaming support.
Changes:
- Added Bedrock runtime instrumentation by patching
botocore.client.BaseClient._make_api_callforConverse/ConverseStreamand mapping request/response fields onto anInferenceInvocation. - Added a streaming wrapper for
converse_streamto keep the invocation open until the stream completes (or fails/closes). - Added package wiring (tox envs, workspace deps, docs requirements) plus unit tests, conformance scenarios, and VCR cassettes/examples.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| uv.lock | Adds the Bedrock package to the workspace lock and pulls in boto3/botocore deps. |
| tox.ini | Wires Bedrock test/conformance/lint envs; adjusts shellcheck env. |
| README.md | Adds Bedrock instrumentation entry to the top-level table. |
| pyproject.toml | Adds Bedrock package to workspace dependencies and pyright include/exclude. |
| docs-requirements.txt | Adds boto3 as a docs build dependency. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/README.rst | Documents supported Bedrock operations and configuration. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/pyproject.toml | Defines the new package, deps, extras, and instrumentor entrypoint. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/LICENSE | Adds Apache 2.0 license file for the new package. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/CHANGELOG.md | Adds a towncrier-managed changelog stub. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/.gitignore | Keeps the changelog dir tracked. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/359.added | Towncrier fragment for initial package scaffold. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/488.added | Towncrier fragment for Converse/ConverseStream spans. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/init.py | Implements BedrockInstrumentor and completion-hook wiring. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/version.py | Sets package version. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/package.py | Declares _instruments dependency metadata. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py | Patches botocore API calls and creates/stops invocations. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py | Extracts Bedrock request/response fields into invocation attributes. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/stream.py | Implements streaming wrapper to finalize spans on stream end/error/close. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/init.py | Marks test package. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conftest.py | Adds shared fixtures + VCR config + Bedrock client/instrument fixtures. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_instrumentor.py | Tests instrument/uninstrument lifecycle and dependency string. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_converse.py | Tests non-streaming Converse spans and request/response extraction. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_converse_stream.py | Tests ConverseStream spans, stream lifecycle, and error paths. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_completion_hook.py | Tests completion hook invocation and default hook loading behavior. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_conformance.py | Runs Bedrock conformance scenarios via weaver live-check. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/init.py | Marks conformance scenario package. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/inference.py | Conformance scenario for chat inference (Converse). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/inference_streaming.py | Conformance scenario for streaming chat (ConverseStream). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/tool_calling.py | Conformance scenario for tool calling in chat. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/requirements.oldest.txt | Oldest factor requirements file (comment-only). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/requirements.latest.txt | Latest factor requirements incl. boto3 and editable workspace installs. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_with_content.yaml | VCR cassette for Converse with content capture. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_no_content.yaml | VCR cassette for Converse without content capture. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_with_invalid_model.yaml | VCR cassette for Converse invalid-model error. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_with_content_different_events.yaml | VCR cassette for Converse with different event patterns. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_no_content_different_events.yaml | VCR cassette for Converse (no-content) with different event patterns. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_tool_call_with_content.yaml | VCR cassette for tool call flow (with content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_tool_call_no_content.yaml | VCR cassette for tool call flow (no content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_with_content.yaml | VCR cassette for ConverseStream with content. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_no_content.yaml | VCR cassette for ConverseStream without content. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_with_invalid_model.yaml | VCR cassette for ConverseStream invalid-model error. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_with_content_different_events.yaml | VCR cassette for streaming with different event patterns. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_no_content_different_events.yaml | VCR cassette for streaming (no-content) with different event patterns. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_handles_event_stream_error.yaml | VCR cassette for streaming error handling test. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_close_before_consumption.yaml | VCR cassette for closing stream before iteration. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_caller_side_error.yaml | VCR cassette for caller-side exception inside stream context manager. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_tool_call_parsing_errors.yaml | Adds a cassette intended for tool-call parsing error coverage. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/README.rst | Manual instrumentation example documentation. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/main.py | Manual instrumentation example code. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/custom_hook.py | Example showing a custom completion hook. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/requirements.txt | Requirements for the manual example. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/.env | Content-capture env for manual example. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/zero-code/README.rst | Zero-code example documentation. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/zero-code/main.py | Zero-code example application. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/zero-code/requirements.txt | Requirements for the zero-code example. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/zero-code/.env | Content-capture env for zero-code example. |
Suppressed comments (1)
tox.ini:374
- The shellcheck command uses
find ... -print | xargs shellcheck ..., which can break on paths with whitespace and can invoke shellcheck with no arguments depending on xargs behavior. Usingfind ... -exec ... +avoids these edge cases and is portable across GNU/BSD userlands.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Pull request dashboard statusMerged · refreshed 2026-09-01 22:08 UTC Status above doesn't look right?
|
- Only extract tool_definitions when capture_content is True
- Remove unnecessary try/except TypeError in BedrockConverseStreamWrapper
- Restrict bedrock latest envlist to py3{10,14} matching repo convention
- Remove unused cassette files and add tests for tool calling with NO_CONTENT
- Update opentelemetry-util-genai floor to >= 1.2b0.dev in pyproject.toml
| response=tool_result.get("content"), | ||
| ) | ||
|
|
||
| return None |
There was a problem hiding this comment.
reasoningContent and the other non-text blocks are dropped, should we follow up on the other parts in a separate PR?
There was a problem hiding this comment.
I added it in here.. WDYT of the various supported block types here (https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ReasoningContentBlock.html) -- i left out audio / video blocks, but added parsing for document / image types.. not sure what the best approach is
There was a problem hiding this comment.
we can add them as GenericPart and create semconv issue to add others.
BTW, would you mind updating Blob (deprecated now) -> BlobPart and such?
There was a problem hiding this comment.
Opened open-telemetry/semantic-conventions-genai#488 and used GenericPart for them. Switched to XPart types too..
There was a problem hiding this comment.
On second thought I wonder if it's worth adding these as GenericParts with just the type set, is that useful at all ? I don't think we will ever add raw audio / video to the telemetry, it's way too big.
Even a single image can be too big.. Google's telemetry API has a cap at 64KB for an attribute value for example.. Maybe we should be checking the size of BlobParts (like mages) and leaving them out if they exceed 50KB or something like that..
|
|
|
I recorded all the VCR tests against the real API and got passing results.. updated all the .yaml files with the real req/resp exchange.. |
- Only extract tool_definitions when capture_content is True
- Remove unnecessary try/except TypeError in BedrockConverseStreamWrapper
- Restrict bedrock latest envlist to py3{10,14} matching repo convention
- Remove unused cassette files and add tests for tool calling with NO_CONTENT
- Update opentelemetry-util-genai floor to >= 1.2b0.dev in pyproject.toml
12324ee to
bb9bb86
Compare
- Only extract tool_definitions when capture_content is True
- Remove unnecessary try/except TypeError in BedrockConverseStreamWrapper
- Restrict bedrock latest envlist to py3{10,14} matching repo convention
- Remove unused cassette files and add tests for tool calling with NO_CONTENT
- Update opentelemetry-util-genai floor to >= 1.2b0.dev in pyproject.toml
…del as expected violation
…dContent support in content blocks
d2f38ba to
0790ca7
Compare
Description
Adds logic to create an
InferenceInvocationand parse the request/response for attributes and set them on theinvocationfor theConverseandConverseStreammethods inboto3.Remaining gaps:
aioboto3to get the async equivalents.Type of change
Please delete options that are not relevant.
How has this been tested?
Unit tests..
Checklist