Пример #1
0
    def test_notify_before_notify_remove_api_key(self):
        def callback(report):
            report.api_key = None

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        self.assertEqual(0, len(self.server.received))
Пример #2
0
 def get(self):
     bugsnag.before_notify(callback)
     raise Exception(
         "Bugsnag Tornado demo says: It crashed! But, due to the attached " +
         "callback the exception has meta information. Go check " +
         "bugsnag.com for a new notification (see the Diagnostics tab)!"
     )
Пример #3
0
def reporteddivide(x, y):
    def callback(notification):
        if notification.context == 'demo.tasks.reporteddivide':
            notification.add_tab('Arguments', {'x': x, 'y': y})

    bugsnag.before_notify(callback)
    return x / y
Пример #4
0
 def get(self):
     bugsnag.before_notify(callback)
     raise Exception(
         "Bugsnag Tornado demo says: It crashed! But, due to the " +
         "attached callback the exception has meta information. Go " +
         "check bugsnag.com for a new notification (see the " +
         "Diagnostics tab)!")
Пример #5
0
def crash_with_callback(request):
    bugsnag.before_notify(callback)
    raise Exception(
        "Bugsnag Django demo says: It crashed! But, due to the attached " +
        "callback the exception has meta information. Go check " +
        "bugsnag.com for a new notification (see the Diagnostics tab)!"
    )
Пример #6
0
def test_uncaught_exception_on_thread_sends_event(bugsnag_server):
    """
    Python 3.8+ has an excepthook for spawned threads. This test checks that
    exceptions thrown by threads are handled.
    """

    def process():
        raise Terrible('oh no')

    def my_program(*args):
        return process()

    def callback(event):
        event.severity = "info"

    bugsnag.configure(app_type='dispatch')
    bugsnag.before_notify(callback)
    thread = threading.Thread(target=my_program)
    thread.start()
    thread.join()

    bugsnag_server.wait_for_request()

    event = bugsnag_server.received[0]['json_body']['events'][0]
    exception = event['exceptions'][0]

    assert 'dispatch' == event['app']['type']
    assert 'info' == event['severity']
    assert 'test_thread_excepthook.Terrible' == exception['errorClass']
    assert 'oh no' == exception['message']
    assert 'process' == exception['stacktrace'][0]['method']
    assert exception['stacktrace'][0]['inProject']
    assert 'my_program' == exception['stacktrace'][1]['method']
    assert exception['stacktrace'][1]['inProject']
    assert not exception['stacktrace'][2]['inProject']
Пример #7
0
    def test_notify_before_notify_modifying_api_key(self):
        def callback(report):
            report.api_key = 'sandwich'

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        headers = self.server.received[0]['headers']
        self.assertEqual('sandwich', headers['Bugsnag-Api-Key'])
Пример #8
0
    def test_notify_before_notify_remove_api_key(self):

        def callback(report):
            report.api_key = None

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        self.assertEqual(0, len(self.server.received))
Пример #9
0
    def test_notify_before_notify_modifying_api_key(self):
        def callback(report):
            report.api_key = 'sandwich'

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        self.assertEqual('sandwich', json_body['apiKey'])
Пример #10
0
    def test_notify_before_notify_modifying_api_key(self):

        def callback(report):
            report.api_key = 'sandwich'

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        headers = self.server.received[0]['headers']
        self.assertEqual('sandwich', headers['Bugsnag-Api-Key'])
Пример #11
0
    def test_notify_before_notify_modifying_metadata(self):
        def callback(report):
            report.meta_data['foo'] = {'sandwich': 'bar'}

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('bar', event['metaData']['foo']['sandwich'])
Пример #12
0
    def test_notify_before_notify_add_custom_data(self):
        def callback(report):
            report.add_custom_data('color', 'green')

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('green', event['metaData']['custom']['color'])
Пример #13
0
def reporteddivide(x, y):
    def callback(notification):
        if notification.context == 'demo.tasks.reporteddivide':
            notification.add_tab('Arguments', {
                'x': x,
                'y': y
            })
    bugsnag.before_notify(callback)
    return x/y
