diff --git a/pillar/__init__.py b/pillar/__init__.py index 1f15d21b..c1d0d883 100644 --- a/pillar/__init__.py +++ b/pillar/__init__.py @@ -21,6 +21,7 @@ from flask_babel import Babel, gettext as _ from flask.templating import TemplateNotFound import pymongo.collection import pymongo.database +from raven.contrib.flask import Sentry from werkzeug.local import LocalProxy @@ -59,7 +60,17 @@ class ConfigurationMissingError(SystemExit): """ -class PillarServer(Eve): +class BlinkerCompatibleEve(Eve): + """Workaround for https://github.com/pyeve/eve/issues/1087""" + + def __getattr__(self, name): + if name in {"im_self", "im_func"}: + raise AttributeError("type object '%s' has no attribute '%s'" % + (self.__class__.__name__, name)) + return super().__getattr__(name) + + +class PillarServer(BlinkerCompatibleEve): def __init__(self, app_root, **kwargs): from .extension import PillarExtension from celery import Celery @@ -94,7 +105,9 @@ class PillarServer(Eve): self._config_auth_token_hmac_key() self._config_tempdirs() self._config_git() - self._config_bugsnag() + + self.sentry: typing.Optional[Sentry] = None + self._config_sentry() self._config_google_cloud_storage() self.algolia_index_users = None @@ -187,39 +200,19 @@ class PillarServer(Eve): self.config['GIT_REVISION'] = 'unknown' self.log.info('Git revision %r', self.config['GIT_REVISION']) - def _config_bugsnag(self): - bugsnag_api_key = self.config.get('BUGSNAG_API_KEY') - if self.config.get('TESTING') or not bugsnag_api_key: - self.log.info('Bugsnag NOT configured.') + def _config_sentry(self): + sentry_dsn = self.config.get('SENTRY_CONFIG', {}).get('dsn') + if self.config.get('TESTING') or sentry_dsn in {'', '-set-in-config-local-'}: + self.log.warning('Sentry NOT configured.') + self.sentry = None return - import bugsnag - from bugsnag.handlers import BugsnagHandler + self.sentry = Sentry(self, logging=True, level=logging.WARNING, + logging_exclusions=('werkzeug',)) - release_stage = self.config.get('BUGSNAG_RELEASE_STAGE', 'unconfigured') - if self.config.get('DEBUG'): - release_stage += '-debug' - - bugsnag.configure( - api_key=bugsnag_api_key, - project_root="/data/git/pillar/pillar", - release_stage=release_stage - ) - - bs_handler = BugsnagHandler() - bs_handler.setLevel(logging.ERROR) - self.log.addHandler(bs_handler) - - # This is what bugsnag.flask.handle_exceptions also tries to do, - # but it passes the app to the connect() call, which causes an - # error. Since we only have one app, we can do without. - from flask import got_request_exception - from . import bugsnag_extra - - bugsnag.before_notify(bugsnag_extra.add_pillar_request_to_notification) - got_request_exception.connect(self.__notify_bugsnag) - - self.log.info('Bugsnag setup complete') + # bugsnag.before_notify(bugsnag_extra.add_pillar_request_to_notification) + # got_request_exception.connect(self.__notify_bugsnag) + self.log.info('Sentry setup complete') def __notify_bugsnag(self, sender, exception, **extra): import bugsnag diff --git a/pillar/config.py b/pillar/config.py index 10602ac4..2a263f25 100644 --- a/pillar/config.py +++ b/pillar/config.py @@ -65,8 +65,13 @@ GOOGLE_SITE_VERIFICATION = '' ADMIN_USER_GROUP = '5596e975ea893b269af85c0e' SUBSCRIBER_USER_GROUP = '5596e975ea893b269af85c0f' -BUGSNAG_API_KEY = '' -BUGSNAG_RELEASE_STAGE = 'development' + +SENTRY_CONFIG = { + 'dsn': '-set-in-config-local-', + # 'release': raven.fetch_git_sha(os.path.dirname(__file__)), +} +# See https://docs.sentry.io/clients/python/integrations/flask/#settings +SENTRY_USER_ATTRS = ['username', 'full_name', 'email', 'objectid'] ALGOLIA_USER = '-SECRET-' ALGOLIA_API_KEY = '-SECRET-' diff --git a/requirements.txt b/requirements.txt index 33b12b8f..4ec1b127 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,6 @@ attrs==16.2.0 algoliasearch==1.12.0 bcrypt==3.1.3 blinker==1.4 -bugsnag[flask]==3.1.1 bleach==1.4.3 celery[redis]==4.0.2 CommonMark==0.7.2 @@ -24,6 +23,7 @@ ndg-httpsclient==0.4.0 Pillow==4.1.1 python-dateutil==2.5.3 rauth==0.7.3 +raven[flask]==6.3.0 redis==2.10.5 WebOb==1.5.0 wheel==0.29.0