Пример #1
0
def main():
    from .application import Application

    # set up logging
    monitor_logger = logging.getLogger("rfi_downloader")
    monitor_logger.setLevel(logging.DEBUG)

    log_fmt_long = logging.Formatter(
        fmt="%(asctime)s %(name)s %(levelname)s: %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )

    # log to stdout
    log_handler_stream = logging.StreamHandler(sys.stdout)
    log_handler_stream.setFormatter(log_fmt_long)
    log_handler_stream.setLevel(logging.DEBUG)
    monitor_logger.addHandler(log_handler_stream)

    # log to bugsnag
    log_handler_bugsnag = BugsnagHandler()
    log_handler_bugsnag.setLevel(logging.WARNING)
    monitor_logger.addHandler(log_handler_bugsnag)

    app = Application()
    rv = app.run(sys.argv)
    sys.exit(rv)
Пример #2
0
def configure_logging(config):
    logging.basicConfig(
        level=logging.INFO,
        format='[%(asctime)s] - [%(levelname)s] - [%(funcName)s] - %(message)s',
        datefmt='%m/%d/%Y %I:%M:%S %p',
        filename='transcribersofreddit.log'
    )
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter('[%(asctime)s] - [%(funcName)s] - %(message)s')
    # tell the handler to use this format
    console.setFormatter(formatter)

    # add the handlers to the root logger
    logging.getLogger('').addHandler(console)
    # will intercept anything error level or above
    if config.bs_api_key:
        bs_handler = BugsnagHandler()
        bs_handler.setLevel(logging.ERROR)
        logging.getLogger('').addHandler(bs_handler)

    if config.bs_api_key:
        logging.info('Bugsnag enabled!')
    else:
        logging.info('Not running with Bugsnag!')

    log_header('Starting!')
Пример #3
0
def main():
    # set up logging
    monitor_logger = logging.getLogger('rfi_file_monitor')
    monitor_logger.setLevel(logging.DEBUG)

    log_fmt_long = logging.Formatter(
        fmt='%(asctime)s %(name)s %(levelname)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    # log to stdout
    log_handler_stream = logging.StreamHandler(sys.stdout)
    log_handler_stream.setFormatter(log_fmt_long)
    log_handler_stream.setLevel(logging.DEBUG)
    monitor_logger.addHandler(log_handler_stream)

    # log to bugsnag
    log_handler_bugsnag = BugsnagHandler()
    log_handler_bugsnag.setLevel(logging.INFO)
    monitor_logger.addHandler(log_handler_bugsnag)

    logger.info('Started')
    app = Application()
    rv = app.run(sys.argv)
    logger.info('Finished')
    sys.exit(rv)
Пример #4
0
def configure_logging(config, log_name='transcribersofreddit.log'):
    logging.basicConfig(
        level=logging.INFO,
        format='%(levelname)s | %(funcName)s | %(message)s',
        datefmt='%Y-%m-%dT%H:%M:%S',
    )

    # will intercept anything error level or above
    if config.bugsnag_api_key:
        bs_handler = BugsnagHandler()
        bs_handler.setLevel(logging.ERROR)
        logging.getLogger('').addHandler(bs_handler)
        logging.info('Bugsnag enabled!')
    else:
        logging.info('Not running with Bugsnag!')

    if config.sentry_api_url:
        sentry_handler = SentryHandler(Client(config.sentry_api_url))
        sentry_handler.setLevel(logging.ERROR)
        # I don't know what this line does but it seems required by raven
        setup_logging(sentry_handler)
        logging.getLogger('').addHandler(sentry_handler)
        logging.info('Sentry enabled!')
    else:
        logging.info('Not running with Sentry!')

    log_header('Starting!')
Пример #5
0
def configure_logging(config, log_name='transcribersofreddit.log'):
    logging.basicConfig(
        level=logging.INFO,
        format='[%(asctime)s] - [%(levelname)s] - [%(funcName)s] - %(message)s',
        datefmt='%m/%d/%Y %I:%M:%S %p',
        filename=log_name)
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter(
        '[%(asctime)s] - [%(funcName)s] - %(message)s')
    # tell the handler to use this format
    console.setFormatter(formatter)

    # add the handlers to the root logger
    logging.getLogger('').addHandler(console)
    # will intercept anything error level or above
    if config.bugsnag_api_key:
        bs_handler = BugsnagHandler()
        bs_handler.setLevel(logging.ERROR)
        logging.getLogger('').addHandler(bs_handler)
        logging.info('Bugsnag enabled!')
    else:
        logging.info('Not running with Bugsnag!')

    if config.sentry_api_url:
        sentry_handler = SentryHandler(Client(config.sentry_api_url))
        sentry_handler.setLevel(logging.ERROR)
        # I don't know what this line does but it seems required by raven
        setup_logging(sentry_handler)
        logging.getLogger('').addHandler(sentry_handler)
        logging.info('Sentry enabled!')
    else:
        logging.info('Not running with Sentry!')

    log_header('Starting!')
Пример #6
0
def configure_bugsnag_error_monitoring(bugsnag_key, bugsnag_release_stage):
    bugsnag.configure(api_key=bugsnag_key,
                      project_root="./",
                      notify_release_stages=["production", "staging"],
                      release_stage=bugsnag_release_stage)
    bugsnag_handler = BugsnagHandler()
    bugsnag_handler.setLevel(logging.ERROR)
    add_handler_to_logger(bugsnag_handler)
Пример #7
0
def init_bugsnag(app_version: str):
    bugsnag.configure(api_key=BUGSNAG_ID,
                      project_root=Path(__file__).parent / 'pingou',
                      notify_release_stages=['production'],
                      release_stage=RELEASE_STAGE,
                      app_version=app_version)
    bugsnag_handler = BugsnagHandler()
    bugsnag_handler.setLevel(logging.ERROR)
    return bugsnag_handler
    def test_custom_level(self):
        handler = BugsnagHandler()
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        logger.log(341, 'The system is down')
        logger.removeHandler(handler)

        self.assertSentReportCount(1)
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        exception = event['exceptions'][0]
        self.assertEqual('LogLevel 341', exception['errorClass'])
    def test_message(self):
        handler = BugsnagHandler()
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        logger.critical('The system is down')
        logger.removeHandler(handler)

        self.assertSentReportCount(1)

        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        exception = event['exceptions'][0]
        self.assertEqual('The system is down', exception['message'])
    def test_extra_fields(self):
        handler = BugsnagHandler(extra_fields={'fruit': ['grapes', 'pears']})
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        logger.error('A wild tomato appeared', extra={
            'grapes': 8, 'pears': 2, 'tomatoes': 1
        })
        logger.removeHandler(handler)

        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual(event['metaData']['fruit'], {
            'grapes': 8, 'pears': 2
        })
    def test_exc_info(self):
        handler = BugsnagHandler()
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        try:
            raise ScaryException('Oh no')
        except Exception:
            logger.exception('The system is down')

        logger.removeHandler(handler)

        self.assertSentReportCount(1)
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        exception = event['exceptions'][0]
        self.assertEqual(exception['errorClass'], 'tests.utils.ScaryException')
Пример #12
0
def configure_logging(cfg, log_name='transcribersofreddit.log'):
    logging.basicConfig(
        level=logging.INFO,
        format='%(levelname)s | %(funcName)s | %(message)s',
        datefmt='%Y-%m-%dT%H:%M:%S',
    )

    # will intercept anything error level or above
    if cfg.bugsnag_api_key:
        bs_handler = BugsnagHandler()
        bs_handler.setLevel(logging.ERROR)
        logging.getLogger('').addHandler(bs_handler)
        logging.info('Bugsnag enabled!')
    else:
        logging.info('Not running with Bugsnag!')

    log_header('Starting!')
Пример #13
0
    def _setup_logging(self):

        log_level = self._conf.get("app", "log_level")
        mdbx_logger = logging.getLogger("maestral")
        mdbx_logger.setLevel(logging.DEBUG)

        log_fmt_long = logging.Formatter(
            fmt="%(asctime)s %(name)s %(levelname)s: %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S")
        log_fmt_short = logging.Formatter(fmt="%(message)s")

        # log to file
        rfh_log_file = get_log_path("maestral", self._config_name + ".log")
        self._log_handler_file = logging.handlers.RotatingFileHandler(
            rfh_log_file, maxBytes=10**7, backupCount=1)
        self._log_handler_file.setFormatter(log_fmt_long)
        self._log_handler_file.setLevel(log_level)
        mdbx_logger.addHandler(self._log_handler_file)

        # log to journal when launched from systemd
        if INVOCATION_ID and journal:
            self._log_handler_journal = journal.JournalHandler()
            self._log_handler_journal.setFormatter(log_fmt_short)
            mdbx_logger.addHandler(self._log_handler_journal)

        # log to stdout (disabled by default)
        self._log_handler_stream = logging.StreamHandler(sys.stdout)
        self._log_handler_stream.setFormatter(log_fmt_long)
        self._log_handler_stream.setLevel(100)
        mdbx_logger.addHandler(self._log_handler_stream)

        # log to cached handlers for GUI and CLI
        self._log_handler_info_cache = CachedHandler(maxlen=1)
        self._log_handler_info_cache.setLevel(logging.INFO)
        self._log_handler_info_cache.setFormatter(log_fmt_short)
        mdbx_logger.addHandler(self._log_handler_info_cache)

        self._log_handler_error_cache = CachedHandler()
        self._log_handler_error_cache.setLevel(logging.ERROR)
        self._log_handler_error_cache.setFormatter(log_fmt_short)
        mdbx_logger.addHandler(self._log_handler_error_cache)

        # log to bugsnag (disabled by default)
        self._log_handler_bugsnag = BugsnagHandler()
        self._log_handler_bugsnag.setLevel(100)
        mdbx_logger.addHandler(self._log_handler_bugsnag)
    def test_severity_warning(self):
        handler = BugsnagHandler()
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        logger.warning('The system is down')
        logger.removeHandler(handler)

        self.assertSentReportCount(1)
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        exception = event['exceptions'][0]
        self.assertEqual('LogWARNING', exception['errorClass'])
        self.assertEqual('warning', event['severity'])
        self.assertEqual(logging.WARNING,
                         event['metaData']['extra data']['levelno'])
        self.assertEqual('WARNING',
                         event['metaData']['extra data']['levelname'])
Пример #15
0
    def test_levelname_message(self):
        handler = BugsnagHandler()
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        class MessageFilter(logging.Filter):
            def filter(self, record):
                record.levelname = None
                return True

        handler.addFilter(MessageFilter())
        logger.info('The system is down')
        logger.removeHandler(handler)

        self.assertSentReportCount(1)
        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        exception = event['exceptions'][0]
        self.assertEqual('LogMessage', exception['errorClass'])
Пример #16
0
    def test_severity_critical(self):
        handler = BugsnagHandler()
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)

        logger.critical('The system is down')
        logger.removeHandler(handler)

        self.assertSentReportCount(1)

        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        exception = event['exceptions'][0]
        self.assertEqual('LogCRITICAL', exception['errorClass'])
        self.assertEqual('error', event['severity'])
        self.assertEqual(logging.CRITICAL,
                         event['metaData']['extra data']['levelno'])
        self.assertEqual(u('CRITICAL'),
                         event['metaData']['extra data']['levelname'])
Пример #17
0
    def test_extra_fields(self):
        class FruitFilter(logging.Filter):
            def filter(self, record):
                record.grapes = 8
                record.pears = 2
                record.apricots = 90
                return True

        handler = BugsnagHandler(api_key='new news',
                                 extra_fields={'fruit': ['grapes', 'pears']})
        logger = logging.getLogger(__name__)
        logger.addHandler(handler)
        logger.addFilter(FruitFilter())

        logger.error('A wild tomato appeared')
        logger.removeHandler(handler)

        json_body = self.server.received[0]['json_body']
        event = json_body['events'][0]
        self.assertEqual(event['metaData']['fruit'], {'grapes': 8, 'pears': 2})
Пример #18
0
    def _config_bugsnag(self):
        # Configure Bugsnag
        if self.config.get(
                'TESTING') or not self.config.get('BUGSNAG_API_KEY'):
            self.log.info('Bugsnag NOT configured.')
            return

        import bugsnag
        from bugsnag.flask import handle_exceptions
        from bugsnag.handlers import BugsnagHandler

        bugsnag.configure(
            api_key=self.config['BUGSNAG_API_KEY'],
            project_root="/data/git/pillar/pillar",
        )
        handle_exceptions(self)

        bs_handler = BugsnagHandler()
        bs_handler.setLevel(logging.ERROR)
        self.log.addHandler(bs_handler)
Пример #19
0
    def _initialize(self):
        bugsnag.configure(api_key=self._bugsnag_key,
                          project_root=self._app_dir)
        logging.config.dictConfig(self.get_logging_config())

        logger = logging.getLogger('antbs')

        for logger_name in self._noisy_loggers:
            _logger = logging.getLogger(logger_name)
            _logger.setLevel(logging.ERROR)

        bs_handler_found = [
            h for h in logger.handlers if isinstance(h, BugsnagHandler)
        ]

        if not bs_handler_found:
            bugsnag_handler = BugsnagHandler()
            bugsnag_handler.setLevel(logging.WARNING)
            logger.addHandler(bugsnag_handler)

        self.logger = logger
Пример #20
0
def configure_logging(cfg: Config,
                      log_name="transcribersofreddit.log") -> None:
    # Set formatting and logging level.
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s | %(levelname)s | %(funcName)s | %(message)s",
        filename=log_name,
    )

    if cfg.bugsnag_api_key:
        # will intercept anything error level or above
        bs_handler = BugsnagHandler()
        bs_handler.setLevel(logging.ERROR)
        logging.getLogger().addHandler(bs_handler)
        log.info("Bugsnag is successfully enabled!")
    else:
        log.info("No Bugsnag API Key found. Not running with Bugsnag!")

    log.info("*" * 50)
    log.info("Logging configured. Starting program!")
    log.info("*" * 50)
