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
17 changes: 8 additions & 9 deletions sentry_sdk/hub.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import sys
import copy
import linecache
from threading import local
from contextlib import contextmanager

from ._compat import with_metaclass
from .scope import Scope
from .utils import exceptions_from_error_tuple, create_event, \
skip_internal_frames
skip_internal_frames, ContextVar


_local = local()
_local = ContextVar('sentry_current_hub')


class HubMeta(type):

@property
def current(self):
try:
rv = _local.hub
except AttributeError:
_local.hub = rv = Hub(GLOBAL_HUB)
rv = _local.get(None)
if rv is None:
rv = Hub(GLOBAL_HUB)
_local.set(rv)
return rv

@property
Expand All @@ -32,10 +31,10 @@ class _HubManager(object):

def __init__(self, hub):
self._old = Hub.current
_local.hub = hub
_local.set(hub)

def __exit__(self, exc_type, exc_value, tb):
_local.hub = self._old
_local.set(self._old)


class _ScopeManager(object):
Expand Down
16 changes: 9 additions & 7 deletions sentry_sdk/integrations/django/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import absolute_import

from threading import Lock, local
from threading import Lock

from django.conf import settings
from django.core import signals
Expand All @@ -10,6 +10,7 @@
from django.core.urlresolvers import resolve

from sentry_sdk import get_current_hub, configure_scope, capture_exception
from sentry_sdk.utils import ContextVar


try:
Expand All @@ -23,15 +24,15 @@
def _get_transaction_from_request(request):
return resolve(request.path).func

_request_scope = local()
_request_scope = ContextVar('sentry_django_request_scope')


# request_started (or any other signal) cannot be used because the request is
# not yet available
class SentryMiddleware(MiddlewareMixin):
def process_request(self, request):
assert getattr(_request_scope, 'manager', None) is None, 'race condition'
_request_scope.manager = get_current_hub().push_scope().__enter__()
assert _request_scope.get(None) is None, 'race condition'
_request_scope.set(get_current_hub().push_scope().__enter__())

try:
with configure_scope() as scope:
Expand All @@ -41,9 +42,10 @@ def process_request(self, request):


def _request_finished(*args, **kwargs):
assert getattr(_request_scope, 'manager', None) is not None, 'race condition'
_request_scope.manager.__exit__(None, None, None)
_request_scope.manager = None
val = _request_scope.get(None)
assert val is not None, 'race condition'
val.__exit__(None, None, None)
_request_scope.set(None)


def _got_request_exception(request=None, **kwargs):
Expand Down
20 changes: 20 additions & 0 deletions sentry_sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,23 @@ def to_string(value):
return text_type(value)
except UnicodeDecodeError:
return repr(value)[1:-1]


try:
from contextvars import ContextVar
except ImportError:
from threading import local
_nothing = object()

class ContextVar(object):
# Super-limited impl of ContextVar

def __init__(self, name):
self._name = name
self._local = local()

def get(self, default):
return getattr(self._local, 'value', default)

def set(self, value):
setattr(self._local, 'value', value)