Пример #14
0
    def test_notify_before_notify_modifying_api_key(self):

        def callback(report):
            report.api_key = 'sandwich'

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        self.assertEqual('sandwich', json_body['apiKey'])
Пример #15
0
    def test_notify_callback_app_type(self):
        def callback(report):
            report.app_type = 'whopper'

        bugsnag.configure(app_type='rq')
        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('whopper', event['app']['type'])
Пример #16
0
    def test_notify_before_notify_modifying_metadata(self):

        def callback(report):
            report.meta_data['foo'] = {'sandwich': 'bar'}

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('bar', event['metaData']['foo']['sandwich'])
Пример #17
0
def configure():
    # default to development if in DEBUG mode
    if getattr(settings, 'DEBUG'):
        bugsnag.configure(release_stage='development')

    # Import Bugsnag settings from settings.py
    django_bugsnag_settings = getattr(settings, 'BUGSNAG', {})
    bugsnag.configure(**django_bugsnag_settings)

    bugsnag.before_notify(add_django_request_to_notification)
Пример #18
0
def configure():
    # default to development if in DEBUG mode
    if getattr(settings, 'DEBUG'):
        bugsnag.configure(release_stage='development')

    # Import Bugsnag settings from settings.py
    django_bugsnag_settings = getattr(settings, 'BUGSNAG', {})
    bugsnag.configure(**django_bugsnag_settings)

    bugsnag.before_notify(add_django_request_to_notification)
Пример #19
0
    def test_notify_before_notify_add_custom_data(self):

        def callback(report):
            report.add_custom_data('color', 'green')

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('green', event['metaData']['custom']['color'])
Пример #20
0
    def test_notify_sends_when_before_notify_throws(self):
        def callback(report):
            report.add_custom_data('foo', 'bar')
            raise ScaryException('oh no')

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        self.assertEqual(1, len(self.server.received))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('bar', event['metaData']['custom']['foo'])
Пример #21
0
    def test_external_middleware_cannot_change_severity_reason(self):
        def severity_reason_callback(event):
            event.severity_reason['type'] = 'testReason'

        bugsnag.before_notify(severity_reason_callback)

        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]

        self.assertEqual(event['severityReason']['type'], 'handledException')
Пример #22
0
    def test_notify_sends_when_before_notify_throws(self):

        def callback(report):
            report.add_custom_data('foo', 'bar')
            raise ScaryException('oh no')

        bugsnag.before_notify(callback)
        bugsnag.notify(ScaryException('unexpected failover'))
        self.assertEqual(1, len(self.server.received))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual('bar', event['metaData']['custom']['foo'])
Пример #23
0
    def test_external_middleware_cannot_change_severity_reason(self):

        def severity_reason_callback(notification):
            notification.severity_reason['type'] = 'testReason'

        bugsnag.before_notify(severity_reason_callback)

        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]

        self.assertEqual(event['severityReason']['type'], 'handledException')
Пример #24
0
    def test_external_middleware_can_change_severity(self):
        def severity_callback(notification):
            notification.severity = 'info'

        bugsnag.before_notify(severity_callback)

        bugsnag.notify(ScaryException('unexpected failover'))
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]

        self.assertEqual(event['severity'], 'info')
        self.assertEqual(event['severityReason']['type'],
                         'userCallbackSetSeverity')
Пример #25
0
    def test_notify_unhandled_severity_callback(self):
        def callback(report):
            report.severity = "info"

        bugsnag.before_notify(callback)

        bugsnag.notify(ScaryException("unexpected failover"), severity="error")

        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertFalse(event['unhandled'])
        self.assertEqual(event['severityReason'],
                         {"type": "userCallbackSetSeverity"})