Пример #21
0
 def log_handler(self, extra_fields=None):
     return BugsnagHandler(client=self, extra_fields=extra_fields)
Пример #22
0
from integrations.music_service_fetchers.spotify_fetcher import SpotifyFetcher
from integrations.models import Release
from django.core.mail import send_mail
import datetime
import os
import requests

import bugsnag
import logging
from bugsnag.handlers import BugsnagHandler
bugsnag.configure(
    api_key=os.environ.get('BUGSNAG_API_KEY'),
    project_root='../../',
)
logger = logging.getLogger('test.logger')
handler = BugsnagHandler()
handler.setLevel(logging.ERROR)
logger.addHandler(handler)


class Command(BaseCommand):
    help = 'Fetches latest releases'

    def handle(self, *args, **options):
        users = User.objects.all()

        for user in users:
            self.stdout.write(
                self.style.SUCCESS(f'starting fetching for {user.email}'))

            integration = None
Пример #23
0
    # Any param key that contains one of these strings will be filtered out of all error reports.
    params_filters=["credit_card_number", "password", "ssn"],

    # We mark stacktrace lines as inProject if they come from files inside root:
    # project_root = "/path/to/your/app",

    # Useful if you are wrapping bugsnag.notify() in with your own library, to ensure errors group properly.
    # traceback_exclude_module = [myapp.custom_logging],
)

