Exemplo n.º 1
0
    def test_notify_error(self):
        ab = Airbrake(project_id=1234, api_key='fake')

        try:
            raise TypeError
        except Exception as e:
            exc_info = sys.exc_info()
            error = Error(exc_info=exc_info)
            user = {"id": "12345", "name": "root", "email": "*****@*****.**"}
            notice = ab.build_notice(error, user=user)

            exception_str = type(e).__name__
            exception_type = type(e).__name__

            expected_payload = self.get_expected_payload(
                exception_str, exception_type)

            data = {
                'type': exc_info[1].__class__.__name__,
                'backtrace': format_backtrace(exc_info[2]),
                'message': pytb_lastline(exc_info)
            }

            expected_payload['errors'] = [data]
            expected_payload['context']['user'] = user
            expected_payload['context']['severity'] = ErrorLevels.DEFAULT_LEVEL

            self.assertEqual(expected_payload, notice.payload)

            with mock.patch('requests.post') as requests_post:
                ab.notify(error)
                data = json.loads(requests_post.call_args[1]['data'])
                self.assertEqual(expected_payload, data)
Exemplo n.º 2
0
    def test_notify_context(self):
        with mock.patch('requests.post') as requests_post:
            version = platform.python_version()
            plat = platform.platform()
            environment = u"testing123"
            root_directory = u"/home/app/"

            ab = Airbrake(project_id=1234,
                          api_key='fake',
                          environment=environment,
                          root_directory=root_directory)
            ab.log("this is a test")

            expected_context = {
                u'notifier': {
                    u'name': u'airbrake-python',
                    u'version': __version__,
                    u'url': __url__
                },
                u'os': plat,
                u'hostname': socket.gethostname(),
                u'language': u'Python/%s' % version,
                u'environment': environment,
                u'rootDirectory': root_directory,
                u'severity': ErrorLevels.DEFAULT_LEVEL,
            }

            data = json.loads(requests_post.call_args[1]['data'])
            actual_context = data["context"]

            self.assertEqual(expected_context, actual_context)
Exemplo n.º 3
0
    def test_log_with_severity(self):
        with mock.patch('requests.post') as requests_post:
            ab = Airbrake(project_id=1234, api_key='fake')
            ab.log("this is a test", severity=ErrorLevels.CRITICAL)

            data = json.loads(requests_post.call_args[1]['data'])
            actual_context = data["context"]

            self.assertEqual(actual_context[u'severity'], ErrorLevels.CRITICAL)
Exemplo n.º 4
0
class AirbrakeHandler(logging.Handler):
    """A handler class which ships logs to airbrake.io.

    Requires one:
        * `project_id` AND `api_key`
        * an instance of airbrake.Airbrake
    """
    def __init__(self,
                 airbrake=None,
                 level=logging.ERROR,
                 project_id=None,
                 api_key=None,
                 environment=None,
                 base_url=None):
        """Initialize the Airbrake handler with a default logging level.

        Default level of logs handled by this class are >= ERROR,
        which includes ERROR and CRITICAL. To change this behavior
        supply a different argument for 'level'.
        """

        logging.Handler.__init__(self, level=level)

        if isinstance(airbrake, Airbrake):
            self.airbrake = airbrake
        else:
            self.airbrake = Airbrake(project_id, api_key, environment,
                                     base_url)

    def emit(self, record):
        """Log the record airbrake.io style.

        To prevent method calls which invoke this handler from using the
        global exception context in sys.exc_info(), exc_info must be passed
        as False.

        E.g. To prevent AirbrakeHandler from reading the global exception
        context, (which it may do to find a traceback and error type), make
        logger method calls like this:

            LOG.error("Bad math.", exc_info=False)

        Otherwise, provide exception context directly, though the following
        contrived example would be a strange way to use the handler:

            exc_info = sys.exc_info()
            ...
            LOG.error("Bad math.", exc_info=exc_info)
        """
        try:
            airbrakeerror = airbrake_error_from_logrecord(record)
            self.airbrake.log(**airbrakeerror)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:  # pylint: disable=bare-except
            self.handleError(record)
Exemplo n.º 5
0
    def test_deploy_revision(self):
        with mock.patch('requests.post') as requests_post:
            ab = Airbrake(project_id=1234, api_key='fake', environment='test')
            ab.deploy('test', 'user1', 'https://github.com/airbrake/airbrake',
                      None, 'v2.0')

            data = json.loads(requests_post.call_args[1]['data'])
            version = airbrake.utils.get_local_git_revision()

            self.assertEqual(version, data['revision'])
