[opentelemetry-instrumentation-genai-bedrock] Add instrumentation for InvokeModel and InvokeModelWithResponseStream - #514
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Amazon Bedrock Runtime (boto3/botocore) operation-level GenAI instrumentation to the existing opentelemetry-instrumentation-genai-bedrock package, including span/attribute extraction for InvokeModel and InvokeModelWithResponseStream plus corresponding tests and conformance wiring.
Changes:
- Patch
botocore.client.BaseClient._make_api_callto instrument BedrockConverse*andInvokeModel*operations, including stream wrappers for streaming responses. - Add Bedrock-specific request/response/stream-chunk extractors mapping provider payloads into
opentelemetry-util-genaiinvocation types. - Add unit + VCR-backed tests and conformance scenarios; wire a Bedrock conformance tox env.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tox.ini | Adds Bedrock conformance env and adjusts Bedrock test commands; introduces global passenv patterns. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_invoke_model.py | New unit tests for invoke_model request/response extraction and span attributes. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_invoke_model_stream.py | New unit tests for streaming InvokeModelWithResponseStream wrapper behavior and error paths. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_converse.py | New VCR-backed tests for converse instrumentation, content capture, tool calls, and errors. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_converse_stream.py | New VCR-backed tests for converse_stream instrumentation, early close, and error paths. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_conformance.py | Adds conformance test runner that executes Bedrock scenarios with weaver live-check. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_completion_hook.py | Adds tests validating completion-hook wiring behavior for Bedrock. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/requirements.oldest.txt | Updates oldest test requirements (editable util-genai note). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/requirements.latest.txt | Keeps latest test requirements aligned with editable workspace installs. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conftest.py | Adds boto3 Bedrock client fixture, VCR config/scrubbing, env setup, and content-capture fixtures. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/tool_calling.py | Adds tool-calling conformance scenario for Bedrock chat. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/inference.py | Adds non-streaming inference conformance scenario for Bedrock chat. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/inference_streaming.py | Adds streaming inference conformance scenario and validates gen_ai.request.stream=true. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/init.py | Marks conformance scenario package. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_with_invalid_model.yaml | VCR cassette for Converse error case. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_with_content.yaml | VCR cassette for Converse success with content capture. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_tool_call_with_content.yaml | VCR cassette for Converse tool call flow (content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_tool_call_no_content.yaml | VCR cassette for Converse tool call flow (no content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_with_invalid_model.yaml | VCR cassette for ConverseStream error case. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_with_content.yaml | VCR cassette for ConverseStream success with content capture. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_with_content_tool_call.yaml | VCR cassette for ConverseStream tool call flow (content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_no_content.yaml | VCR cassette for ConverseStream success (no content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_handles_event_stream_error.yaml | VCR cassette used for stream error-path test coverage. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_close_before_consumption.yaml | VCR cassette used to validate early stream close handling. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_stream_caller_side_error.yaml | VCR cassette used for caller-side exception path coverage. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_converse_no_content.yaml | VCR cassette for Converse success (no content). |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/stream.py | Adds SyncStreamWrapper subclasses for ConverseStream and InvokeModelWithResponseStream. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py | Adds BaseClient._make_api_call wrapper and handlers for Converse/InvokeModel paths. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py | Adds request/response extraction + finish-reason mapping for Bedrock payload formats. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/init.py | Wires patch/unpatch into BedrockInstrumentor. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/README.rst | Documents supported Bedrock operations and basic usage. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/pyproject.toml | Updates util-genai dependency floor for Bedrock instrumentation. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/zero-code/main.py | Updates zero-code example to use converse. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/main.py | Updates manual example to use converse. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/custom_hook.py | Adds custom completion-hook example for Bedrock. |
| instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/488.added | Adds a changelog fragment describing the feature addition. |
Suppressed comments (2)
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py:574
int(...)conversion foroutput_tokensfrom the response payload is unguarded and can raise, which would cause the instrumentation wrapper to fail the SDK call.
if invocation.output_tokens is None:
out_tok = usage.get("output_tokens") or usage.get("outputTokens")
if out_tok is not None:
invocation.output_tokens = int(out_tok)
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py:584
cacheReadInputTokens/cacheWriteInputTokenspayload parsing uses unguardedint(...)conversions; if these values are absent or non-integer the instrumentation will raise and fail the request.
cache_read = usage.get("cache_read_input_tokens") or usage.get(
"cacheReadInputTokens"
)
if cache_read is not None:
invocation.cache_read_input_tokens = int(cache_read)
cache_write = usage.get("cache_creation_input_tokens") or usage.get(
"cacheWriteInputTokens"
)
if cache_write is not None:
invocation.cache_creation_input_tokens = int(cache_write)
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Pull request dashboard statusWaiting on the author · refreshed 2026-09-02 21:15 UTC Respond to 2 review items (e.g. link a commit, explain why not, ask a follow-up): Status above doesn't look right?
|
d083b66 to
ef86be9
Compare
f01d3c7 to
fc5990a
Compare
5322535 to
756332f
Compare
…delWithResponseStream
…or instead of stop
a5bddf7 to
289a944
Compare
…ock_instrumentation_3
…ool calling - Restore .changelog/488.added fragment from main - Gate stream content accumulation behind capture_content in BedrockInvokeModelStreamWrapper - Support Anthropic tool_use and tool_result content blocks in extract_content_block - Support streamed tool use in BedrockInvokeModelStreamWrapper - Add unit and end-to-end integration tests using Stubber for InvokeModel streaming
…mptVariables - Extract guardrail identifier in Converse and InvokeModel as aws.bedrock.guardrail.id - Extract outputConfig textFormat in Converse as gen_ai.output.type - Extract promptVariables in Converse as gen_ai.prompt.variable.<key> when content capture is enabled - Add unit and integration tests
…drock_instrumentation_3
|
|
||
| FinishReason = Literal[ | ||
| "content_filter", "error", "length", "stop", "tool_calls", "compaction" | ||
| "content_filter", "error", "length", "stop", "tool_call", "compaction" |
There was a problem hiding this comment.
This change breaks OpenAI instrumentation when choices have tool calls (OutputMessage expects FinishReason, but OpenAI returns "tool_calls"). Please update OpenAI to map "tool_calls" to "tool_call".
| ) | ||
| ) | ||
| else: | ||
| if self._self_accumulated_reasoning: |
There was a problem hiding this comment.
self._self_accumulated_reasoning is never populated in _process_chunk, did you want to populate reasoning part with it?
Description
Adds instrumentation for
InvokeModelandInvokeModelWithResponseStreamAdd support for bedrock specific sem convs: Add
aws.bedrock.guardrail.id, addgen_ai.prompt.variable.<key>, addgen_ai.output.type.How has this been tested?
Unit tests
Checklist