diff --git a/django_q/cluster.py b/django_q/cluster.py index e49792a..32935a4 100644 --- a/django_q/cluster.py +++ b/django_q/cluster.py @@ -25,7 +25,7 @@ import signing import tasks from django_q.compat import range -from django_q.conf import Conf, logger, psutil, get_ppid, rollbar +from django_q.conf import Conf, logger, psutil, get_ppid, error_reporter from django_q.models import Task, Success, Schedule from django_q.status import Stat, Status from django_q.brokers import get_broker @@ -365,8 +365,8 @@ def worker(task_queue, result_queue, timer, timeout=Conf.TIMEOUT): f = getattr(m, func) except (ValueError, ImportError, AttributeError) as e: result = (e, False) - if rollbar: - rollbar.report_exc_info() + if error_reporter: + error_reporter.report() # We're still going if not result: db.close_old_connections() @@ -380,8 +380,8 @@ def worker(task_queue, result_queue, timer, timeout=Conf.TIMEOUT): result = (res, True) except Exception as e: result = ('{}'.format(e), False) - if rollbar: - rollbar.report_exc_info() + if error_reporter: + error_reporter.report() # Process result task['result'] = result[0] task['success'] = result[1] diff --git a/django_q/conf.py b/django_q/conf.py index 9bfbe71..bf62a17 100644 --- a/django_q/conf.py +++ b/django_q/conf.py @@ -9,6 +9,7 @@ from django.conf import settings # external import os +import pkg_resources # optional try: @@ -141,8 +142,8 @@ class Conf(object): # The redis stats key Q_STAT = 'django_q:{}:cluster'.format(PREFIX) - # Optional Rollbar key - ROLLBAR = conf.get('rollbar', {}) + # Optional error reporting setup + ERROR_REPORTER = conf.get('error_reporter', {}) # OSX doesn't implement qsize because of missing sem_getvalue() try: @@ -177,17 +178,50 @@ if not logger.handlers: handler.setFormatter(formatter) logger.addHandler(handler) -# rollbar -if Conf.ROLLBAR: - rollbar_conf = deepcopy(Conf.ROLLBAR) - try: - import rollbar - rollbar.init(rollbar_conf.pop('access_token'), environment=rollbar_conf.pop('environment'), **rollbar_conf) - except ImportError: - rollbar = None +# Error Reporting Interface +class ErrorReporter(object): + + # initialize with iterator of reporters (better name, targets?) + def __init__(self, reporters): + self.targets = [target for target in reporters] + + # report error to all configured targets + def report(self): + for t in self.targets: + t.report() + + +# error reporting setup (sentry or rollbar) +if Conf.ERROR_REPORTER: + error_conf = deepcopy(Conf.ERROR_REPORTER) + try: + reporters = [] + # iterate through the configured error reporters, + # and instantiate an ErrorReporter using the provided config + for name, conf in error_conf.items(): + Reporter = pkg_resources.iter_entry_points( + 'djangoq.errorreporters', name).load() + e = Reporter(**conf) + reporters.append(e) + error_reporter = ErrorReporter(reporters) + except ImportError: + error_reporter = None else: - rollbar = None + error_reporter = None + +# # rollbar +# if Conf.ROLLBAR: +# rollbar_conf = deepcopy(Conf.ROLLBAR) +# try: +# import rollbar +# rollbar.init(rollbar_conf.pop('access_token'), environment=rollbar_conf.pop('environment'), **rollbar_conf) +# except ImportError: +# rollbar = None + +# else: +# rollbar = None + # get parent pid compatibility diff --git a/setup.py b/setup.py index 854864a..1c4ef11 100644 --- a/setup.py +++ b/setup.py @@ -56,5 +56,15 @@ setup( 'Programming Language :: Python :: 3.6', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development :: Libraries :: Python Modules', - ] + ], + entry_points={ + 'djangoq.errorreporters': [ + 'rollbar = django_q_rollbar.Rollbar', + 'sentry = django_q_sentry.Sentry', + ] + }, + extras_require={ + 'rollbar': ["django-q-rollbar>=0.1"], + 'sentry': ["django-q-sentry>=0.1"], + } )