Skip to content

Commit 26601cc

Browse files
alexon1234devin-ai-integration[bot]
authored andcommitted
perf(modules): Don't re-serialize the installed modules on every event
Fixes #8090 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent 641517a commit 26601cc

2 files changed

Lines changed: 59 additions & 5 deletions

File tree

‎sentry_sdk/integrations/modules.py‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,28 @@
66
from sentry_sdk.utils import _get_installed_modules
77

88
if TYPE_CHECKING:
9-
from typing import Any
9+
from typing import Any, Dict, Optional
1010

1111
from sentry_sdk._types import Event
1212

1313

14+
class _InstalledModules(dict): # type: ignore[type-arg]
15+
def __sentry_repr__(self) -> "Dict[str, str]":
16+
return dict(self)
17+
18+
19+
_installed_modules: "Optional[_InstalledModules]" = None
20+
21+
22+
def _get_installed_modules_for_event() -> _InstalledModules:
23+
global _installed_modules
24+
25+
if _installed_modules is None:
26+
_installed_modules = _InstalledModules(_get_installed_modules())
27+
28+
return _installed_modules
29+
30+
1431
class ModulesIntegration(Integration):
1532
identifier = "modules"
1633

@@ -24,5 +41,5 @@ def processor(event: "Event", hint: "Any") -> "Event":
2441
if sentry_sdk.get_client().get_integration(ModulesIntegration) is None:
2542
return event
2643

27-
event["modules"] = _get_installed_modules()
44+
event["modules"] = _get_installed_modules_for_event()
2845
return event
Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import sentry_sdk
2-
from sentry_sdk.integrations.modules import ModulesIntegration
2+
from sentry_sdk.integrations.modules import ModulesIntegration, _InstalledModules
3+
from sentry_sdk.serializer import _Serializer, serialize
4+
from sentry_sdk.utils import _get_installed_modules
35

46

57
def test_basic(sentry_init, capture_events):
@@ -9,5 +11,40 @@ def test_basic(sentry_init, capture_events):
911
sentry_sdk.capture_exception(ValueError())
1012

1113
(event,) = events
12-
assert "sentry-sdk" in event["modules"]
13-
assert "pytest" in event["modules"]
14+
assert event["modules"] == _get_installed_modules()
15+
16+
17+
def test_before_send_modules_mutations_do_not_leak(sentry_init, capture_events):
18+
modules_seen = []
19+
20+
def before_send(event, hint):
21+
assert type(event["modules"]) is dict
22+
modules_seen.append(event["modules"].copy())
23+
event["modules"]["sentry-sdk"] = "mutated"
24+
return event
25+
26+
sentry_init(integrations=[ModulesIntegration()], before_send=before_send)
27+
events = capture_events()
28+
29+
sentry_sdk.capture_exception(ValueError())
30+
sentry_sdk.capture_exception(ValueError())
31+
32+
assert len(events) == 2
33+
assert modules_seen == [_get_installed_modules(), _get_installed_modules()]
34+
35+
36+
def test_installed_modules_are_not_recursively_serialized(monkeypatch):
37+
original_serialize_node = _Serializer._serialize_node
38+
segments = []
39+
40+
def counting_serialize_node(self, obj, *args, **kwargs):
41+
segments.append(kwargs.get("segment"))
42+
return original_serialize_node(self, obj, *args, **kwargs)
43+
44+
monkeypatch.setattr(_Serializer, "_serialize_node", counting_serialize_node)
45+
46+
event = serialize({"modules": _InstalledModules({"package": "1.0"})})
47+
48+
assert event["modules"] == {"package": "1.0"}
49+
assert segments.count("modules") == 1
50+
assert "package" not in segments

0 commit comments

Comments
 (0)