Skip to content

Commit 2b86d05

Browse files
committed
Merge branch 'master' into antonpirker/better-aws-tests
2 parents 1fa3a6f + c557b56 commit 2b86d05

File tree

6 files changed

+100
-12
lines changed

6 files changed

+100
-12
lines changed

sentry_sdk/integrations/anthropic.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ def _collect_ai_data(event, input_tokens, output_tokens, content_blocks):
101101
elif event.type == "content_block_delta":
102102
if hasattr(event.delta, "text"):
103103
content_blocks.append(event.delta.text)
104+
elif hasattr(event.delta, "partial_json"):
105+
content_blocks.append(event.delta.partial_json)
104106
elif event.type == "content_block_stop":
105107
pass
106108
elif event.type == "message_delta":

sentry_sdk/integrations/aws_lambda.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ def sentry_init_error(*args, **kwargs):
6161

6262
else:
6363
# Fall back to AWS lambdas JSON representation of the error
64-
sentry_event = _event_from_error_json(json.loads(args[1]))
64+
error_info = args[1]
65+
if isinstance(error_info, str):
66+
error_info = json.loads(error_info)
67+
sentry_event = _event_from_error_json(error_info)
6568
sentry_sdk.capture_event(sentry_event)
6669

6770
return init_error(*args, **kwargs)

sentry_sdk/profiler/__init__.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
from sentry_sdk.profiler.continuous_profiler import start_profiler, stop_profiler
1+
from sentry_sdk.profiler.continuous_profiler import (
2+
start_profile_session,
3+
start_profiler,
4+
stop_profile_session,
5+
stop_profiler,
6+
)
27
from sentry_sdk.profiler.transaction_profiler import (
38
MAX_PROFILE_DURATION_NS,
49
PROFILE_MINIMUM_SAMPLES,
@@ -20,8 +25,10 @@
2025
)
2126

