Current File : //opt/alt/python37/lib/python3.7/site-packages/raven/contrib/django/models.py |
"""
raven.contrib.django.models
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Acts as an implicit hook for Django installs.
:copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
# flake8: noqa
from __future__ import absolute_import, unicode_literals
import logging
import sys
import warnings
import django
from django.conf import settings
from django.core.signals import got_request_exception, request_started
from threading import Lock
from raven.utils.conf import convert_options
from raven.utils.compat import PY2, binary_type, text_type
from raven.utils.imports import import_string
logger = logging.getLogger('sentry.errors.client')
def get_installed_apps():
"""
Modules in settings.INSTALLED_APPS as a set.
"""
return set(settings.INSTALLED_APPS)
_client = (None, None)
class ProxyClient(object):
"""
A proxy which represents the currently client at all times.
"""
# introspection support:
__members__ = property(lambda x: x.__dir__())
# Need to pretend to be the wrapped class, for the sake of objects that care
# about this (especially in equality tests)
__class__ = property(lambda x: get_client().__class__)
__dict__ = property(lambda o: get_client().__dict__)
__repr__ = lambda x: repr(get_client())
__getattr__ = lambda x, o: getattr(get_client(), o)
__setattr__ = lambda x, o, v: setattr(get_client(), o, v)
__delattr__ = lambda x, o: delattr(get_client(), o)
__lt__ = lambda x, o: get_client() < o
__le__ = lambda x, o: get_client() <= o
__eq__ = lambda x, o: get_client() == o
__ne__ = lambda x, o: get_client() != o
__gt__ = lambda x, o: get_client() > o
__ge__ = lambda x, o: get_client() >= o
if PY2:
__cmp__ = lambda x, o: cmp(get_client(), o) # NOQA
__hash__ = lambda x: hash(get_client())
# attributes are currently not callable
# __call__ = lambda x, *a, **kw: get_client()(*a, **kw)
__nonzero__ = lambda x: bool(get_client())
__len__ = lambda x: len(get_client())
__getitem__ = lambda x, i: get_client()[i]
__iter__ = lambda x: iter(get_client())
__contains__ = lambda x, i: i in get_client()
__getslice__ = lambda x, i, j: get_client()[i:j]
__add__ = lambda x, o: get_client() + o
__sub__ = lambda x, o: get_client() - o
__mul__ = lambda x, o: get_client() * o
__floordiv__ = lambda x, o: get_client() // o
__mod__ = lambda x, o: get_client() % o
__divmod__ = lambda x, o: get_client().__divmod__(o)
__pow__ = lambda x, o: get_client() ** o
__lshift__ = lambda x, o: get_client() << o
__rshift__ = lambda x, o: get_client() >> o
__and__ = lambda x, o: get_client() & o
__xor__ = lambda x, o: get_client() ^ o
__or__ = lambda x, o: get_client() | o
__div__ = lambda x, o: get_client().__div__(o)
__truediv__ = lambda x, o: get_client().__truediv__(o)
__neg__ = lambda x: -(get_client())
__pos__ = lambda x: +(get_client())
__abs__ = lambda x: abs(get_client())
__invert__ = lambda x: ~(get_client())
__complex__ = lambda x: complex(get_client())
__int__ = lambda x: int(get_client())
if PY2:
__long__ = lambda x: long(get_client()) # NOQA
__float__ = lambda x: float(get_client())
__str__ = lambda x: binary_type(get_client())
__unicode__ = lambda x: text_type(get_client())
__oct__ = lambda x: oct(get_client())
__hex__ = lambda x: hex(get_client())
__index__ = lambda x: get_client().__index__()
__coerce__ = lambda x, o: x.__coerce__(x, o)
__enter__ = lambda x: x.__enter__()
__exit__ = lambda x, *a, **kw: x.__exit__(*a, **kw)
client = ProxyClient()
def get_client(client=None, reset=False):
global _client
tmp_client = client is not None
if not tmp_client:
client = getattr(settings, 'SENTRY_CLIENT', 'raven.contrib.django.DjangoClient')
if _client[0] != client or reset:
options = convert_options(
settings,
defaults={
'include_paths': get_installed_apps(),
},
)
try:
Client = import_string(client)
except ImportError:
logger.exception('Failed to import client: %s', client)
if not _client[1]:
# If there is no previous client, set the default one.
client = 'raven.contrib.django.DjangoClient'
_client = (client, get_client(client))
else:
instance = Client(**options)
if not tmp_client:
_client = (client, instance)
return instance
return _client[1]
def sentry_exception_handler(request=None, **kwargs):
try:
client.captureException(exc_info=sys.exc_info(), request=request)
except Exception as exc:
try:
logger.exception('Unable to process log entry: %s' % (exc,))
except Exception as exc:
warnings.warn('Unable to process log entry: %s' % (exc,))
class SentryDjangoHandler(object):
def __init__(self, client=client):
self.client = client
try:
import celery
except ImportError:
self.has_celery = False
else:
self.has_celery = celery.VERSION >= (2, 5)
self.celery_handler = None
def install_celery(self):
from raven.contrib.celery import (
SentryCeleryHandler, register_logger_signal
)
ignore_expected = getattr(settings,
'SENTRY_CELERY_IGNORE_EXPECTED',
False)
self.celery_handler = SentryCeleryHandler(client,
ignore_expected=ignore_expected)\
.install()
# try:
# ga = lambda x, d=None: getattr(settings, 'SENTRY_%s' % x, d)
# options = getattr(settings, 'RAVEN_CONFIG', {})
# loglevel = options.get('celery_loglevel',
# ga('CELERY_LOGLEVEL', logging.ERROR))
# register_logger_signal(client, loglevel=loglevel)
# except Exception:
# logger.exception('Failed to install Celery error handler')
def install(self):
request_started.connect(self.before_request, weak=False)
got_request_exception.connect(self.exception_handler, weak=False)
if self.has_celery:
try:
self.install_celery()
except Exception:
logger.exception('Failed to install Celery error handler')
def uninstall(self):
request_started.disconnect(self.before_request)
got_request_exception.disconnect(self.exception_handler)
if self.celery_handler:
self.celery_handler.uninstall()
def exception_handler(self, request=None, **kwargs):
try:
self.client.captureException(exc_info=sys.exc_info(), request=request)
except Exception as exc:
try:
logger.exception('Unable to process log entry: %s' % (exc,))
except Exception as exc:
warnings.warn('Unable to process log entry: %s' % (exc,))
def before_request(self, *args, **kwargs):
self.client.context.activate()
def register_serializers():
# force import so serializers can call register
import raven.contrib.django.serializers # NOQA
def install_middleware(middleware_name, lookup_names=None):
"""
Install specified middleware
"""
if lookup_names is None:
lookup_names = (middleware_name,)
# default settings.MIDDLEWARE is None
middleware_attr = 'MIDDLEWARE' if getattr(settings,
'MIDDLEWARE',
None) is not None \
else 'MIDDLEWARE_CLASSES'
# make sure to get an empty tuple when attr is None
middleware = getattr(settings, middleware_attr, ()) or ()
if set(lookup_names).isdisjoint(set(middleware)):
setattr(settings,
middleware_attr,
type(middleware)((middleware_name,)) + middleware)
_setup_lock = Lock()
_initialized = False
def initialize():
global _initialized
with _setup_lock:
if _initialized:
return
# mark this as initialized immediatley to avoid recursive import issues
_initialized = True
try:
register_serializers()
install_middleware(
'raven.contrib.django.middleware.SentryMiddleware',
(
'raven.contrib.django.middleware.SentryMiddleware',
'raven.contrib.django.middleware.SentryLogMiddleware'))
install_middleware(
'raven.contrib.django.middleware.DjangoRestFrameworkCompatMiddleware')
# XXX(dcramer): maybe this setting should disable ALL of this?
if not getattr(settings, 'DISABLE_SENTRY_INSTRUMENTATION', False):
handler = SentryDjangoHandler()
handler.install()
# instantiate client so hooks get registered
get_client() # NOQA
except Exception:
_initialized = False
# Django 1.8 uses ``raven.contrib.apps.RavenConfig``
if django.VERSION < (1, 7, 0):
initialize()