Пример #26
0
    def test_notify_unhandled_severity_callback(self):
        def callback(report):
            report.severity = "info"

        bugsnag.before_notify(callback)

        bugsnag.notify(ScaryException("unexpected failover"), severity="error")

        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertFalse(event['unhandled'])
        self.assertEqual(event['severityReason'], {
            "type": "userCallbackSetSeverity"
        })
Пример #27
0
    def test_read_request_in_callback(self):

        class MyApp(object):

            def __init__(self, environ, start_response):
                raise SentinelError("oops")

        def callback(event):
            event.set_user(id=event.request.GET['user_id'])

        bugsnag.before_notify(callback)
        app = TestApp(BugsnagMiddleware(MyApp))

        with pytest.raises(SentinelError):
            app.get('/beans?user_id=my_id')

        assert len(self.server.received) == 1
        payload = self.server.received[0]['json_body']
        assert payload['events'][0]['user']['id'] == 'my_id'
Пример #28
0
    def test_middleware_stack_order_legacy(self):
        def first_callback(notification):
            notification.meta_data['test']['array'].append(1)

        def second_callback(notification):
            notification.meta_data['test']['array'].append(2)

        # Add a regular callback function
        bugsnag.before_notify(second_callback)

        # Simulate an internal middleware
        bugsnag.legacy.configuration.internal_middleware.before_notify(
                first_callback)

        bugsnag.notify(ScaryException('unexpected failover'),
                       test={'array': []})
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]

        self.assertEqual(event['metaData']['test']['array'], [1, 2])
Пример #29
0
    def test_middleware_stack_order_legacy(self):
        def first_callback(notification):
            notification.meta_data['test']['array'].append(1)

        def second_callback(notification):
            notification.meta_data['test']['array'].append(2)

        # Add a regular callback function
        bugsnag.before_notify(second_callback)

        # Simulate an internal middleware
        bugsnag.legacy.configuration.internal_middleware.before_notify(
                first_callback)

        bugsnag.notify(ScaryException('unexpected failover'),
                       test={'array': []})
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]

        self.assertEqual(event['metaData']['test']['array'], [1, 2])
Пример #30
0
def crash_with_callback(request):
    bugsnag.before_notify(callback)
    raise Exception(
        "crash with callback!"
    )
Пример #31
0
            report.exception = exception


def customize_exception_formatting(record, options):
    """ Caches exception data based on the log record. This is a trivial example, though there could be custom log record properties which are more useful than than the generated error class and message.  This attaches to the log handler.
    """
    if record.exc_info is None:
        exc_type = type("MyCustomException", (Exception,), {})
        exception = exc_type(record.getMessage())
        exception.__module__ = None
        options['custom exception'] = exception


def set_unhandled_from_record(record, options):
    """Overwrites the default value of Bugsnag's 'unhandled' when a log is a level of ERROR or higher.
    """
    if record.levelno >= logging.ERROR:
        options['unhandled'] = True
        options['severity_reason'] = {'type': 'unhandledException'}

# attach your callbacks to Bugsnag. Important to attach AFTER 'addHandler' above, so that the function will have full access to the exception data.
bugsnag.before_notify(use_custom_exception_data)
bugsnag.before_notify(callback)

# Also can attach callbacks to the handler itself:
handler.add_callback(set_unhandled_from_record)
handler.add_callback(customize_exception_formatting)


# This file has configured your Bugsnag client and attached it to your logger.  Now you can import the logger to any other python files in your app, and all exceptions & logs will be reported to your Bugsnag dashboard.
Пример #32
0
 def __init__(self, app):
     bugsnag.before_notify(self.add_context_to_notification)
     self.app = app
Пример #33
0
def crash_with_callback(request):
    bugsnag.before_notify(callback)
    raise Exception("crash with callback!")
