Skip to content

Commit 69b90e6

Browse files
committed
test: Move conversation ID tests to their own file
1 parent 7024d19 commit 69b90e6

2 files changed

Lines changed: 191 additions & 184 deletions

File tree

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import pytest
2+
3+
import sentry_sdk
4+
from sentry_sdk import start_span
5+
6+
7+
def test_conversation_id_propagates_to_span_with_gen_ai_operation_name(
8+
self, sentry_init, capture_events
9+
):
10+
"""Span with gen_ai.operation.name data should get conversation_id."""
11+
sentry_init(traces_sample_rate=1.0)
12+
events = capture_events()
13+
14+
scope = sentry_sdk.get_current_scope()
15+
scope.set_conversation_id("conv-op-name-test")
16+
17+
with sentry_sdk.start_transaction(name="test-tx"):
18+
with start_span(op="http.client") as span:
19+
span.set_data("gen_ai.operation.name", "chat")
20+
21+
(event,) = events
22+
span_data = event["spans"][0]["data"]
23+
assert span_data.get("gen_ai.conversation.id") == "conv-op-name-test"
24+
25+
26+
def test_conversation_id_propagates_to_span_with_ai_op(
27+
self, sentry_init, capture_events
28+
):
29+
"""Span with ai.* op should get conversation_id."""
30+
sentry_init(traces_sample_rate=1.0)
31+
events = capture_events()
32+
33+
scope = sentry_sdk.get_current_scope()
34+
scope.set_conversation_id("conv-ai-op-test")
35+
36+
with sentry_sdk.start_transaction(name="test-tx"):
37+
with start_span(op="ai.chat.completions"):
38+
pass
39+
40+
(event,) = events
41+
span_data = event["spans"][0]["data"]
42+
assert span_data.get("gen_ai.conversation.id") == "conv-ai-op-test"
43+
44+
45+
@pytest.mark.parametrize("stream_gen_ai_spans", [True, False])
46+
def test_conversation_id_propagates_to_span_with_gen_ai_op(
47+
self, sentry_init, capture_events, capture_items, stream_gen_ai_spans
48+
):
49+
"""Span with gen_ai.* op should get conversation_id."""
50+
sentry_init(
51+
traces_sample_rate=1.0,
52+
stream_gen_ai_spans=stream_gen_ai_spans,
53+
)
54+
55+
if stream_gen_ai_spans:
56+
items = capture_items("span")
57+
58+
scope = sentry_sdk.get_current_scope()
59+
scope.set_conversation_id("conv-gen-ai-op-test")
60+
61+
with sentry_sdk.start_transaction(name="test-tx"):
62+
with start_span(op="gen_ai.invoke_agent"):
63+
pass
64+
65+
spans = [item.payload for item in items if item.type == "span"]
66+
span_data = spans[0]["attributes"]
67+
else:
68+
events = capture_events()
69+
70+
scope = sentry_sdk.get_current_scope()
71+
scope.set_conversation_id("conv-gen-ai-op-test")
72+
73+
with sentry_sdk.start_transaction(name="test-tx"):
74+
with start_span(op="gen_ai.invoke_agent"):
75+
pass
76+
77+
(event,) = events
78+
span_data = event["spans"][0]["data"]
79+
80+
assert span_data.get("gen_ai.conversation.id") == "conv-gen-ai-op-test"
81+
82+
83+
def test_conversation_id_not_propagated_to_non_ai_span(
84+
self, sentry_init, capture_events
85+
):
86+
"""Non-AI span should NOT get conversation_id."""
87+
sentry_init(traces_sample_rate=1.0)
88+
events = capture_events()
89+
90+
scope = sentry_sdk.get_current_scope()
91+
scope.set_conversation_id("conv-should-not-appear")
92+
93+
with sentry_sdk.start_transaction(name="test-tx"):
94+
with start_span(op="http.client") as span:
95+
span.set_data("some.other.data", "value")
96+
97+
(event,) = events
98+
span_data = event["spans"][0]["data"]
99+
assert "gen_ai.conversation.id" not in span_data
100+
101+
102+
def test_conversation_id_not_propagated_when_not_set(self, sentry_init, capture_events):
103+
"""AI span should not have conversation_id if not set on scope."""
104+
sentry_init(traces_sample_rate=1.0)
105+
events = capture_events()
106+
107+
# Ensure no conversation_id is set
108+
scope = sentry_sdk.get_current_scope()
109+
scope.remove_conversation_id()
110+
111+
with sentry_sdk.start_transaction(name="test-tx"):
112+
with start_span(op="ai.chat.completions"):
113+
pass
114+
115+
(event,) = events
116+
span_data = event["spans"][0]["data"]
117+
assert "gen_ai.conversation.id" not in span_data
118+
119+
120+
def test_conversation_id_not_propagated_to_span_without_op(
121+
self, sentry_init, capture_events
122+
):
123+
"""Span without op and without gen_ai.operation.name should NOT get conversation_id."""
124+
sentry_init(traces_sample_rate=1.0)
125+
events = capture_events()
126+
127+
scope = sentry_sdk.get_current_scope()
128+
scope.set_conversation_id("conv-no-op-test")
129+
130+
with sentry_sdk.start_transaction(name="test-tx"):
131+
with start_span(name="unnamed-span") as span:
132+
span.set_data("regular.data", "value")
133+
134+
(event,) = events
135+
span_data = event["spans"][0]["data"]
136+
assert "gen_ai.conversation.id" not in span_data
137+
138+
139+
def test_conversation_id_propagates_with_gen_ai_operation_name_no_op(
140+
self, sentry_init, capture_events
141+
):
142+
"""Span with gen_ai.operation.name but no op should still get conversation_id."""
143+
sentry_init(traces_sample_rate=1.0)
144+
events = capture_events()
145+
146+
scope = sentry_sdk.get_current_scope()
147+
scope.set_conversation_id("conv-no-op-but-data-test")
148+
149+
with sentry_sdk.start_transaction(name="test-tx"):
150+
with start_span(name="unnamed-span") as span:
151+
span.set_data("gen_ai.operation.name", "embedding")
152+
153+
(event,) = events
154+
span_data = event["spans"][0]["data"]
155+
assert span_data.get("gen_ai.conversation.id") == "conv-no-op-but-data-test"
156+
157+
158+
def test_conversation_id_propagates_to_transaction_with_ai_op(
159+
self, sentry_init, capture_events
160+
):
161+
"""Transaction with ai.* op should get conversation_id."""
162+
sentry_init(traces_sample_rate=1.0)
163+
events = capture_events()
164+
165+
scope = sentry_sdk.get_current_scope()
166+
scope.set_conversation_id("conv-tx-ai-op-test")
167+
168+
with sentry_sdk.start_transaction(op="ai.workflow", name="AI Workflow"):
169+
pass
170+
171+
(event,) = events
172+
trace_data = event["contexts"]["trace"]["data"]
173+
assert trace_data.get("gen_ai.conversation.id") == "conv-tx-ai-op-test"
174+
175+
176+
def test_conversation_id_not_propagated_to_non_ai_transaction(
177+
self, sentry_init, capture_events
178+
):
179+
"""Non-AI transaction should NOT get conversation_id."""
180+
sentry_init(traces_sample_rate=1.0)
181+
events = capture_events()
182+
183+
scope = sentry_sdk.get_current_scope()
184+
scope.set_conversation_id("conv-tx-should-not-appear")
185+
186+
with sentry_sdk.start_transaction(op="http.server", name="HTTP Request"):
187+
pass
188+
189+
(event,) = events
190+
trace_data = event["contexts"]["trace"]["data"]
191+
assert "gen_ai.conversation.id" not in trace_data

