Skip to content

Commit 06216d8

Browse files
committed
handle scope merging for breadcrumb annotations
1 parent bd8e3fa commit 06216d8

6 files changed

Lines changed: 60 additions & 13 deletions

File tree

sentry_sdk/_types.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ def __eq__(self, other):
3030

3131
return self.value == other.value and self.metadata == other.metadata
3232

33+
def __str__(self):
34+
return str({"value": str(self.value), "metadata": str(self.metadata)})
35+
36+
def __repr__(self):
37+
return str(self)
38+
39+
def __len__(self):
40+
return len(self.value)
41+
3342
@classmethod
3443
def removed_because_raw_data(cls):
3544
# type: () -> AnnotatedValue
@@ -81,8 +90,11 @@ def substituted_because_contains_sensitive_data(cls):
8190
},
8291
)
8392

93+
8494
T = TypeVar("T")
8595
Annotated = Union[AnnotatedValue, T]
96+
97+
8698
class AnnotatedDeque(AnnotatedValue):
8799
"""
88100
Meta information for a data field in the event payload.
@@ -128,6 +140,7 @@ def truncated(cls, value, n_truncated):
128140
metadata={"len": [n_truncated]}, # Remark
129141
)
130142

143+
131144
if TYPE_CHECKING:
132145
from collections.abc import Container, MutableMapping, Sequence
133146

sentry_sdk/client.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ def _prepare_event(
491491
# type: (...) -> Optional[Event]
492492

493493
previous_total_spans = None # type: Optional[int]
494+
previous_total_breadcrumbs = None # type: Optional[int]
494495

495496
if event.get("timestamp") is None:
496497
event["timestamp"] = datetime.now(timezone.utc)
@@ -527,6 +528,10 @@ def _prepare_event(
527528
dropped_spans = event.pop("_dropped_spans", 0) + spans_delta # type: int
528529
if dropped_spans > 0:
529530
previous_total_spans = spans_before + dropped_spans
531+
if scope._n_breadcrumbs_truncated > 0:
532+
previous_total_breadcrumbs = (
533+
len(event["breadcrumbs"]) + scope._n_breadcrumbs_truncated
534+
)
530535

531536
if (
532537
self.options["attach_stacktrace"]
@@ -579,7 +584,10 @@ def _prepare_event(
579584
event["spans"] = AnnotatedValue(
580585
event.get("spans", []), {"len": previous_total_spans}
581586
)
582-
587+
if previous_total_breadcrumbs is not None:
588+
event["breadcrumbs"] = AnnotatedValue(
589+
event.get("breadcrumbs", []), {"len": previous_total_breadcrumbs}
590+
)
583591
# Postprocess the event here so that annotated types do
584592
# generally not surface in before_send
585593
if event is not None:

sentry_sdk/scope.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import os
23
import sys
34
import warnings
@@ -9,6 +10,7 @@
910
from functools import wraps
1011
from itertools import chain
1112

13+
from sentry_sdk._types import AnnotatedValue
1214
from sentry_sdk.attachments import Attachment
1315
from sentry_sdk.consts import DEFAULT_MAX_BREADCRUMBS, FALSE_VALUES, INSTRUMENTER
1416
from sentry_sdk.feature_flags import FlagBuffer, DEFAULT_FLAG_CAPACITY
@@ -33,7 +35,6 @@
3335
Transaction,
3436
)
3537
from sentry_sdk.utils import (
36-
AnnotatedDeque,
3738
capture_internal_exception,
3839
capture_internal_exceptions,
3940
ContextVar,
@@ -987,8 +988,14 @@ def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
987988
logger.info("before breadcrumb dropped breadcrumb (%s)", crumb)
988989

989990
while len(self._breadcrumbs) > max_breadcrumbs:
991+
logging.debug(
992+
f"i am here in the truncation logic before, {self._n_breadcrumbs_truncated}"
993+
)
990994
self._breadcrumbs.popleft()
991995
self._n_breadcrumbs_truncated += 1
996+
logging.debug(
997+
f"i am here in the truncation logic after, {self._n_breadcrumbs_truncated}"
998+
)
992999

9931000
def start_transaction(
9941001
self,
@@ -1388,12 +1395,19 @@ def _apply_breadcrumbs_to_event(self, event, hint, options):
13881395
pass
13891396

13901397
# Add annotation that breadcrumbs were truncated
1398+
logging.debug(
1399+
f"i am here outside of the truncated thing, {self._n_breadcrumbs_truncated} and {len(self._breadcrumbs)}"
1400+
)
13911401
if self._n_breadcrumbs_truncated:
1402+
logging.debug("i am here in the truncated thing")
13921403
original_length = (
13931404
len(event["breadcrumbs"]["values"]) + self._n_breadcrumbs_truncated
13941405
)
1395-
event["breadcrumbs"]["values"] = AnnotatedDeque.truncated_breadcrumbs(
1396-
event["breadcrumbs"]["values"], original_length
1406+
logging.debug(
1407+
f"in the truncated thing, the original_lenght is {original_length}"
1408+
)
1409+
event["breadcrumbs"] = AnnotatedValue(
1410+
event.get("breadcrumbs", []), {"len": original_length}
13971411
)
13981412

13991413
def _apply_user_to_event(self, event, hint, options):
@@ -1546,6 +1560,9 @@ def apply_to_event(
15461560

15471561
if not is_transaction and not is_check_in:
15481562
self._apply_breadcrumbs_to_event(event, hint, options)
1563+
# logging.debug(event)
1564+
logging.debug(event["breadcrumbs"])
1565+
logging.debug(type(event["breadcrumbs"]))
15491566
self._apply_flags_to_event(event, hint, options)
15501567

15511568
event = self.run_error_processors(event, hint)
@@ -1579,6 +1596,10 @@ def update_from_scope(self, scope):
15791596
self._extras.update(scope._extras)
15801597
if scope._breadcrumbs:
15811598
self._breadcrumbs.extend(scope._breadcrumbs)
1599+
if scope._n_breadcrumbs_truncated:
1600+
self._n_breadcrumbs_truncated = (
1601+
self._n_breadcrumbs_truncated + scope._n_breadcrumbs_truncated
1602+
)
15821603
if scope._span:
15831604
self._span = scope._span
15841605
if scope._attachments:

sentry_sdk/serializer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import sys
23
import math
34
from collections.abc import Mapping, Sequence, Set
@@ -230,6 +231,7 @@ def _serialize_node(
230231
def _flatten_annotated(obj):
231232
# type: (Any) -> Any
232233
if isinstance(obj, AnnotatedValue):
234+
logging.debug(obj)
233235
_annotate(**obj.metadata)
234236
obj = obj.value
235237
return obj

tests/test_scrubber.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,27 +119,30 @@ def test_stack_var_scrubbing(sentry_init, capture_events):
119119

120120

121121
def test_breadcrumb_extra_scrubbing(sentry_init, capture_events):
122-
sentry_init()
122+
sentry_init(max_breadcrumbs=2)
123+
breakpoint()
123124
events = capture_events()
124-
125-
logger.info("bread", extra=dict(foo=42, password="secret"))
125+
logger.info("breadcrumb 1", extra=dict(foo=1, password="secret"))
126+
logger.info("breadcrumb 2", extra=dict(bar=2, auth="secret"))
127+
logger.info("breadcrumb 3", extra=dict(foobar=3, password="secret"))
126128
logger.critical("whoops", extra=dict(bar=69, auth="secret"))
127129

130+
print(events)
128131
(event,) = events
129132

130133
assert event["extra"]["bar"] == 69
131134
assert event["extra"]["auth"] == "[Filtered]"
132-
133135
assert event["breadcrumbs"]["values"][0]["data"] == {
134-
"foo": 42,
135-
"password": "[Filtered]",
136+
"bar": 2,
137+
"auth": "[Filtered]",
136138
}
137139

138140
assert event["_meta"]["extra"]["auth"] == {"": {"rem": [["!config", "s"]]}}
139141
assert event["_meta"]["breadcrumbs"] == {
140142
"values": {
141-
"": {"len": [1]},
142-
"0": {"data": {"password": {"": {"rem": [["!config", "s"]]}}}},
143+
"": {"len": [4]},
144+
"0": {"data": {"auth": {"": {"rem": [["!config", "s"]]}}}},
145+
"1": {"data": {"password": {"": {"rem": [["!config", "s"]]}}}},
143146
}
144147
}
145148

tests/tracing/test_misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_span_trimming(sentry_init, capture_events):
4040
def test_span_data_scrubbing_and_trimming(sentry_init, capture_events):
4141
sentry_init(traces_sample_rate=1.0, _experiments={"max_spans": 3})
4242
events = capture_events()
43-
43+
breakpoint()
4444
with start_transaction(name="hi"):
4545
with start_span(op="foo", name="bar") as span:
4646
span.set_data("password", "secret")

0 commit comments

Comments
 (0)