8000 fix event recursion (#210) · etherscan-io/sentry-python@5271685 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5271685

Browse files
mmerickeluntitaker
authored andcommitted
fix event recursion (getsentry#210)
* reproduce infinite recursion between integrations * avoid creating new events while processing one * fix a bug in older pyramid versions getting authenticated_userid * blackify * add comment * use a decorator to pull out logic * fix: Formatting
1 parent 7b01082 commit 5271685

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

sentry_sdk/client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ def _is_ignored_error(self, event, hint=None):
156156
return False
157157

158158
def _should_capture(self, event, hint, scope=None):
159+
if scope is not None and not scope._should_capture:
160+
return False
161+
159162
if (
160163
self.options["sample_rate"] < 1.0
161164
and random.random() >= self.options["sample_rate"]

sentry_sdk/integrations/pyramid.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import weakref
66

77
from pyramid.httpexceptions import HTTPException
8+
from pyramid.request import Request
89

910
from sentry_sdk.hub import Hub, _should_send_default_pii
1011
from sentry_sdk.utils import capture_internal_exceptions, event_from_exception
@@ -15,6 +16,17 @@
1516
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
1617

1718

19+
if getattr(Request, "authenticated_userid", None):
20+
21+
def authenticated_userid(request):
22+
return request.authenticated_userid
23+
24+
25+
else:
26+
# bw-compat for pyramid < 1.5
27+
from pyramid.security import authenticated_userid
28+
29+
1830
class PyramidIntegration(Integration):
1931
identifier = "pyramid"
2032

@@ -142,7 +154,7 @@ def event_processor(event, hint):
142154
with capture_internal_exceptions():
143155
user_info = event.setdefault("user", {})
144156
if "id" not in user_info:
145-
user_info["id"] = request.authenticated_userid
157+
user_info["id"] = authenticated_userid(request)
146158

147159
return event
148160

sentry_sdk/scope.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from copy import copy
22
from collections import deque
3+
from functools import wraps
34
from itertools import chain
45

56
from sentry_sdk.utils import logger, capture_internal_exceptions
@@ -16,6 +17,20 @@ def _attr_setter(fn):
1617
return property(fset=fn, doc=fn.__doc__)
1718

1819

20+
def _disable_capture(fn):
21+
@wraps(fn)
22+
def wrapper(self, *args, **kwargs):
23+
if not self._should_capture:
24+
return
25+
try:
26+
self._should_capture = False
27+
return fn(self, *args, **kwargs)
28+
finally:
29+
self._should_capture = True
30+
31+
return wrapper
32+
33+
1934
class Scope(object):
2035
"""The scope holds extra information that should be sent with all
2136
events that belong to it.
@@ -33,6 +48,7 @@ class Scope(object):
3348
"_breadcrumbs",
3449
"_event_processors",
3550
"_error_processors",
51+
"_should_capture",
3652
)
3753

3854
def __init__(self):
@@ -99,6 +115,8 @@ def clear(self):
99115

100116
self._breadcrumbs = deque()
101117

118+
self._should_capture = True
119+
102120
def add_event_processor(self, func):
103121
""""Register a scope local event processor on the scope.
104122
@@ -126,6 +144,7 @@ def func(event, exc_info):
126144

127145
self._error_processors.append(func)
128146

147+
@_disable_capture
129148
def apply_to_event(self, event, hint=None):
130149
"""Applies the information contained on the scope to the given event."""
131150

@@ -189,6 +208,8 @@ def __copy__(self):
189208
rv._event_processors = list(self._event_processors)
190209
rv._error_processors = list(self._error_processors)
191210

211+
rv._should_capture = self._should_capture
212+
192213
return rv
193214

194215
def __repr__(self):

tests/integrations/pyramid/test_pyramid.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
from io import BytesIO
44

5+
import logging
6+
57
import pytest
68

9+
from pyramid.authorization import ACLAuthorizationPolicy
710
import pyramid.testing
811

912
from pyramid.response import Response
@@ -239,3 +242,32 @@ def error_handler(err, request):
239242

240243
exception, = event2["exception"]["values"]
241244
assert exception["type"] == "ZeroDivisionError"
245+
246+
247+
def test_error_in_authenticated_userid(
248+
sentry_init, pyramid_config, capture_events, route, get_client
249+
):
250+
from sentry_sdk.integrations.logging import LoggingIntegration
251+
252+
sentry_init(
253+
send_default_pii=True,
254+
integrations=[
255+
PyramidIntegration(),
256+
LoggingIntegration(event_level=logging.ERROR),
257+
],
258+
)
259+
logger = logging.getLogger("test_pyramid")
260+
261+
class AuthenticationPolicy(object):
262+
def authenticated_userid(self, request):
263+
logger.error("failed to identify user")
264+
265+
pyramid_config.set_authorization_policy(ACLAuthorizationPolicy())
266+
pyramid_config.set_authentication_policy(AuthenticationPolicy())
267+
268+
events = capture_events()
269+
270+
client = get_client()
271+
client.get("/message")
272+
273+
assert len(events) == 1

0 commit comments

Comments
 (0)
0