Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sentry_sdk/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def push_scope(self):
def pop_scope_unsafe(self):
"""Pops a scope layer from the stack. Try to use the context manager
`push_scope()` instead."""
self._pending_processors = []
self._stack.pop()

@contextmanager
Expand Down
7 changes: 5 additions & 2 deletions sentry_sdk/integrations/_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ class RequestExtractor(object):
def __init__(self, request):
self.request = request

def extract_into_scope(self, scope):
def extract_into_event(self, event):
if "request" in event:
return

# if the code below fails halfway through we at least have some data
scope.request = request_info = {}
event["request"] = request_info = {}

request_info["url"] = self.url
request_info["query_string"] = self.query_string
Expand Down
22 changes: 15 additions & 7 deletions sentry_sdk/integrations/django/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ def process_request(self, request):
try:
get_current_hub().push_scope()

get_current_hub().add_event_processor(
lambda: self.make_event_processor(request)
)

with configure_scope() as scope:
scope.transaction = _get_transaction_from_request(request)
try:
DjangoRequestExtractor(request).extract_into_scope(scope)
except Exception:
get_current_hub().capture_internal_exception()

# TODO: user info

except Exception:
get_current_hub().capture_internal_exception()

def make_event_processor(self, request):
def processor(event):
try:
DjangoRequestExtractor(request).extract_into_event(event)
except Exception:
get_current_hub().capture_internal_exception()

# TODO: user info

return processor


class DjangoRequestExtractor(RequestExtractor):
@property
Expand Down
61 changes: 33 additions & 28 deletions sentry_sdk/integrations/flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,46 +25,48 @@ def init_app(self, app):
raise RuntimeError("Sentry registration is already registered")
app.extensions[__name__] = True

appcontext_pushed.connect(_push_appctx, sender=app)
app.teardown_appcontext(_pop_appctx)
got_request_exception.connect(_capture_exception, sender=app)
app.before_request(_before_request)
appcontext_pushed.connect(self._push_appctx, sender=app)
app.teardown_appcontext(self._pop_appctx)
got_request_exception.connect(self._capture_exception, sender=app)
app.before_request(self._before_request)

def _push_appctx(self, *args, **kwargs):
get_current_hub().push_scope()
_app_ctx_stack.top._sentry_app_scope_pushed = True

def _push_appctx(*args, **kwargs):
get_current_hub().push_scope()
_app_ctx_stack.top._sentry_app_scope_pushed = True
def _pop_appctx(self, exception):
get_current_hub().pop_scope_unsafe()

def _capture_exception(self, sender, exception, **kwargs):
capture_exception(exception)

def _pop_appctx(exception):
get_current_hub().pop_scope_unsafe()
def _before_request(self, *args, **kwargs):
try:
assert getattr(
_app_ctx_stack.top, "_sentry_app_scope_pushed", None
), "scope push failed"

with configure_scope() as scope:
if request.url_rule:
scope.transaction = request.url_rule.endpoint

def _capture_exception(sender, exception, **kwargs):
capture_exception(exception)


def _before_request(*args, **kwargs):
try:
assert getattr(
_app_ctx_stack.top, "_sentry_app_scope_pushed", None
), "scope push failed"

with configure_scope() as scope:
if request.url_rule:
scope.transaction = request.url_rule.endpoint
get_current_hub().add_event_processor(self.make_event_processor)
except Exception:
get_current_hub().capture_internal_exception()

def make_event_processor(self):
def processor(event):
try:
FlaskRequestExtractor(request).extract_into_scope(scope)
FlaskRequestExtractor(request).extract_into_event(event)
except Exception:
get_current_hub().capture_internal_exception()

try:
_set_user_info(scope)
_set_user_info(event)
except Exception:
get_current_hub().capture_internal_exception()
except Exception:
get_current_hub().capture_internal_exception()

return processor


class FlaskRequestExtractor(RequestExtractor):
Expand Down Expand Up @@ -96,7 +98,10 @@ def size_of_file(self, file):
return file.content_length


def _set_user_info(scope):
def _set_user_info(event):
if "user" in event:
return

try:
ip_address = request.access_route[0]
except IndexError:
Expand All @@ -114,4 +119,4 @@ def _set_user_info(scope):
# - no user is logged in
pass

scope.user = user_info
event["user"] = user_info
20 changes: 8 additions & 12 deletions tests/integrations/flask/test_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from flask_login import LoginManager, login_user

from sentry_sdk import configure_scope, capture_message
from sentry_sdk import capture_message
import sentry_sdk.integrations.flask as flask_sentry

sentry = flask_sentry.FlaskSentry()
Expand All @@ -34,20 +34,16 @@ def hi():
return app


def test_has_context(app):
@app.route("/")
def index():
with configure_scope() as scope:
assert scope._data["transaction"] == "index"
assert "data" not in scope._data["request"]
assert scope._data["request"]["url"] == "http://localhost/"

return "ok"

def test_has_context(app, capture_events):
client = app.test_client()
response = client.get("/")
response = client.get("/message")
assert response.status_code == 200

event, = capture_events
assert event["transaction"] == "hi"
assert "data" not in event["request"]
assert event["request"]["url"] == "http://localhost/message"


@pytest.mark.parametrize("debug", (True, False))
@pytest.mark.parametrize("testing", (True, False))
Expand Down
4 changes: 1 addition & 3 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from hypothesis import given, assume, settings
from hypothesis import given, assume
import hypothesis.strategies as st

from sentry_sdk.utils import safe_repr
Expand All @@ -8,15 +8,13 @@


@given(x=any_string)
@settings(max_examples=1000)
def test_safe_repr_never_broken_for_strings(x):
r = safe_repr(x)
assert isinstance(r, text_type)
assert u"broken repr" not in r


@given(x=any_string)
@settings(max_examples=1000)
def test_safe_repr_never_leaves_escapes_in(x):
if isinstance(x, bytes):
assume(b"\\u" not in x and b"\\x" not in x)
Expand Down