Пример #34
0
        'company', {
            'name': 'Stark Industries'
        }
    )

    if notification.context == 'GET /crashcallback':
        # The callback will evaluate all exceptions, but in this example only errors from @app.route('/crashcallback') will have the below data added to their error reports.
        notification.add_tab('Diagnostics', {
            'message': 'Flask demo: Everything is fine',
            'status': 200,
            'password': '******' # this will be filtered by your param_filters.
        })
    # note that if you return false from the callback, this will cancel the entire error report.

# attach your callback to Bugsnag. Important to attach AFTER 'handle_exceptions(app)' above, so that the function will have full access to the exception data.
bugsnag.before_notify(callback)

@app.route('/')
def index():
    return render_template('index.html')


@app.route('/crashdict')
def crashdict():
    """Deliberately triggers an unhandled KeyError to be reported by the bugsnag exception handler, and crash the app.
    """
    customheader = request.headers['my-custom-header']
    return 'Received your header: ' + customheader


@app.route('/crashcallback')
Пример #35
0
def handle_crash_callback(request):
    bugsnag.before_notify(request_inspection)
    terrible_event()
Пример #36
0
 def get(self):
     bugsnag.before_notify(callback)
     raise Exception(
         "It crashed! But, due to the attached " +
         "callback the exception has meta information. Go check " +
         "bugsnag.com for a new notification (see the Diagnostics tab)!")
Пример #37
0
        # The callback will evaluate all exceptions, but in this example only
        # errors from @app.route('/crashcallback') will have the below data
        # added to their error reports.
        notification.add_tab('Diagnostics', {
            'message': 'Flask demo: Everything is fine',
            'status': 200,
            'password': '******'  # this will be filtered
        })
    # note that if you return false from the callback, this will cancel the
    # entire error report.


# attach your callback to Bugsnag. Important to attach AFTER
# 'handle_exceptions(app)' above, so that the function will have full access to
# the exception data.
bugsnag.before_notify(callback)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/crashdict')
def crashdict():
    """
    Deliberately triggers an unhandled KeyError to be reported by the bugsnag
    exception handler, and crash the app.
    """
    customheader = request.headers['my-custom-header']
    return 'Received your header: ' + customheader
Пример #38
0
 def __init__(self, application):
     bugsnag.before_notify(add_wsgi_request_data_to_notification)
     self.application = application
Пример #39
0
def crashcallback():
    bugsnag.before_notify(callback)
    raise (Exception(
        'Flask demo: Everything is fine, check the Diagnostics tab at <a href=\"bugsnag.com\">bugsnag.com</a>'
    ))
 def __init__(self, application):
     bugsnag.before_notify(add_wsgi_request_data_to_notification)
     self.application = application
Пример #41
0
def handle_exceptions(app):
    bugsnag.before_notify(add_flask_request_to_notification)
    got_request_exception.connect(__log_exception, app)
    request_started.connect(__track_session, app)
Пример #42
0
def handle_exceptions(app):
    bugsnag.before_notify(add_flask_request_to_notification)
    got_request_exception.connect(__log_exception, app)
Пример #43
0
    auto_notify=False,
    auto_capture_sessions=False,
)


def bugsnag_global_callback(notification):
    notification.add_tab('system', {
        'platform': platform.platform(),
        'python': platform.python_version()
    })
    cause = notification.exception.__cause__
    if cause:
        notification.add_tab('original exception', error_to_dict(cause))


bugsnag.before_notify(bugsnag_global_callback)

run_housekeeping()

# custom logging handlers


class CachedHandler(logging.Handler):
    """Handler which stores past records.

    :param int maxlen: Maximum number of records to store.
    """
    def __init__(self, maxlen=None):
        logging.Handler.__init__(self)
        self.cached_records = deque([], maxlen)