tests/tracing/test_misc.py

Lines changed: 0 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -606,187 +606,3 @@ def test_update_current_span(sentry_init, capture_events):
606606
"thread.id": mock.ANY,
607607
"thread.name": mock.ANY,
608608
}
609-
610-
611-
class TestConversationIdPropagation:
612-
"""Tests for conversation_id propagation to AI spans."""
613-
614-
def test_conversation_id_propagates_to_span_with_gen_ai_operation_name(
615-
self, sentry_init, capture_events
616-
):
617-
"""Span with gen_ai.operation.name data should get conversation_id."""
618-
sentry_init(traces_sample_rate=1.0)
619-
events = capture_events()
620-
621-
scope = sentry_sdk.get_current_scope()
622-
scope.set_conversation_id("conv-op-name-test")
623-
624-
with sentry_sdk.start_transaction(name="test-tx"):
625-
with start_span(op="http.client") as span:
626-
span.set_data("gen_ai.operation.name", "chat")
627-
628-
(event,) = events
629-
span_data = event["spans"][0]["data"]
630-
assert span_data.get("gen_ai.conversation.id") == "conv-op-name-test"
631-
632-
def test_conversation_id_propagates_to_span_with_ai_op(
633-
self, sentry_init, capture_events
634-
):
635-
"""Span with ai.* op should get conversation_id."""
636-
sentry_init(traces_sample_rate=1.0)
637-
events = capture_events()
638-
639-
scope = sentry_sdk.get_current_scope()
640-
scope.set_conversation_id("conv-ai-op-test")
641-
642-
with sentry_sdk.start_transaction(name="test-tx"):
643-
with start_span(op="ai.chat.completions"):
644-
pass
645-
646-
(event,) = events
647-
span_data = event["spans"][0]["data"]
648-
assert span_data.get("gen_ai.conversation.id") == "conv-ai-op-test"
649-
650-
@pytest.mark.parametrize("stream_gen_ai_spans", [True, False])
651-
def test_conversation_id_propagates_to_span_with_gen_ai_op(
652-
self, sentry_init, capture_events, capture_items, stream_gen_ai_spans
653-
):
654-
"""Span with gen_ai.* op should get conversation_id."""
655-
sentry_init(
656-
traces_sample_rate=1.0,
657-
stream_gen_ai_spans=stream_gen_ai_spans,
658-
)
659-
660-
if stream_gen_ai_spans:
661-
items = capture_items("span")
662-
663-
scope = sentry_sdk.get_current_scope()
664-
scope.set_conversation_id("conv-gen-ai-op-test")
665-
666-
with sentry_sdk.start_transaction(name="test-tx"):
667-
with start_span(op="gen_ai.invoke_agent"):
668-
pass
669-
670-
spans = [item.payload for item in items if item.type == "span"]
671-
span_data = spans[0]["attributes"]
672-
else:
673-
events = capture_events()
674-
675-
scope = sentry_sdk.get_current_scope()
676-
scope.set_conversation_id("conv-gen-ai-op-test")
677-
678-
with sentry_sdk.start_transaction(name="test-tx"):
679-
with start_span(op="gen_ai.invoke_agent"):
680-
pass
681-
682-
(event,) = events
683-
span_data = event["spans"][0]["data"]
684-
685-
assert span_data.get("gen_ai.conversation.id") == "conv-gen-ai-op-test"
686-
687-
def test_conversation_id_not_propagated_to_non_ai_span(
688-
self, sentry_init, capture_events
689-
):
690-
"""Non-AI span should NOT get conversation_id."""
691-
sentry_init(traces_sample_rate=1.0)
692-
events = capture_events()
693-
694-
scope = sentry_sdk.get_current_scope()
695-
scope.set_conversation_id("conv-should-not-appear")
696-
697-
with sentry_sdk.start_transaction(name="test-tx"):
698-
with start_span(op="http.client") as span:
699-
span.set_data("some.other.data", "value")
700-
701-
(event,) = events
702-
span_data = event["spans"][0]["data"]
703-
assert "gen_ai.conversation.id" not in span_data
704-
705-
def test_conversation_id_not_propagated_when_not_set(
706-
self, sentry_init, capture_events
707-
):
708-
"""AI span should not have conversation_id if not set on scope."""
709-
sentry_init(traces_sample_rate=1.0)
710-
events = capture_events()
711-
712-
# Ensure no conversation_id is set
713-
scope = sentry_sdk.get_current_scope()
714-
scope.remove_conversation_id()
715-
716-
with sentry_sdk.start_transaction(name="test-tx"):
717-
with start_span(op="ai.chat.completions"):
718-
pass
719-
720-
(event,) = events
721-
span_data = event["spans"][0]["data"]
722-
assert "gen_ai.conversation.id" not in span_data
723-
724-
def test_conversation_id_not_propagated_to_span_without_op(
725-
self, sentry_init, capture_events
726-
):
727-
"""Span without op and without gen_ai.operation.name should NOT get conversation_id."""
728-
sentry_init(traces_sample_rate=1.0)
729-
events = capture_events()
730-
731-
scope = sentry_sdk.get_current_scope()
732-
scope.set_conversation_id("conv-no-op-test")
733-
734-
with sentry_sdk.start_transaction(name="test-tx"):
735-
with start_span(name="unnamed-span") as span:
736-
span.set_data("regular.data", "value")
737-
738-
(event,) = events
739-
span_data = event["spans"][0]["data"]
740-
assert "gen_ai.conversation.id" not in span_data
741-
742-
def test_conversation_id_propagates_with_gen_ai_operation_name_no_op(
743-
self, sentry_init, capture_events
744-
):
745-
"""Span with gen_ai.operation.name but no op should still get conversation_id."""
746-
sentry_init(traces_sample_rate=1.0)
747-
events = capture_events()
748-
749-
scope = sentry_sdk.get_current_scope()
750-
scope.set_conversation_id("conv-no-op-but-data-test")
751-
752-
with sentry_sdk.start_transaction(name="test-tx"):
753-
with start_span(name="unnamed-span") as span:
754-
span.set_data("gen_ai.operation.name", "embedding")
755-
756-
(event,) = events
757-
span_data = event["spans"][0]["data"]
758-
assert span_data.get("gen_ai.conversation.id") == "conv-no-op-but-data-test"
759-
760-
def test_conversation_id_propagates_to_transaction_with_ai_op(
761-
self, sentry_init, capture_events
762-
):
763-
"""Transaction with ai.* op should get conversation_id."""
764-
sentry_init(traces_sample_rate=1.0)
765-
events = capture_events()
766-
767-
scope = sentry_sdk.get_current_scope()
768-
scope.set_conversation_id("conv-tx-ai-op-test")
769-
770-
with sentry_sdk.start_transaction(op="ai.workflow", name="AI Workflow"):
771-
pass
772-
773-
(event,) = events
774-
trace_data = event["contexts"]["trace"]["data"]
775-
assert trace_data.get("gen_ai.conversation.id") == "conv-tx-ai-op-test"
776-
777-
def test_conversation_id_not_propagated_to_non_ai_transaction(
778-
self, sentry_init, capture_events
779-
):
780-
"""Non-AI transaction should NOT get conversation_id."""
781-
sentry_init(traces_sample_rate=1.0)
782-
events = capture_events()
783-
784-
scope = sentry_sdk.get_current_scope()
785-
scope.set_conversation_id("conv-tx-should-not-appear")
786-
787-
with sentry_sdk.start_transaction(op="http.server", name="HTTP Request"):
788-
pass
789-
790-
(event,) = events
791-
trace_data = event["contexts"]["trace"]["data"]
792-
assert "gen_ai.conversation.id" not in trace_data

0 commit comments

Comments
 (0)