1- import weakref
2- import gc
31import re
42import pytest
53import random
64
75import sentry_sdk
86from sentry_sdk import (
97 capture_message ,
8+ continue_trace ,
109 start_span ,
11- start_transaction ,
1210)
1311from sentry_sdk .consts import SPANSTATUS
1412from sentry_sdk .transport import Transport
15- from sentry_sdk .tracing import Transaction
1613
1714
1815@pytest .mark .parametrize ("sample_rate" , [0.0 , 1.0 ])
1916def test_basic (sentry_init , capture_events , sample_rate ):
2017 sentry_init (traces_sample_rate = sample_rate )
2118 events = capture_events ()
2219
23- with start_transaction (name = "hi" ) as transaction :
24- transaction .set_status (SPANSTATUS .OK )
20+ with start_span (name = "hi" ) as root_span :
21+ root_span .set_status (SPANSTATUS .OK )
2522 with pytest .raises (ZeroDivisionError ):
2623 with start_span (op = "foo" , name = "foodesc" ):
2724 1 / 0
@@ -39,21 +36,23 @@ def test_basic(sentry_init, capture_events, sample_rate):
3936 span1 , span2 = event ["spans" ]
4037 parent_span = event
4138 assert span1 ["tags" ]["status" ] == "internal_error"
39+ assert span1 ["status" ] == "internal_error"
4240 assert span1 ["op" ] == "foo"
4341 assert span1 ["description" ] == "foodesc"
4442 assert "status" not in span2 .get ("tags" , {})
4543 assert span2 ["op" ] == "bar"
4644 assert span2 ["description" ] == "bardesc"
4745 assert parent_span ["transaction" ] == "hi"
48- assert "status" not in event [ "tags" ]
46+ assert "status" not in event . get ( "tags" , {})
4947 assert event ["contexts" ]["trace" ]["status" ] == "ok"
5048 else :
5149 assert not events
5250
5351
54- @pytest .mark .parametrize ("sampled" , [True , False , None ])
5552@pytest .mark .parametrize ("sample_rate" , [0.0 , 1.0 ])
56- def test_continue_from_headers (sentry_init , capture_envelopes , sampled , sample_rate ):
53+ def test_continue_trace (
54+ sentry_init , capture_envelopes , sample_rate , SortedBaggage
55+ ): # noqa:N803
5756 """
5857 Ensure data is actually passed along via headers, and that they are read
5958 correctly.
@@ -62,55 +61,41 @@ def test_continue_from_headers(sentry_init, capture_envelopes, sampled, sample_r
6261 envelopes = capture_envelopes ()
6362
6463 # make a parent transaction (normally this would be in a different service)
65- with start_transaction (name = "hi" , sampled = True if sample_rate == 0 else None ):
66- with start_span () as old_span :
67- old_span .sampled = sampled
68- headers = dict (
69- sentry_sdk .get_current_scope ().iter_trace_propagation_headers (old_span )
70- )
71- headers ["baggage" ] = (
72- "other-vendor-value-1=foo;bar;baz, "
73- "sentry-trace_id=771a43a4192642f0b136d5159a501700, "
74- "sentry-public_key=49d0f7386ad645858ae85020e393bef3, "
75- "sentry-sample_rate=0.01337, sentry-user_id=Amelie, "
76- "other-vendor-value-2=foo;bar;"
77- )
64+ with start_span (name = "hi" ):
65+ with start_span (name = "inner" ) as old_span :
66+ headers = dict (old_span .iter_headers ())
67+ assert headers ["sentry-trace" ]
68+ assert headers ["baggage" ]
7869
7970 # child transaction, to prove that we can read 'sentry-trace' header data correctly
80- child_transaction = Transaction .continue_from_headers (headers , name = "WRONG" )
81- assert child_transaction is not None
82- assert child_transaction .parent_sampled == sampled
83- assert child_transaction .trace_id == old_span .trace_id
84- assert child_transaction .same_process_as_parent is False
85- assert child_transaction .parent_span_id == old_span .span_id
86- assert child_transaction .span_id != old_span .span_id
87-
88- baggage = child_transaction ._baggage
89- assert baggage
90- assert not baggage .mutable
91- assert baggage .sentry_items == {
92- "public_key" : "49d0f7386ad645858ae85020e393bef3" ,
93- "trace_id" : "771a43a4192642f0b136d5159a501700" ,
94- "user_id" : "Amelie" ,
95- "sample_rate" : "0.01337" ,
96- }
97-
98- # add child transaction to the scope, to show that the captured message will
99- # be tagged with the trace id (since it happens while the transaction is
100- # open)
101- with start_transaction (child_transaction ):
102- # change the transaction name from "WRONG" to make sure the change
103- # is reflected in the final data
104- sentry_sdk .get_current_scope ().transaction = "ho"
105- capture_message ("hello" )
71+ with continue_trace (headers ):
72+ with start_span (name = "WRONG" ) as child_root_span :
73+ assert child_root_span is not None
74+ assert child_root_span .sampled == (sample_rate == 1.0 )
75+ if child_root_span .sampled :
76+ assert child_root_span .parent_span_id == old_span .span_id
77+ assert child_root_span .trace_id == old_span .trace_id
78+ assert child_root_span .span_id != old_span .span_id
79+
80+ baggage = child_root_span .get_baggage ()
81+ assert baggage .serialize () == SortedBaggage (headers ["baggage" ])
82+
83+ # change the transaction name from "WRONG" to make sure the change
84+ # is reflected in the final data
85+ sentry_sdk .get_current_scope ().set_transaction_name ("ho" )
86+ # to show that the captured message will be tagged with the trace id
87+ # (since it happens while the transaction is open)
88+ capture_message ("hello" )
10689
10790 # in this case the child transaction won't be captured
108- if sampled is False or (sample_rate == 0 and sampled is None ):
109- trace1 , message = envelopes
91+ # but message follows twp spec
92+ if sample_rate == 0.0 :
93+ (message ,) = envelopes
11094 message_payload = message .get_event ()
111- trace1_payload = trace1 .get_transaction_event ()
112-
113- assert trace1_payload ["transaction" ] == "hi"
95+ assert message_payload ["transaction" ] == "ho"
96+ assert (
97+ child_root_span .trace_id == message_payload ["contexts" ]["trace" ]["trace_id" ]
98+ )
11499 else :
115100 trace1 , message , trace2 = envelopes
116101 trace1_payload = trace1 .get_transaction_event ()
@@ -123,56 +108,43 @@ def test_continue_from_headers(sentry_init, capture_envelopes, sampled, sample_r
123108 assert (
124109 trace1_payload ["contexts" ]["trace" ]["trace_id" ]
125110 == trace2_payload ["contexts" ]["trace" ]["trace_id" ]
126- == child_transaction .trace_id
111+ == child_root_span .trace_id
127112 == message_payload ["contexts" ]["trace" ]["trace_id" ]
128113 )
129114
130115 assert trace2 .headers ["trace" ] == baggage .dynamic_sampling_context ()
131- assert trace2 .headers ["trace" ] == {
132- "public_key" : "49d0f7386ad645858ae85020e393bef3" ,
133- "trace_id" : "771a43a4192642f0b136d5159a501700" ,
134- "user_id" : "Amelie" ,
135- "sample_rate" : "0.01337" ,
136- }
137116
138117 assert message_payload ["message" ] == "hello"
139118
140119
141120@pytest .mark .parametrize ("sample_rate" , [0.5 , 1.0 ])
142121def test_dynamic_sampling_head_sdk_creates_dsc (
143- sentry_init , capture_envelopes , sample_rate , monkeypatch
122+ sentry_init ,
123+ capture_envelopes ,
124+ sample_rate ,
125+ monkeypatch ,
126+ SortedBaggage , # noqa: N803
144127):
145128 sentry_init (traces_sample_rate = sample_rate , release = "foo" )
146129 envelopes = capture_envelopes ()
147130
148131 # make sure transaction is sampled for both cases
149132 monkeypatch .setattr (random , "random" , lambda : 0.1 )
150133
151- transaction = Transaction .continue_from_headers ({}, name = "Head SDK tx" )
152-
153- # will create empty mutable baggage
154- baggage = transaction ._baggage
155- assert baggage
156- assert baggage .mutable
157- assert baggage .sentry_items == {}
158- assert baggage .third_party_items == ""
159-
160- with start_transaction (transaction ):
161- with start_span (op = "foo" , name = "foodesc" ):
162- pass
134+ with continue_trace ({}):
135+ with start_span (name = "Head SDK tx" ):
136+ with start_span (op = "foo" , name = "foodesc" ) as span :
137+ baggage = span .get_baggage ()
163138
164- # finish will create a new baggage entry
165- baggage = transaction ._baggage
166- trace_id = transaction .trace_id
139+ trace_id = span .trace_id
167140
168141 assert baggage
169- assert not baggage .mutable
170142 assert baggage .third_party_items == ""
171143 assert baggage .sentry_items == {
172144 "environment" : "production" ,
173145 "release" : "foo" ,
174146 "sample_rate" : str (sample_rate ),
175- "sampled" : "true" if transaction .sampled else "false" ,
147+ "sampled" : "true" if span .sampled else "false" ,
176148 "transaction" : "Head SDK tx" ,
177149 "trace_id" : trace_id ,
178150 }
@@ -184,59 +156,30 @@ def test_dynamic_sampling_head_sdk_creates_dsc(
184156 "sentry-transaction=Head%%20SDK%%20tx,"
185157 "sentry-sample_rate=%s,"
186158 "sentry-sampled=%s"
187- % (trace_id , sample_rate , "true" if transaction .sampled else "false" )
159+ % (trace_id , sample_rate , "true" if span .sampled else "false" )
188160 )
189- assert baggage .serialize () == expected_baggage
161+ assert baggage .serialize () == SortedBaggage ( expected_baggage )
190162
191163 (envelope ,) = envelopes
192164 assert envelope .headers ["trace" ] == baggage .dynamic_sampling_context ()
193165 assert envelope .headers ["trace" ] == {
194166 "environment" : "production" ,
195167 "release" : "foo" ,
196168 "sample_rate" : str (sample_rate ),
197- "sampled" : "true" if transaction .sampled else "false" ,
169+ "sampled" : "true" if span .sampled else "false" ,
198170 "transaction" : "Head SDK tx" ,
199171 "trace_id" : trace_id ,
200172 }
201173
202174
203- @pytest .mark .parametrize (
204- "args,expected_refcount" ,
205- [({"traces_sample_rate" : 1.0 }, 100 ), ({"traces_sample_rate" : 0.0 }, 0 )],
206- )
207- def test_memory_usage (sentry_init , capture_events , args , expected_refcount ):
208- sentry_init (** args )
209-
210- references = weakref .WeakSet ()
211-
212- with start_transaction (name = "hi" ):
213- for i in range (100 ):
214- with start_span (op = "helloworld" , name = "hi {}" .format (i )) as span :
215-
216- def foo ():
217- pass
218-
219- references .add (foo )
220- span .set_tag ("foo" , foo )
221- pass
222-
223- del foo
224- del span
225-
226- # required only for pypy (cpython frees immediately)
227- gc .collect ()
228-
229- assert len (references ) == expected_refcount
230-
231-
232175def test_transactions_do_not_go_through_before_send (sentry_init , capture_events ):
233176 def before_send (event , hint ):
234177 raise RuntimeError ("should not be called" )
235178
236179 sentry_init (traces_sample_rate = 1.0 , before_send = before_send )
237180 events = capture_events ()
238181
239- with start_transaction (name = "/" ):
182+ with start_span (name = "/" ):
240183 pass
241184
242185 assert len (events ) == 1
@@ -254,7 +197,7 @@ def capture_event(self, event):
254197 sentry_init (traces_sample_rate = 1 , transport = CustomTransport ())
255198 events = capture_events ()
256199
257- with start_transaction (name = "hi" ):
200+ with start_span (name = "hi" ):
258201 with start_span (op = "bar" , name = "bardesc" ):
259202 pass
260203
@@ -264,14 +207,14 @@ def capture_event(self, event):
264207def test_trace_propagation_meta_head_sdk (sentry_init ):
265208 sentry_init (traces_sample_rate = 1.0 , release = "foo" )
266209
267- transaction = Transaction .continue_from_headers ({}, name = "Head SDK tx" )
268210 meta = None
269211 span = None
270212
271- with start_transaction (transaction ):
272- with start_span (op = "foo" , name = "foodesc" ) as current_span :
273- span = current_span
274- meta = sentry_sdk .get_current_scope ().trace_propagation_meta ()
213+ with continue_trace ({}):
214+ with start_span (name = "Head SDK tx" ) as root_span :
215+ with start_span (op = "foo" , name = "foodesc" ) as current_span :
216+ span = current_span
217+ meta = sentry_sdk .get_current_scope ().trace_propagation_meta ()
275218
276219 ind = meta .find (">" ) + 1
277220 sentry_trace , baggage = meta [:ind ], meta [ind :]
@@ -282,4 +225,4 @@ def test_trace_propagation_meta_head_sdk(sentry_init):
282225
283226 assert 'meta name="baggage"' in baggage
284227 baggage_content = re .findall ('content="([^"]*)"' , baggage )[0 ]
285- assert baggage_content == transaction .get_baggage ().serialize ()
228+ assert baggage_content == root_span .get_baggage ().serialize ()
0 commit comments