def setup_logging():
    """ Configure our logger """
    logger = logging.getLogger()

    logger.handlers = []

    if cmd_line.debug:
        log_level = logging.DEBUG
    else:
        log_level = logging.INFO

    logger.setLevel(log_level)

    context_filter = ContextFilter()
    logger.addFilter(context_filter.filter)

    # Log format
    formatter = logging.Formatter(
        fmt="%(asctime)s [%(levelname)s] %(filename)s(%(lineno)d) %(funcName)s(): %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )

    # File logger
    try:
        file_handler = logging.FileHandler("/tmp/DSGos_Installer.log", mode="w")
        file_handler.setLevel(log_level)
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
    except PermissionError as permission_error:
        print("Can't open /tmp/DSGos_Installer.log : ", permission_error)

    # Stdout logger
    if cmd_line.verbose:
        # Show log messages to stdout
        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(log_level)
        stream_handler.setFormatter(formatter)
        logger.addHandler(stream_handler)

    if cmd_line.log_server:
        log_server = cmd_line.log_server

        if log_server == "bugsnag":
            if not BUGSNAG_ERROR:
                # Bugsnag logger
                bugsnag_api = context_filter.api_key
                if bugsnag_api is not None:
                    bugsnag.configure(
                        api_key=bugsnag_api,
                        app_version=info.DSGos_Installer_VERSION,
                        project_root="/usr/share/DSGos-Installer",
                        release_stage=info.DSGos_Installer_RELEASE_STAGE,
                    )
                    bugsnag_handler = BugsnagHandler(api_key=bugsnag_api)
                    bugsnag_handler.setLevel(logging.WARNING)
                    bugsnag_handler.setFormatter(formatter)
                    bugsnag_handler.addFilter(context_filter.filter)
                    bugsnag.before_notify(context_filter.bugsnag_before_notify_callback)
                    logger.addHandler(bugsnag_handler)
                    logging.info("Sending DSGos_Installer log messages to bugsnag server (using python-bugsnag).")
                else:
                    logging.warning("Cannot read the bugsnag api key, logging to bugsnag is not possible.")
            else:
                logging.warning(BUGSNAG_ERROR)
        else:
            # Socket logger
            socket_handler = logging.handlers.SocketHandler(log_server, logging.handlers.DEFAULT_TCP_LOGGING_PORT)
            socket_formatter = logging.Formatter(formatter)
            socket_handler.setFormatter(socket_formatter)
            logger.addHandler(socket_handler)

            # Also add uuid filter to requests logs
            logger_requests = logging.getLogger("requests.packages.urllib3.connectionpool")
            logger_requests.addFilter(context_filter.filter)

            uid = str(uuid.uuid1()).split("-")
            myuid = uid[3] + "-" + uid[1] + "-" + uid[2] + "-" + uid[4]
            logging.info("Sending DSGos_Installer logs to {0} with id '{1}'".format(log_server, myuid))
Пример #45
0
            report.exception = exception


def customize_exception_formatting(record, options):
    """ Caches exception data based on the log record. This is a trivial example, though there could be custom log record properties which are more useful than than the generated error class and message.  This attaches to the log handler.
    """
    if record.exc_info is None:
        exc_type = type("MyCustomException", (Exception, ), {})
        exception = exc_type(record.getMessage())
        exception.__module__ = None
        options['custom exception'] = exception


def set_unhandled_from_record(record, options):
    """Overwrites the default value of Bugsnag's 'unhandled' when a log is a level of ERROR or higher.
    """
    if record.levelno >= logging.ERROR:
        options['unhandled'] = True
        options['severity_reason'] = {'type': 'unhandledException'}


# attach your callbacks to Bugsnag. Important to attach AFTER 'addHandler' above, so that the function will have full access to the exception data.
bugsnag.before_notify(use_custom_exception_data)
bugsnag.before_notify(callback)

# Also can attach callbacks to the handler itself:
handler.add_callback(set_unhandled_from_record)
handler.add_callback(customize_exception_formatting)

# This file has configured your Bugsnag client and attached it to your logger.  Now you can import the logger to any other python files in your app, and all exceptions & logs will be reported to your Bugsnag dashboard.
Пример #46
0
def setup_logging():
    """ Configure our logger """
    logger = logging.getLogger()

    logger.handlers = []

    if cmd_line.debug:
        log_level = logging.DEBUG
    else:
        log_level = logging.INFO

    logger.setLevel(log_level)

    context_filter = ContextFilter()
    logger.addFilter(context_filter.filter)

    # Log format
    formatter = logging.Formatter(
        fmt=
        "%(asctime)s [%(levelname)s] %(filename)s(%(lineno)d) %(funcName)s(): %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S")

    # File logger
    try:
        file_handler = logging.FileHandler('/tmp/cnchi.log', mode='w')
        file_handler.setLevel(log_level)
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
    except PermissionError as permission_error:
        print("Can't open /tmp/cnchi.log : ", permission_error)

    # Stdout logger
    if cmd_line.verbose:
        # Show log messages to stdout
        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(log_level)
        stream_handler.setFormatter(formatter)
        logger.addHandler(stream_handler)

    if cmd_line.log_server:
        log_server = cmd_line.log_server

        if log_server == 'bugsnag':
            if not BUGSNAG_ERROR:
                # Bugsnag logger
                bugsnag_api = context_filter.api_key
                if bugsnag_api is not None:
                    bugsnag.configure(api_key=bugsnag_api,
                                      app_version=info.CNCHI_VERSION,
                                      project_root='/usr/share/cnchi/cnchi',
                                      release_stage=info.CNCHI_RELEASE_STAGE)
                    bugsnag_handler = BugsnagHandler(api_key=bugsnag_api)
                    bugsnag_handler.setLevel(logging.WARNING)
                    bugsnag_handler.setFormatter(formatter)
                    bugsnag_handler.addFilter(context_filter.filter)
                    bugsnag.before_notify(
                        context_filter.bugsnag_before_notify_callback)
                    logger.addHandler(bugsnag_handler)
                    logging.info(
                        "Sending Cnchi log messages to bugsnag server (using python-bugsnag)."
                    )
                else:
                    logging.warning(
                        "Cannot read the bugsnag api key, logging to bugsnag is not possible."
                    )
            else:
                logging.warning(BUGSNAG_ERROR)
        else:
            # Socket logger
            socket_handler = logging.handlers.SocketHandler(
                log_server, logging.handlers.DEFAULT_TCP_LOGGING_PORT)
            socket_formatter = logging.Formatter(formatter)
            socket_handler.setFormatter(socket_formatter)
            logger.addHandler(socket_handler)

            # Also add uuid filter to requests logs
            logger_requests = logging.getLogger(
                "requests.packages.urllib3.connectionpool")
            logger_requests.addFilter(context_filter.filter)

            uid = str(uuid.uuid1()).split("-")
            myuid = uid[3] + "-" + uid[1] + "-" + uid[2] + "-" + uid[4]
            logging.info("Sending Cnchi logs to {0} with id '{1}'".format(
                log_server, myuid))
Пример #47
0
    bugsnag.configure(
        api_key=app.config['BUGSNAG_API_KEY'],
        project_root="/data/dev/pillar-web/pillar-web",
    )

    def bugsnag_notify_callback(notification):
        # If we return False, the notification will not be sent to Bugsnag.
        if isinstance(notification.exception, KeyboardInterrupt):
            return False
        if current_user.is_authenticated():
            notification.user = dict(id=current_user.id,
                                     name=current_user.full_name,
                                     email=current_user.email)
            notification.add_tab("account", {"roles": current_user.roles})

    bugsnag.before_notify(bugsnag_notify_callback)
    handle_exceptions(app)

# Login manager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "users.login"
login_manager.login_message = u''


@login_manager.user_loader
def load_user(userid):
    from application import system_util

    api = system_util.pillar_api(token=userid)