# Create a logger
logger = logging.getLogger("test.logger")

# Create a Bugsnag handler.
# Optionally, add 'extra_fields' which will attach meta_data to every Bugsnag report. The values should be attributes to pull off each log record.
handler = BugsnagHandler(extra_fields={"logger": ["__repr__"]})

# Define which level of log you want to report to Bugsnag. Here, warning & above.
handler.setLevel(logging.WARNING)

# Attach the Bugsnag handler to your logger.
logger.addHandler(handler)


# You can define a callback function which, when attached to your Bugsnag client, will run right before each and every report is sent to the api.  Here you can evaluate and modify the report data.
def callback(notification):
    """This callback will evaluate and modify every exception report, handled and unhandled, that occurs within the app, right before it is sent to Bugsnag.
    """
    # adding user info and metadata to every report:
    notification.user = {
        # in your app, you can pull these details from session.
Пример #24
0
                    type(e), e.args, e))

    bugsnag.configure(
        api_key="e8f8e38698ff222ae1a9060aa443b75e",
        # Note: This is Jurek's private BugSnag account.
        # We might need to upgrade it later.
        project_root=current_dir,
        app_version=git_tag,
        ignore_classes=["django.http.Http404"],
        release_stage="development",
        # ! Note, asynchronous=False might be needed for this to work from inside Matlab. Enable otherwise to improve load performance.
        asynchronous=True)

    logger = logging.getLogger("basic")
    logger.setLevel(logging.INFO)
    logger.addHandler(BugsnagHandler())

    login = None
    hostname = None
    node = None
    if enable_hostname_reporting:
        login = os.getlogin()
        hostname = socket.gethostname()
        node = platform.node()

    bugsnag.notify(Exception("I have been imported"),
                   context="bugcatcher.start",
                   meta_data={
                       "startup_data": {
                           "login": login,
                           "hostname": hostname,
Пример #25
0
 def log_handler(self, extra_fields: List[str] = None) -> BugsnagHandler:
     return BugsnagHandler(client=self, extra_fields=extra_fields)
Пример #26
0
    def _setup_logging(self):
        """
        Sets up logging to log files, status and error properties, desktop notifications,
        the systemd journal if available, bugsnag if error reports are enabled, and to
        stdout if requested.
        """

        log_level = self._conf.get('app', 'log_level')
        mdbx_logger = logging.getLogger('maestral')
        mdbx_logger.setLevel(logging.DEBUG)

        log_fmt_long = logging.Formatter(
            fmt='%(asctime)s %(name)s %(levelname)s: %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S')
        log_fmt_short = logging.Formatter(fmt='%(message)s')

        # log to file
        rfh_log_file = get_log_path('maestral', self._config_name + '.log')
        self.log_handler_file = logging.handlers.RotatingFileHandler(
            rfh_log_file, maxBytes=10**7, backupCount=1)
        self.log_handler_file.setFormatter(log_fmt_long)
        self.log_handler_file.setLevel(log_level)
        mdbx_logger.addHandler(self.log_handler_file)

        # log to journal when launched from systemd
        if INVOCATION_ID and journal:
            self.log_handler_journal = journal.JournalHandler()
            self.log_handler_journal.setFormatter(log_fmt_short)
            self.log_handler_journal.setLevel(log_level)
            mdbx_logger.addHandler(self.log_handler_journal)
        else:
            self.log_handler_journal = None

        # send systemd notifications when started as 'notify' daemon
        if NOTIFY_SOCKET:
            self.log_handler_sd = SdNotificationHandler()
            self.log_handler_sd.setFormatter(log_fmt_short)
            self.log_handler_sd.setLevel(logging.INFO)
            mdbx_logger.addHandler(self.log_handler_sd)
        else:
            self.log_handler_sd = None

        # log to stdout (disabled by default)
        level = log_level if self._log_to_stdout else 100
        self.log_handler_stream = logging.StreamHandler(sys.stdout)
        self.log_handler_stream.setFormatter(log_fmt_long)
        self.log_handler_stream.setLevel(level)
        mdbx_logger.addHandler(self.log_handler_stream)

        # log to cached handlers for GUI and CLI
        self._log_handler_info_cache = CachedHandler(maxlen=1)
        self._log_handler_info_cache.setFormatter(log_fmt_short)
        self._log_handler_info_cache.setLevel(logging.INFO)
        mdbx_logger.addHandler(self._log_handler_info_cache)

        self._log_handler_error_cache = CachedHandler()
        self._log_handler_error_cache.setFormatter(log_fmt_short)
        self._log_handler_error_cache.setLevel(logging.ERROR)
        mdbx_logger.addHandler(self._log_handler_error_cache)

        # log to desktop notifications
        # 'file changed' events will be collated and sent as desktop
        # notifications by the monitor directly, we don't handle them here
        self.desktop_notifier = MaestralDesktopNotifier.for_config(
            self.config_name)
        self.desktop_notifier.setLevel(logging.WARNING)
        mdbx_logger.addHandler(self.desktop_notifier)

        # log to bugsnag (disabled by default)
        self._log_handler_bugsnag = BugsnagHandler()
        self._log_handler_bugsnag.setLevel(100)
        mdbx_logger.addHandler(self._log_handler_bugsnag)

        self.analytics = self._conf.get('app', 'analytics')
Пример #27
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))
Пример #28
0
 def log_handler(self):
     return BugsnagHandler(client=self)