Exemplo n.º 6
0
class AirbrakeHandler(logging.Handler):
    """A handler class which ships logs to airbrake.io.

    Requires one:
        * `project_id` AND `api_key`
        * an instance of airbrake.Airbrake
    """

    def __init__(self, airbrake=None, level=logging.ERROR, project_id=None,
                 api_key=None, environment=None, base_url=None):
        """Initialize the Airbrake handler with a default logging level.

        Default level of logs handled by this class are >= ERROR,
        which includes ERROR and CRITICAL. To change this behavior
        supply a different argument for 'level'.
        """

        logging.Handler.__init__(self, level=level)

        if isinstance(airbrake, Airbrake):
            self.airbrake = airbrake
        else:
            self.airbrake = Airbrake(project_id, api_key, environment,
                                     base_url)

    def emit(self, record):
        """Log the record airbrake.io style.

        To prevent method calls which invoke this handler from using the
        global exception context in sys.exc_info(), exc_info must be passed
        as False.

        E.g. To prevent AirbrakeHandler from reading the global exception
        context, (which it may do to find a traceback and error type), make
        logger method calls like this:

            LOG.error("Bad math.", exc_info=False)

        Otherwise, provide exception context directly, though the following
        contrived example would be a strange way to use the handler:

            exc_info = sys.exc_info()
            ...
            LOG.error("Bad math.", exc_info=exc_info)
        """
        try:
            airbrakeerror = airbrake_error_from_logrecord(record)
            self.airbrake.log(**airbrakeerror)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:  # pylint: disable=bare-except
            self.handleError(record)
Exemplo n.º 7
0
    def test_notice_severity(self):
        ab = Airbrake(project_id=1234, api_key='fake')
        notice = ab.build_notice(ValueError("This is a test"),
                                 severity=ErrorLevels.CRITICAL)

        self.assertEqual(ErrorLevels.CRITICAL,
                         notice.payload['context']['severity'])

        with mock.patch('requests.post') as requests_post:
            ab.notify(notice)
            data = json.loads(requests_post.call_args[1]['data'])
            error_level = data['context']['severity']
            self.assertEqual(ErrorLevels.CRITICAL, error_level)
Exemplo n.º 8
0
    def test_notify_str(self):
        ab = Airbrake(project_id=1234, api_key='fake')
        exception_str = "This is a test"
        exception_type = 'Error'
        notice = ab.build_notice(exception_str)

        expected_payload = self.get_expected_payload(exception_str,
                                                     exception_type)
        self.assertEqual(expected_payload, notice.payload)

        with mock.patch('requests.post') as requests_post:
            ab.notify(exception_str)
            data = json.loads(requests_post.call_args[1]['data'])
            self.assertEqual(expected_payload, data)
Exemplo n.º 9
0
    def test_deploy_payload(self):
        with mock.patch('requests.post') as requests_post:
            ab = Airbrake(project_id=1234, api_key='fake', environment='test')
            ab.deploy('test', 'user1', 'https://github.com/airbrake/airbrake',
                      '38748467ea579e7ae64f7815452307c9d05e05c5', 'v2.0')

            expected_call_args = mock.call(
                'https://airbrake.io/api/v4/projects/1234/deploys',
                data='{"environment": "test",'
                ' "repository": "https://github.com/airbrake/airbrake",'
                ' "revision": "38748467ea579e7ae64f7815452307c9d05e05c5",'
                ' "username": "******",'
                ' "version": "v2.0"}',
                headers={'Content-Type': 'application/json'},
                params={'key': 'fake'},
                timeout=Airbrake.AIRBRAKE_TIMEOUT_DEFAULT)
            self.assertEqual(expected_call_args, requests_post.call_args)
Exemplo n.º 10
0
    def __init__(self,
                 airbrake=None,
                 level=logging.ERROR,
                 project_id=None,
                 api_key=None,
                 **config):
        """Initialize the Airbrake handler with a default logging level.

        Default level of logs handled by this class are >= ERROR,
        which includes ERROR and CRITICAL. To change this behavior
        supply a different argument for 'level'.
        """

        logging.Handler.__init__(self, level=level)

        if isinstance(airbrake, Airbrake):
            self.airbrake = airbrake
        else:
            self.airbrake = Airbrake(project_id, api_key, **config)