2227
__all__ = [
23-
"start_profiler",
24-
"stop_profiler",
28+
"start_profile_session",
29+
"start_profiler", # TODO: Deprecate this in favor of `start_profile_session`
30+
"stop_profile_session",
31+
"stop_profiler", # TODO: Deprecate this in favor of `stop_profile_session`
2532
# DEPRECATED: The following was re-exported for backwards compatibility. It
2633
# will be removed from sentry_sdk.profiler in a future release.
2734
"MAX_PROFILE_DURATION_NS",

sentry_sdk/scope.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,7 @@ def update_from_kwargs(
15681568
user=None, # type: Optional[Any]
15691569
level=None, # type: Optional[LogLevelStr]
15701570
extras=None, # type: Optional[Dict[str, Any]]
1571-
contexts=None, # type: Optional[Dict[str, Any]]
1571+
contexts=None, # type: Optional[Dict[str, Dict[str, Any]]]
15721572
tags=None, # type: Optional[Dict[str, str]]
15731573
fingerprint=None, # type: Optional[List[str]]
15741574
):

tests/integrations/anthropic/test_anthropic.py

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from unittest import mock
22

3+
34
try:
45
from unittest.mock import AsyncMock
56
except ImportError:
@@ -10,7 +11,7 @@ async def __call__(self, *args, **kwargs):
1011

1112

1213
import pytest
13-
from anthropic import AsyncAnthropic, Anthropic, AnthropicError, AsyncStream, Stream
14+
from anthropic import Anthropic, AnthropicError, AsyncAnthropic, AsyncStream, Stream
1415
from anthropic.types import MessageDeltaUsage, TextDelta, Usage
1516
from anthropic.types.content_block_delta_event import ContentBlockDeltaEvent
1617
from anthropic.types.content_block_start_event import ContentBlockStartEvent
@@ -19,6 +20,7 @@ async def __call__(self, *args, **kwargs):
1920
from anthropic.types.message_delta_event import MessageDeltaEvent
2021
from anthropic.types.message_start_event import MessageStartEvent
2122

23+
from sentry_sdk.integrations.anthropic import _add_ai_data_to_span, _collect_ai_data
2224
from sentry_sdk.utils import package_version
2325

2426
try:
@@ -42,7 +44,7 @@ async def __call__(self, *args, **kwargs):
4244
except ImportError:
4345
from anthropic.types.content_block import ContentBlock as TextBlock
4446

45-
from sentry_sdk import start_transaction
47+
from sentry_sdk import start_transaction, start_span
4648
from sentry_sdk.consts import OP, SPANDATA
4749
from sentry_sdk.integrations.anthropic import AnthropicIntegration
4850

@@ -517,9 +519,8 @@ def test_streaming_create_message_with_input_json_delta(
517519
if send_default_pii and include_prompts:
518520
assert span["data"][SPANDATA.AI_INPUT_MESSAGES] == messages
519521
assert span["data"][SPANDATA.AI_RESPONSES] == [
520-
{"text": "", "type": "text"}
521-
] # we do not record InputJSONDelta because it could contain PII
522-
522+
{"text": "{'location': 'San Francisco, CA'}", "type": "text"}
523+
]
523524
else:
524525
assert SPANDATA.AI_INPUT_MESSAGES not in span["data"]
525526
assert SPANDATA.AI_RESPONSES not in span["data"]
@@ -654,8 +655,8 @@ async def test_streaming_create_message_with_input_json_delta_async(
654655
if send_default_pii and include_prompts:
655656
assert span["data"][SPANDATA.AI_INPUT_MESSAGES] == messages
656657
assert span["data"][SPANDATA.AI_RESPONSES] == [
657-
{"text": "", "type": "text"}
658-
] # we do not record InputJSONDelta because it could contain PII
658+
{"text": "{'location': 'San Francisco, CA'}", "type": "text"}
659+
]
659660

660661
else:
661662
assert SPANDATA.AI_INPUT_MESSAGES not in span["data"]
@@ -757,3 +758,59 @@ async def test_span_origin_async(sentry_init, capture_events):
757758

758759
assert event["contexts"]["trace"]["origin"] == "manual"
759760
assert event["spans"][0]["origin"] == "auto.ai.anthropic"
761+
762+
763+
@pytest.mark.skipif(
764+
ANTHROPIC_VERSION < (0, 27),
765+
reason="Versions <0.27.0 do not include InputJSONDelta.",
766+
)
767+
def test_collect_ai_data_with_input_json_delta():
768+
event = ContentBlockDeltaEvent(
769+
delta=InputJSONDelta(partial_json="test", type="input_json_delta"),
770+
index=0,
771+
type="content_block_delta",
772+
)
773+
774+
input_tokens = 10
775+
output_tokens = 20
776+
content_blocks = []
777+
778+
new_input_tokens, new_output_tokens, new_content_blocks = _collect_ai_data(
779+
event, input_tokens, output_tokens, content_blocks
780+
)
781+
782+
assert new_input_tokens == input_tokens
783+
assert new_output_tokens == output_tokens
784+
assert new_content_blocks == ["test"]
785+
786+
787+
@pytest.mark.skipif(
788+
ANTHROPIC_VERSION < (0, 27),
789+
reason="Versions <0.27.0 do not include InputJSONDelta.",
790+
)
791+
def test_add_ai_data_to_span_with_input_json_delta(sentry_init):
792+
sentry_init(
793+
integrations=[AnthropicIntegration(include_prompts=True)],
794+
traces_sample_rate=1.0,
795+
send_default_pii=True,
796+
)
797+
798+
with start_transaction(name="test"):
799+
span = start_span()
800+
integration = AnthropicIntegration()
801+
802+
_add_ai_data_to_span(
803+
span,
804+
integration,
805+
input_tokens=10,
806+
output_tokens=20,
807+
content_blocks=["{'test': 'data',", "'more': 'json'}"],
808+
)
809+
810+
assert span._data.get(SPANDATA.AI_RESPONSES) == [
811+
{"type": "text", "text": "{'test': 'data','more': 'json'}"}
812+
]
813+
assert span._data.get("ai.streaming") is True
814+
assert span._measurements.get("ai_prompt_tokens_used")["value"] == 10
815+
assert span._measurements.get("ai_completion_tokens_used")["value"] == 20
816+
assert span._measurements.get("ai_total_tokens_used")["value"] == 30

tests/test_feature_flags.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,25 @@ def test_flag_tracking():
170170
{"flag": "f", "result": False},
171171
]
172172

173+
# Test updates
174+
buffer.set("e", True)
175+
buffer.set("e", False)
176+
buffer.set("e", True)
177+
flags = buffer.get()
178+
assert flags == [
179+
{"flag": "d", "result": False},
180+
{"flag": "f", "result": False},
181+
{"flag": "e", "result": True},
182+
]
183+
184+
buffer.set("d", True)
185+
flags = buffer.get()
186+
assert flags == [
187+
{"flag": "f", "result": False},
188+
{"flag": "e", "result": True},
189+
{"flag": "d", "result": True},
190+
]
191+
173192

174193
def test_flag_buffer_concurrent_access():
175194
buffer = FlagBuffer(capacity=100)

0 commit comments

Comments
 (0)