Skip to content

Commit b9624a1

Browse files
committed
Added test for breadcrumb behavior
1 parent 0526d15 commit b9624a1

File tree

4 files changed

+150
-6
lines changed

4 files changed

+150
-6
lines changed

sentry_sdk/integrations/asyncpg.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ async def _inner(*args: Any, **kwargs: Any) -> T:
181181

182182
with capture_internal_exceptions():
183183
sentry_sdk.add_breadcrumb(
184-
message="connect", category="query", data=span._data
184+
message="connect",
185+
category="query",
186+
data=span._data,
185187
)
186188
res = await f(*args, **kwargs)
187189

sentry_sdk/integrations/clickhouse_driver.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ def _inner_end(*args: P.args, **kwargs: P.kwargs) -> T:
119119

120120
with capture_internal_exceptions():
121121
span.scope.add_breadcrumb(
122-
message=span._data.pop("query"), category="query", data=span._data
122+
message=span._data.pop("query"),
123+
category="query",
124+
data=span._data,
123125
)
124126

125127
span.finish()

sentry_sdk/tracing_utils.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,20 @@ def record_sql_queries(
156156

157157
def maybe_create_breadcrumbs_from_span(scope, span):
158158
# type: (sentry_sdk.Scope, sentry_sdk.tracing.Span) -> None
159-
160159
if span.op == OP.DB_REDIS:
161160
scope.add_breadcrumb(
162-
message=span.description, type="redis", category="redis", data=span._tags
161+
message=span.description,
162+
type="redis",
163+
category="redis",
164+
data=span._tags,
163165
)
164166
elif span.op == OP.HTTP_CLIENT:
165-
scope.add_breadcrumb(type="http", category="httplib", data=span._data)
166-
elif span.op == "subprocess":
167+
scope.add_breadcrumb(
168+
type="http",
169+
category="httplib",
170+
data=span._data,
171+
)
172+
elif span.op == OP.SUBPROCESS:
167173
scope.add_breadcrumb(
168174
type="subprocess",
169175
category="subprocess",

tests/test_breadcrumbs.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
from unittest import mock
2+
3+
import sentry_sdk
4+
from sentry_sdk.consts import OP
5+
6+
7+
def test_breadcrumbs(sentry_init, capture_envelopes):
8+
"""
9+
This test illustrates how breadcrumbs are added to the error event when an error occurs
10+
"""
11+
sentry_init(
12+
traces_sample_rate=1.0,
13+
)
14+
envelopes = capture_envelopes()
15+
16+
add_breadcrumbs_kwargs = {
17+
"type": "navigation",
18+
"category": "unit_tests.breadcrumbs",
19+
"level": "fatal",
20+
"origin": "unit-tests",
21+
"data": {
22+
"string": "foobar",
23+
"number": 4.2,
24+
"array": [1, 2, 3],
25+
"dict": {"foo": "bar"},
26+
},
27+
}
28+
29+
with sentry_sdk.start_transaction(name="trx-breadcrumbs"):
30+
sentry_sdk.add_breadcrumb(message="breadcrumb0", **add_breadcrumbs_kwargs)
31+
32+
with sentry_sdk.start_span(name="span1", op="function"):
33+
sentry_sdk.add_breadcrumb(message="breadcrumb1", **add_breadcrumbs_kwargs)
34+
35+
with sentry_sdk.start_span(name="span2", op="function"):
36+
sentry_sdk.add_breadcrumb(message="breadcrumb2", **add_breadcrumbs_kwargs)
37+
38+
# Spans that create breadcrumbs automatically
39+
with sentry_sdk.start_span(name="span3", op=OP.DB_REDIS) as span3:
40+
span3.set_data("span3_data", "data on the redis span")
41+
span3.set_tag("span3_tag", "tag on the redis span")
42+
43+
with sentry_sdk.start_span(name="span4", op=OP.HTTP_CLIENT) as span4:
44+
span4.set_data("span4_data", "data on the http.client span")
45+
span4.set_tag("span4_tag", "tag on the http.client span")
46+
47+
with sentry_sdk.start_span(name="span5", op=OP.SUBPROCESS) as span5:
48+
span5.set_data("span5_data", "data on the subprocess span")
49+
span5.set_tag("span5_tag", "tag on the subprocess span")
50+
51+
with sentry_sdk.start_span(name="span6", op="function") as span6:
52+
# This data on the span is not added to custom breadcrumbs.
53+
# Data from the span is only added to automatic breadcrumbs shown above
54+
span6.set_data("span6_data", "data on span6")
55+
span6.set_tag("span6_tag", "tag on the span6")
56+
sentry_sdk.add_breadcrumb(message="breadcrumb6", **add_breadcrumbs_kwargs)
57+
58+
try:
59+
1/0
60+
except ZeroDivisionError as ex:
61+
sentry_sdk.capture_exception(ex)
62+
63+
(error_envelope, transaction_envelope) = envelopes
64+
error = error_envelope.get_event()
65+
transaction = transaction_envelope.get_transaction_event()
66+
67+
breadcrumbs = error["breadcrumbs"]["values"]
68+
assert len(breadcrumbs) == 7
69+
70+
# Check for my custom breadcrumbs
71+
for i in range(0, 3):
72+
assert breadcrumbs[i]["message"] == f"breadcrumb{i}"
73+
assert breadcrumbs[i]["type"] == "navigation"
74+
assert breadcrumbs[i]["category"] == "unit_tests.breadcrumbs"
75+
assert breadcrumbs[i]["level"] == "fatal"
76+
assert breadcrumbs[i]["origin"] == "unit-tests"
77+
assert breadcrumbs[i]["data"] == {
78+
"string": "foobar",
79+
"number": 4.2,
80+
"array": [1, 2, 3],
81+
"dict": {"foo": "bar"},
82+
}
83+
assert breadcrumbs[i]["timestamp"] == mock.ANY
84+
85+
# Check automatic redis breadcrumbs
86+
assert breadcrumbs[3]["message"] == f"span3"
87+
assert breadcrumbs[3]["type"] == "redis"
88+
assert breadcrumbs[3]["category"] == "redis"
89+
assert "level" not in breadcrumbs[3]
90+
assert "origin" not in breadcrumbs[3]
91+
assert breadcrumbs[3]["data"] == {
92+
"span3_tag": "tag on the redis span",
93+
}
94+
assert breadcrumbs[3]["timestamp"] == mock.ANY
95+
96+
# Check automatic http.client breadcrumbs
97+
assert "message" not in breadcrumbs[4]
98+
assert breadcrumbs[4]["type"] == "http"
99+
assert breadcrumbs[4]["category"] == "httplib"
100+
assert "level" not in breadcrumbs[4]
101+
assert "origin" not in breadcrumbs[4]
102+
assert breadcrumbs[4]["data"] == {
103+
"thread.id": mock.ANY,
104+
"thread.name": mock.ANY,
105+
"span4_data": "data on the http.client span",
106+
}
107+
assert breadcrumbs[4]["timestamp"] == mock.ANY
108+
109+
# Check automatic subprocess breadcrumbs
110+
assert breadcrumbs[5]["message"] == f"span5"
111+
assert breadcrumbs[5]["type"] == "subprocess"
112+
assert breadcrumbs[5]["category"] == "subprocess"
113+
assert "level" not in breadcrumbs[5]
114+
assert "origin" not in breadcrumbs[5]
115+
assert breadcrumbs[5]["data"] == {
116+
"thread.id": mock.ANY,
117+
"thread.name": mock.ANY,
118+
"span5_data": "data on the subprocess span",
119+
}
120+
assert breadcrumbs[5]["timestamp"] == mock.ANY
121+
122+
# Check for custom breadcrumbs on span6
123+
assert breadcrumbs[6]["message"] == f"breadcrumb6"
124+
assert breadcrumbs[6]["type"] == "navigation"
125+
assert breadcrumbs[6]["category"] == "unit_tests.breadcrumbs"
126+
assert breadcrumbs[6]["level"] == "fatal"
127+
assert breadcrumbs[6]["origin"] == "unit-tests"
128+
assert breadcrumbs[6]["data"] == {
129+
"string": "foobar",
130+
"number": 4.2,
131+
"array": [1, 2, 3],
132+
"dict": {"foo": "bar"},
133+
}
134+
assert breadcrumbs[6]["timestamp"] == mock.ANY

0 commit comments

Comments
 (0)