Exemplo n.º 11
0
    def test_blacklist(self):
        ab = Airbrake(project_id=1234,
                      api_key='fake',
                      blacklist_keys=["filter_me_i_dare_you", "blacklist_me"])
        expected_params = {
            "filter_me_i_dare_you": "[Filtered]",
            "blacklist_me": "[Filtered]",
            "page": 1,
            "order": "desc"
        }

        self.check_filter(ab, expected_params)
Exemplo n.º 12
0
    def check_timeout(self, timeout=None, expected_timeout=None):
        ab = Airbrake(project_id=1234,
                      api_key='fake',
                      environment='test',
                      timeout=timeout)
        if not timeout:
            ab = Airbrake(project_id=1234, api_key='fake', environment='test')

        with mock.patch('requests.post') as requests_post:
            ab.deploy('test', 'user1')
            timeout = requests_post.call_args[1]['timeout']
            self.assertEqual(expected_timeout, timeout)

        with mock.patch('requests.post') as requests_post:
            notice = ab.build_notice("This is a test")
            ab.notify(notice)
            timeout = requests_post.call_args[1]['timeout']
            self.assertEqual(expected_timeout, timeout)
Exemplo n.º 13
0
    def test_capture(self):
        ab = Airbrake(project_id=1234, api_key='fake')

        try:
            raise ValueError("oh nos")
        except Exception:
            with mock.patch('requests.post') as requests_post:
                ab.capture()

                exc_info = sys.exc_info()
                raw_frames = traceback.extract_tb(exc_info[2])
                exc_frame = raw_frames[0]
                exception_str = exc_frame[3]
                exception_type = "ERROR:%s" % exc_frame[0]

                expected_payload = self.get_expected_payload(
                    exception_str, exception_type)

                data = {
                    'type': exc_info[1].__class__.__name__,
                    'backtrace': format_backtrace(exc_info[2]),
                    'message': str(exc_frame[3])
                }

                expected_payload['errors'] = [data]
                expected_payload['context']['severity'] =\
                    ErrorLevels.DEFAULT_LEVEL

                err = Error(exc_info=exc_info,
                            filename=str(exc_frame[0]),
                            line=str(exc_frame[1]),
                            function=str(exc_frame[2]),
                            message=str(exc_frame[3]),
                            errtype="ERROR:%s" % str(exc_frame[0]))
                notice = ab.build_notice(err)
                self.assertEqual(expected_payload, notice.payload)

                data = json.loads(requests_post.call_args[1]['data'])
                self.assertEqual(expected_payload, data)
Exemplo n.º 14
0
    def __init__(self, airbrake=None, level=logging.ERROR, project_id=None,
                 api_key=None, environment=None):
        """Initialize the Airbrake handler with a default logging level.

        Default level of logs handled by this class are >= ERROR,
        which includes ERROR and CRITICAL. To change this behavior
        supply a different argument for 'level'.
        """

        logging.Handler.__init__(self, level=level)

        if isinstance(airbrake, Airbrake):
            self.airbrake = airbrake
        else:
            self.airbrake = Airbrake(project_id, api_key, environment)
Exemplo n.º 15
0
    def test_uncaught_exception(self):
        ab = Airbrake(project_id=1234, api_key='fake')
        self.preserved_syshook = False

        def early_exit_syshook(*exc_info):
            self.preserved_syshook = True
            return

        ab.excepthook = early_exit_syshook

        with mock.patch('requests.post') as requests_post:
            try:
                raise Exception("raise to sys level")
            except Exception:
                # nose wraps exceptions, so manually call the exception as
                # if it was uncaught.
                exc_info = sys.exc_info()

                sys.excepthook(*exc_info)

            data = json.loads(requests_post.call_args[1]['data'])
            error_level = data['context']['severity']
            self.assertEqual(ErrorLevels.ERROR, error_level)
            self.assertTrue(self.preserved_syshook)
Exemplo n.º 16
0
    def test_capture_decorator(self):
        ab = Airbrake(project_id=1234, api_key='fake')

        with mock.patch('requests.post') as requests_post:

            @capture(ab)
            def faulty_func(msg):
                raise ValueError(msg)

            msg = "I am a banana"
            with self.assertRaises(ValueError) as cm:
                faulty_func(msg)
            self.assertEqual(msg, str(cm.exception))

            data = json.loads(requests_post.call_args[1]['data'])
            err_data = data['errors'][0]
            self.assertEqual(err_data['backtrace'][0]['function'],
                             'faulty_func')
            filename = err_data['backtrace'][0]['file']
            self.assertTrue(filename.endswith("tests/test_notifier.py"))
