Skip to content

Commit 3e1cb35

Browse files
ai monitoring tests
1 parent 67b768a commit 3e1cb35

1 file changed

Lines changed: 46 additions & 134 deletions

File tree

tests/test_ai_monitoring.py

Lines changed: 46 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111
)
1212
from sentry_sdk.ai.monitoring import ai_track
1313
from sentry_sdk.ai.utils import (
14-
MAX_GEN_AI_MESSAGE_BYTES,
1514
MAX_SINGLE_MESSAGE_CONTENT_CHARS,
1615
set_data_normalized,
1716
truncate_and_annotate_messages,
18-
truncate_messages_by_size,
19-
_find_truncation_index,
2017
parse_data_uri,
2118
redact_blob_message_parts,
2219
get_modality_from_mime_type,
@@ -222,127 +219,7 @@ def large_messages():
222219
]
223220

224221

225-
class TestTruncateMessagesBySize:
226-
def test_no_truncation_needed(self, sample_messages):
227-
"""Test that messages under the limit are not truncated"""
228-
result, truncation_index = truncate_messages_by_size(
229-
sample_messages, max_bytes=MAX_GEN_AI_MESSAGE_BYTES
230-
)
231-
assert len(result) == len(sample_messages)
232-
assert result == sample_messages
233-
assert truncation_index == 0
234-
235-
def test_truncation_removes_oldest_first(self, large_messages):
236-
"""Test that oldest messages are removed first during truncation"""
237-
small_limit = 3000
238-
result, truncation_index = truncate_messages_by_size(
239-
large_messages, max_bytes=small_limit
240-
)
241-
assert len(result) < len(large_messages)
242-
243-
assert result[-1] == large_messages[-1]
244-
assert truncation_index == len(large_messages) - len(result)
245-
246-
def test_empty_messages_list(self):
247-
"""Test handling of empty messages list"""
248-
result, truncation_index = truncate_messages_by_size(
249-
[], max_bytes=MAX_GEN_AI_MESSAGE_BYTES // 500
250-
)
251-
assert result == []
252-
assert truncation_index == 0
253-
254-
def test_find_truncation_index(
255-
self,
256-
):
257-
"""Test that the truncation index is found correctly"""
258-
# when represented in JSON, these are each 7 bytes long
259-
messages = ["A" * 5, "B" * 5, "C" * 5, "D" * 5, "E" * 5]
260-
truncation_index = _find_truncation_index(messages, 20)
261-
assert truncation_index == 3
262-
assert messages[truncation_index:] == ["D" * 5, "E" * 5]
263-
264-
messages = ["A" * 5, "B" * 5, "C" * 5, "D" * 5, "E" * 5]
265-
truncation_index = _find_truncation_index(messages, 40)
266-
assert truncation_index == 0
267-
assert messages[truncation_index:] == [
268-
"A" * 5,
269-
"B" * 5,
270-
"C" * 5,
271-
"D" * 5,
272-
"E" * 5,
273-
]
274-
275-
def test_progressive_truncation(self, large_messages):
276-
"""Test that truncation works progressively with different limits"""
277-
limits = [
278-
MAX_GEN_AI_MESSAGE_BYTES // 5,
279-
MAX_GEN_AI_MESSAGE_BYTES // 10,
280-
MAX_GEN_AI_MESSAGE_BYTES // 25,
281-
MAX_GEN_AI_MESSAGE_BYTES // 100,
282-
MAX_GEN_AI_MESSAGE_BYTES // 500,
283-
]
284-
prev_count = len(large_messages)
285-
286-
for limit in limits:
287-
result = truncate_messages_by_size(large_messages, max_bytes=limit)
288-
current_count = len(result)
289-
290-
assert current_count <= prev_count
291-
assert current_count >= 1
292-
prev_count = current_count
293-
294-
def test_single_message_truncation(self):
295-
large_content = "This is a very long message. " * 10_000
296-
297-
messages = [
298-
{"role": "system", "content": "You are a helpful assistant."},
299-
{"role": "user", "content": large_content},
300-
]
301-
302-
result, truncation_index = truncate_messages_by_size(
303-
messages, max_single_message_chars=MAX_SINGLE_MESSAGE_CONTENT_CHARS
304-
)
305-
306-
assert len(result) == 1
307-
assert (
308-
len(result[0]["content"].rstrip("...")) <= MAX_SINGLE_MESSAGE_CONTENT_CHARS
309-
)
310-
311-
# If the last message is too large, the system message is not present
312-
system_msgs = [m for m in result if m.get("role") == "system"]
313-
assert len(system_msgs) == 0
314-
315-
# Confirm the user message is truncated with '...'
316-
user_msgs = [m for m in result if m.get("role") == "user"]
317-
assert len(user_msgs) == 1
318-
assert user_msgs[0]["content"].endswith("...")
319-
assert len(user_msgs[0]["content"]) < len(large_content)
320-
321-
322222
class TestTruncateAndAnnotateMessages:
323-
def test_no_truncation_returns_list(self, sample_messages):
324-
class MockSpan:
325-
def __init__(self):
326-
self.span_id = "test_span_id"
327-
self.data = {}
328-
329-
def set_data(self, key, value):
330-
self.data[key] = value
331-
332-
class MockScope:
333-
def __init__(self):
334-
self._gen_ai_original_message_count = {}
335-
336-
span = MockSpan()
337-
scope = MockScope()
338-
result = truncate_and_annotate_messages(sample_messages, span, scope)
339-
340-
assert isinstance(result, list)
341-
assert not isinstance(result, AnnotatedValue)
342-
assert len(result) == len(sample_messages)
343-
assert result == sample_messages
344-
assert span.span_id not in scope._gen_ai_original_message_count
345-
346223
def test_truncation_sets_metadata_on_scope(self, large_messages):
347224
class MockSpan:
348225
def __init__(self):
@@ -361,7 +238,7 @@ def __init__(self):
361238
scope = MockScope()
362239
original_count = len(large_messages)
363240
result = truncate_and_annotate_messages(
364-
large_messages, span, scope, max_bytes=small_limit
241+
large_messages, span, scope, max_single_message_chars=small_limit
365242
)
366243

