1
- import weakref
2
- import gc
3
1
import re
4
2
import pytest
5
3
import random
6
4
7
5
import sentry_sdk
8
6
from sentry_sdk import (
9
7
capture_message ,
8
+ continue_trace ,
10
9
start_span ,
11
- start_transaction ,
12
10
)
13
11
from sentry_sdk .consts import SPANSTATUS
14
12
from sentry_sdk .transport import Transport
15
- from sentry_sdk .tracing import Transaction
16
13
17
14
18
15
@pytest .mark .parametrize ("sample_rate" , [0.0 , 1.0 ])
19
16
def test_basic (sentry_init , capture_events , sample_rate ):
20
17
sentry_init (traces_sample_rate = sample_rate )
21
18
events = capture_events ()
22
19
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 )
25
22
with pytest .raises (ZeroDivisionError ):
26
23
with start_span (op = "foo" , name = "foodesc" ):
27
24
1 / 0
@@ -39,21 +36,23 @@ def test_basic(sentry_init, capture_events, sample_rate):
39
36
span1 , span2 = event ["spans" ]
40
37
parent_span = event
41
38
assert span1 ["tags" ]["status" ] == "internal_error"
39
+ assert span1 ["status" ] == "internal_error"
42
40
assert span1 ["op" ] == "foo"
43
41
assert span1 ["description" ] == "foodesc"
44
42
assert "status" not in span2 .get ("tags" , {})
45
43
assert span2 ["op" ] == "bar"
46
44
assert span2 ["description" ] == "bardesc"
47
45
assert parent_span ["transaction" ] == "hi"
48
- assert "status" not in event [ "tags" ]
46
+ assert "status" not in event . get ( "tags" , {})
49
47
assert event ["contexts" ]["trace" ]["status" ] == "ok"
50
48
else :
51
49
assert not events
52
50
53
51
54
- @pytest .mark .parametrize ("sampled" , [True , False , None ])
55
52
@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
57
56
"""
58
57
Ensure data is actually passed along via headers, and that they are read
59
58
correctly.
@@ -62,55 +61,41 @@ def test_continue_from_headers(sentry_init, capture_envelopes, sampled, sample_r
62
61
envelopes = capture_envelopes ()
63
62
64
63
# 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" ]
78
69
79
70
# 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" )
106
89
107
90
# 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
110
94
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
+ )
114
99
else :
115
100
trace1 , message , trace2 = envelopes
116
101
trace1_payload = trace1 .get_transaction_event ()
@@ -123,56 +108,43 @@ def test_continue_from_headers(sentry_init, capture_envelopes, sampled, sample_r
123
108
assert (
124
109
trace1_payload ["contexts" ]["trace" ]["trace_id" ]
125
110
== trace2_payload ["contexts" ]["trace" ]["trace_id" ]
126
- == child_transaction .trace_id
111
+ == child_root_span .trace_id
127
112
== message_payload ["contexts" ]["trace" ]["trace_id" ]
128
113
)
129
114
130
115
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
- }
137
116
138
117
assert message_payload ["message" ] == "hello"
139
118
140
119
141
120
@pytest .mark .parametrize ("sample_rate" , [0.5 , 1.0 ])
142
121
def 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
144
127
):
145
128
sentry_init (traces_sample_rate = sample_rate , release = "foo" )
146
129
envelopes = capture_envelopes ()
147
130
148
131
# make sure transaction is sampled for both cases
149
132
monkeypatch .setattr (random , "random" , lambda : 0.1 )
150
133
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 ()
163
138
164
- # finish will create a new baggage entry
165
- baggage = transaction ._baggage
166
- trace_id = transaction .trace_id
139
+ trace_id = span .trace_id
167
140
168
141
assert baggage
169
- assert not baggage .mutable
170
142
assert baggage .third_party_items == ""
171
143
assert baggage .sentry_items == {
172
144
"environment" : "production" ,
173
145
"release" : "foo" ,
174
146
"sample_rate" : str (sample_rate ),
175
- "sampled" : "true" if transaction .sampled else "false" ,
147
+ "sampled" : "true" if span .sampled else "false" ,
176
148
"transaction" : "Head SDK tx" ,
177
149
"trace_id" : trace_id ,
178
150
}
@@ -184,59 +156,30 @@ def test_dynamic_sampling_head_sdk_creates_dsc(
184
156
"sentry-transaction=Head%%20SDK%%20tx,"
185
157
"sentry-sample_rate=%s,"
186
158
"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" )
188
160
)
189
- assert baggage .serialize () == expected_baggage
161
+ assert baggage .serialize () == SortedBaggage ( expected_baggage )
190
162
191
163
(envelope ,) = envelopes
192
164
assert envelope .headers ["trace" ] == baggage .dynamic_sampling_context ()
193
165
assert envelope .headers ["trace" ] == {
194
166
"environment" : "production" ,
195
167
"release" : "foo" ,
196
168
"sample_rate" : str (sample_rate ),
197
- "sampled" : "true" if transaction .sampled else "false" ,
169
+ "sampled" : "true" if span .sampled else "false" ,
198
170
"transaction" : "Head SDK tx" ,
199
171
"trace_id" : trace_id ,
200
172
}
201
173
202
174
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
-
232
175
def test_transactions_do_not_go_through_before_send (sentry_init , capture_events ):
233
176
def before_send (event , hint ):
234
177
raise RuntimeError ("should not be called" )
235
178
236
179
sentry_init (traces_sample_rate = 1.0 , before_send = before_send )
237
180
events = capture_events ()
238
181
239
- with start_transaction (name = "/" ):
182
+ with start_span (name = "/" ):
240
183
pass
241
184
242
185
assert len (events ) == 1
@@ -254,7 +197,7 @@ def capture_event(self, event):
254
197
sentry_init (traces_sample_rate = 1 , transport = CustomTransport ())
255
198
events = capture_events ()
256
199
257
- with start_transaction (name = "hi" ):
200
+ with start_span (name = "hi" ):
258
201
with start_span (op = "bar" , name = "bardesc" ):
259
202
pass
260
203
@@ -264,14 +207,14 @@ def capture_event(self, event):
264
207
def test_trace_propagation_meta_head_sdk (sentry_init ):
265
208
sentry_init (traces_sample_rate = 1.0 , release = "foo" )
266
209
267
- transaction = Transaction .continue_from_headers ({}, name = "Head SDK tx" )
268
210
meta = None
269
211
span = None
270
212
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 ()
275
218
276
219
ind = meta .find (">" ) + 1
277
220
sentry_trace , baggage = meta [:ind ], meta [ind :]
@@ -282,4 +225,4 @@ def test_trace_propagation_meta_head_sdk(sentry_init):
282
225
283
226
assert 'meta name="baggage"' in baggage
284
227
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