Exemplo n.º 17
0
from airbrake.notifier import Airbrake

manager = Airbrake(project_id=144031,
                   api_key="5a2fb879e83b40479b90284263193376")

try:
    # Raising an exception.
    1 / 0
except ZeroDivisionError as e:
    # Sends a 'division by zero' exception to Airbrake.
    manager.notify(e)
except:
    # Sends all other exceptions to Airbrake.
    manager.capture()
Exemplo n.º 18
0
#!/usr/bin/env python3
# coding=utf-8

import serial
import time
import struct
import requests
import json
from airbrake.notifier import Airbrake

with open('config.json') as f:
    CONFIG = json.load(f)

ab = Airbrake(host=CONFIG["ERRBIT_HOST"],
              api_key=CONFIG["ERRBIT_PROJECT_KEY"],
              project_id=CONFIG["ERRBIT_PROJECT_ID"])


class BTPOWER:
    setAddrBytes = [0xB4, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1E]
    readVoltageBytes = [0xB0, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1A]
    readCurrentBytes = [0XB1, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1B]
    readPowerBytes = [0XB2, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1C]
    readRegPowerBytes = [0XB3, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1D]

    def __init__(self, com=CONFIG["USB_SERIAL"], timeout=10.0):
        self.ser = serial.Serial(port=com,
                                 baudrate=9600,
                                 parity=serial.PARITY_NONE,
                                 stopbits=serial.STOPBITS_ONE,
                                 bytesize=serial.EIGHTBITS,
Exemplo n.º 19
0
class AirbrakeNotifier:

    MAX_NOTIFICATIONS = 50
    airbrake_notifier = Airbrake(project_id=config['airbrake_project_id'],
                                 api_key=config['airbrake_api_key'])
    blacklisted_log_group_names = set(
        config['airbrake_blacklisted_log_group_names'])
    blacklisted_log_message_strings_regex = re.compile('|'.join(
        config["airbrake_blacklisted_log_message_strings"]))
    whitelisted_log_message_terms_regex_string = "|".join(
        config['airbrake_whitelisted_log_message_terms'])
    whitelisted_log_message_terms_regexp = re.compile(
        whitelisted_log_message_terms_regex_string, re.IGNORECASE)

    def __init__(self):
        self._report = dict()
        self._total_errors = 0
        self._airbrake_rate_limited = False

    def report(self):
        results = []
        for log_group, subcounts in self._report.items():
            for message_type, count in subcounts.items():
                results += [(log_group, message_type, count)]
        return results

    def notify_on_stream(self, log_event_stream):
        for log_event in log_event_stream:
            self.notify(log_event)
            yield log_event

    def notify(self, log_event):
        message = log_event['@message']
        log_group = log_event['@log_group']
        log_stream = log_event['@log_stream']
        error_str = None
        if AirbrakeNotifier._is_message_appropriate_for_airbrake(message, log_group) and \
                not AirbrakeNotifier._contains_blacklisted_string(message):
            error_str = "'{0} {1} '@log_stream': {2}".format(
                log_group, message, log_stream)
            try:
                if not self._airbrake_rate_limited and self._total_errors < AirbrakeNotifier.MAX_NOTIFICATIONS:
                    AirbrakeNotifier.airbrake_notifier.notify(error_str)
            except Exception as e:
                message = str(e)
                if message.startswith('420 Client Error'):
                    self._airbrake_rate_limited = True
                else:
                    logger.error(
                        "Airbrake notification failed! {}".format(message))
        self._observe(log_group, error_str)

    def _observe(self, log_group, error_str):
        if log_group not in self._report:
            self._report[log_group] = {'errors': 0, 'total': 0}
        if error_str:
            self._report[log_group]['errors'] += 1
            self._total_errors += 1
        self._report[log_group]['total'] += 1

    @staticmethod
    def _is_message_appropriate_for_airbrake(message, log_group):
        if log_group not in AirbrakeNotifier.blacklisted_log_group_names and \
                AirbrakeNotifier.whitelisted_log_message_terms_regexp.search(message):
            return True
        return False

    @staticmethod
    def _contains_blacklisted_string(message):
        if AirbrakeNotifier.blacklisted_log_message_strings_regex.search(
                message):
            return True
        return False