diff --git a/sentry_sdk/integrations/boto3/_services/bedrock.py b/sentry_sdk/integrations/boto3/_services/bedrock.py index 77420f3407..1fc11d7581 100644 --- a/sentry_sdk/integrations/boto3/_services/bedrock.py +++ b/sentry_sdk/integrations/boto3/_services/bedrock.py @@ -38,6 +38,23 @@ def get_request_attributes(self, ctx: "AwsCallContext") -> "Attributes": if model_id is not None: attributes[SPANDATA.GEN_AI_REQUEST_MODEL] = model_id + inference_config = ctx.params.get("inferenceConfig") + + if not isinstance(inference_config, dict): + return attributes + + max_tokens = inference_config.get("maxTokens") + if max_tokens is not None: + attributes[SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] = max_tokens + + temperature = inference_config.get("temperature") + if temperature is not None: + attributes[SPANDATA.GEN_AI_REQUEST_TEMPERATURE] = temperature + + top_p = inference_config.get("topP") + if top_p is not None: + attributes[SPANDATA.GEN_AI_REQUEST_TOP_P] = top_p + return attributes def get_response_attributes( diff --git a/tests/integrations/boto3/test_bedrock.py b/tests/integrations/boto3/test_bedrock.py index a272ae2dd5..1040231230 100644 --- a/tests/integrations/boto3/test_bedrock.py +++ b/tests/integrations/boto3/test_bedrock.py @@ -55,6 +55,11 @@ def test_converse( client.converse( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) sentry_sdk.flush() @@ -72,6 +77,10 @@ def test_converse( span["attributes"][SPANDATA.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-sonnet-20240229-v1:0" ) + + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 else: events = capture_events() @@ -79,6 +88,11 @@ def test_converse( client.converse( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) (transaction,) = events @@ -92,6 +106,10 @@ def test_converse( == "anthropic.claude-3-sonnet-20240229-v1:0" ) + assert span["data"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 + @pytest.mark.parametrize("span_streaming", [True, False]) @pytest.mark.parametrize("stream_gen_ai_spans", [True, False]) @@ -135,6 +153,11 @@ def raise_client_error(**kwargs): client.converse( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) sentry_sdk.flush() @@ -152,6 +175,10 @@ def raise_client_error(**kwargs): == "anthropic.claude-3-sonnet-20240229-v1:0" ) + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 + assert span["attributes"][SPANDATA.ERROR_TYPE] == "AccessDeniedException" assert span["attributes"][SPANDATA.HTTP_STATUS_CODE] == 403 assert span["attributes"][SPANDATA.AWS_REQUEST_ID] == "test-id" @@ -164,6 +191,11 @@ def raise_client_error(**kwargs): client.converse( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) (transaction,) = events @@ -176,6 +208,10 @@ def raise_client_error(**kwargs): == "anthropic.claude-3-sonnet-20240229-v1:0" ) + assert span["data"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 + assert span["data"][SPANDATA.ERROR_TYPE] == "AccessDeniedException" assert span["data"][SPANDATA.HTTP_STATUS_CODE] == 403 assert span["data"][SPANDATA.AWS_REQUEST_ID] == "test-id" @@ -209,6 +245,11 @@ def test_converse_stream( client.converse_stream( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) sentry_sdk.flush() @@ -226,6 +267,10 @@ def test_converse_stream( span["attributes"][SPANDATA.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-sonnet-20240229-v1:0" ) + + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 else: events = capture_events() @@ -233,6 +278,11 @@ def test_converse_stream( client.converse_stream( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) (transaction,) = events @@ -246,6 +296,10 @@ def test_converse_stream( == "anthropic.claude-3-sonnet-20240229-v1:0" ) + assert span["data"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 + @pytest.mark.parametrize("span_streaming", [True, False]) @pytest.mark.parametrize("stream_gen_ai_spans", [True, False]) @@ -289,6 +343,11 @@ def raise_client_error(**kwargs): client.converse_stream( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) sentry_sdk.flush() @@ -307,6 +366,10 @@ def raise_client_error(**kwargs): == "anthropic.claude-3-sonnet-20240229-v1:0" ) + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["attributes"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 + assert span["attributes"][SPANDATA.ERROR_TYPE] == "AccessDeniedException" assert span["attributes"][SPANDATA.HTTP_STATUS_CODE] == 403 assert span["attributes"][SPANDATA.AWS_REQUEST_ID] == "test-id" @@ -319,6 +382,11 @@ def raise_client_error(**kwargs): client.converse_stream( modelId="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": [{"text": "Hi"}]}], + inferenceConfig={ + "maxTokens": 1024, + "temperature": 0.7, + "topP": 0.9, + }, ) (transaction,) = events @@ -332,6 +400,10 @@ def raise_client_error(**kwargs): == "anthropic.claude-3-sonnet-20240229-v1:0" ) + assert span["data"][SPANDATA.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert span["data"][SPANDATA.GEN_AI_REQUEST_TOP_P] == 0.9 + assert span["data"][SPANDATA.ERROR_TYPE] == "AccessDeniedException" assert span["data"][SPANDATA.HTTP_STATUS_CODE] == 403 assert span["data"][SPANDATA.AWS_REQUEST_ID] == "test-id"