Skip to content

Commit fbce5a2

Browse files
authored
Merge branch 'main' into minghui/log_chat_messages
2 parents 8ff9403 + be8dfdc commit fbce5a2

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4242

4343
### Fixed
4444

45+
- `opentelemetry-instrumentation-botocore`: bedrock: Add safety check for bedrock ConverseStream responses
46+
([#3990](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3990))
4547
- `opentelemetry-instrumentation-botocore`: bedrock: only decode JSON input buffer in Anthropic Claude streaming
4648
([#3875](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3875))
4749
- `opentelemetry-instrumentation-aiohttp-client`, `opentelemetry-instrumentation-aiohttp-server`: Fix readme links and text

instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/bedrock_utils.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,9 @@ def __init__(
528528
def from_converse(
529529
cls, response: dict[str, Any], capture_content: bool
530530
) -> _Choice:
531-
orig_message = response["output"]["message"]
531+
# be defensive about malformed responses, refer to #3958 for more context
532+
output = response.get("output", {})
533+
orig_message = output.get("message", {})
532534
if role := orig_message.get("role"):
533535
message = {"role": role}
534536
else:
@@ -537,8 +539,8 @@ def from_converse(
537539

538540
if tool_calls := extract_tool_calls(orig_message, capture_content):
539541
message["tool_calls"] = tool_calls
540-
elif capture_content:
541-
message["content"] = orig_message["content"]
542+
elif capture_content and (content := orig_message.get("content")):
543+
message["content"] = content
542544

543545
return cls(message, response["stopReason"], index=0)
544546

instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_bedrock.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from opentelemetry.instrumentation.botocore.extensions.bedrock_utils import (
2929
InvokeModelWithResponseStreamWrapper,
30+
_Choice,
3031
)
3132
from opentelemetry.semconv._incubating.attributes.error_attributes import (
3233
ERROR_TYPE,
@@ -3051,6 +3052,16 @@ def stream_error_callback(exc, ended):
30513052
assert "input" not in tool_block
30523053

30533054

3055+
def test_converse_stream_with_missing_output_in_response():
3056+
# Test malformed response missing "output" key
3057+
malformed_response = {"stopReason": "end_turn"}
3058+
choice = _Choice.from_converse(malformed_response, capture_content=True)
3059+
3060+
assert choice.finish_reason == "end_turn"
3061+
assert choice.message == {}
3062+
assert choice.index == 0
3063+
3064+
30543065
def amazon_nova_messages():
30553066
return [
30563067
{"role": "user", "content": [{"text": "Say this is a test"}]},

0 commit comments

Comments
 (0)