367244
assert isinstance(result, list)
@@ -388,7 +265,7 @@ def __init__(self):
388265
scope = MockScope()
389266

390267
result = truncate_and_annotate_messages(
391-
large_messages, span, scope, max_bytes=small_limit
268+
large_messages, span, scope, max_single_message_chars=small_limit
392269
)
393270

394271
assert scope._gen_ai_original_message_count[span.span_id] == original_count
@@ -415,6 +292,47 @@ def __init__(self):
415292
result = truncate_and_annotate_messages(None, span, scope)
416293
assert result is None
417294

295+
def test_single_message_truncation(self, large_messages):
296+
class MockSpan:
297+
def __init__(self):
298+
self.span_id = "test_span_id"
299+
self.data = {}
300+
301+
def set_data(self, key, value):
302+
self.data[key] = value
303+
304+
class MockScope:
305+
def __init__(self):
306+
self._gen_ai_original_message_count = {}
307+
308+
large_content = "This is a very long message. " * 10_000
309+
310+
messages = [
311+
{"role": "system", "content": "You are a helpful assistant."},
312+
{"role": "user", "content": large_content},
313+
]
314+
315+
span = MockSpan()
316+
scope = MockScope()
317+
result = truncate_and_annotate_messages(
318+
messages,
319+
span,
320+
scope,
321+
max_single_message_chars=MAX_SINGLE_MESSAGE_CONTENT_CHARS,
322+
)
323+
assert result is not None
324+
325+
assert len(result) == 1
326+
assert (
327+
len(result[0]["content"].rstrip("...")) <= MAX_SINGLE_MESSAGE_CONTENT_CHARS
328+
)
329+
330+
# Confirm the user message is truncated with '...'
331+
user_msgs = [m for m in result if m.get("role") == "user"]
332+
assert len(user_msgs) == 1
333+
assert user_msgs[0]["content"].endswith("...")
334+
assert len(user_msgs[0]["content"]) < len(large_content)
335+
418336
def test_truncated_messages_newest_first(self, large_messages):
419337
class MockSpan:
420338
def __init__(self):
@@ -432,7 +350,7 @@ def __init__(self):
432350
span = MockSpan()
433351
scope = MockScope()
434352
result = truncate_and_annotate_messages(
435-
large_messages, span, scope, max_bytes=small_limit
353+
large_messages, span, scope, max_single_message_chars=small_limit
436354
)
437355

438356
assert isinstance(result, list)
@@ -500,15 +418,12 @@ class MockScope:
500418
def __init__(self):
501419
self._gen_ai_original_message_count = {}
502420

503-
small_limit = 3000
504421
span = MockSpan()
505422
scope = MockScope()
506423
original_count = len(large_messages)
507424

508425
# Simulate what integrations do
509-
truncated_messages = truncate_and_annotate_messages(
510-
large_messages, span, scope, max_bytes=small_limit
511-
)
426+
truncated_messages = truncate_and_annotate_messages(large_messages, span, scope)
512427
span.set_data(SPANDATA.GEN_AI_REQUEST_MESSAGES, truncated_messages)
513428

514429
# Verify metadata was set on scope
@@ -557,14 +472,11 @@ class MockScope:
557472
def __init__(self):
558473
self._gen_ai_original_message_count = {}
559474

560-
small_limit = 3000
561475
span = MockSpan()
562476
scope = MockScope()
563477
original_message_count = len(large_messages)
564478

565-
truncated_messages = truncate_and_annotate_messages(
566-
large_messages, span, scope, max_bytes=small_limit
567-
)
479+
truncated_messages = truncate_and_annotate_messages(large_messages, span, scope)
568480

569481
assert len(truncated_messages) < original_message_count
570482

0 commit comments

Comments
 (0)