Ejemplo n.º 1
0
 def sentry_logger(sender, logger, loglevel, logfile, format,
                   colorize, **kw):
     filter_ = CeleryFilter()
     handler = SentryHandler(client)
     handler.setLevel(loglevel)
     handler.addFilter(filter_)
     logger.addHandler(handler)
Ejemplo n.º 2
0
 def sentry_logger(sender, logger, loglevel, logfile, format, colorize,
                   **kw):
     filter_ = CeleryFilter()
     handler = SentryHandler(client)
     handler.setLevel(loglevel)
     handler.addFilter(filter_)
     logger.addHandler(handler)
Ejemplo n.º 3
0
    def process_logger_event(sender, logger, loglevel, logfile, format, colorize, **kw):
        import logging

        logger = logging.getLogger()
        handler = SentryHandler(client)
        if handler.__class__ in list(map(type, logger.handlers)):
            return False
        handler.setLevel(logging.ERROR)
        handler.addFilter(CeleryFilter())
        logger.addHandler(handler)
Ejemplo n.º 4
0
 def process_logger_event(sender, logger, loglevel, logfile, format,
                          colorize, **kw):
     import logging
     logger = logging.getLogger()
     handler = SentryHandler(client)
     if handler.__class__ in map(type, logger.handlers):
         return False
     handler.setLevel(logging.ERROR)
     handler.addFilter(CeleryFilter())
     logger.addHandler(handler)
Ejemplo n.º 5
0
def init_sentry(app):
    sentry = IndicoSentry(wrap_wsgi=False, register_signal=True, logging=False)
    sentry.init_app(app)
    # setup logging manually and exclude uncaught indico exceptions.
    # these are logged manually in the flask error handler logic so
    # we get the X-Sentry-ID header which is not populated in the
    # logging handlers
    handler = SentryHandler(sentry.client, level=getattr(logging, config.SENTRY_LOGGING_LEVEL))
    handler.addFilter(BlacklistFilter({'indico.flask', 'celery.redirected'}))
    setup_logging(handler)
    # connect to the celery logger
    register_logger_signal(sentry.client)
    register_signal(sentry.client)
Ejemplo n.º 6
0
def init_sentry(app):
    sentry = IndicoSentry(wrap_wsgi=False, register_signal=True, logging=False)
    sentry.init_app(app)
    # setup logging manually and exclude uncaught indico exceptions.
    # these are logged manually in the flask error handler logic so
    # we get the X-Sentry-ID header which is not populated in the
    # logging handlers
    handler = SentryHandler(sentry.client, level=getattr(logging, config.SENTRY_LOGGING_LEVEL))
    handler.addFilter(BlacklistFilter({'indico.flask', 'celery.redirected'}))
    setup_logging(handler)
    # connect to the celery logger
    register_logger_signal(sentry.client)
    register_signal(sentry.client)
Ejemplo n.º 7
0
def register_logger_signal(client, logger=None, loglevel=logging.ERROR):
    filter_ = CeleryFilter()
    handler = SentryHandler(client)
    handler.setLevel(loglevel)
    handler.addFilter(filter_)

    def process_logger_event(sender, logger, loglevel, logfile, format,
                             colorize, **kw):
        for h in logger.handlers:
            if type(h) == SentryHandler:
                h.addFilter(filter_)
                return False

        logger.addHandler(handler)

    after_setup_logger.connect(process_logger_event, weak=False)
Ejemplo n.º 8
0
def register_logger_signal(client, logger=None, loglevel=logging.ERROR):
    filter_ = CeleryFilter()

    handler = SentryHandler(client)
    handler.setLevel(loglevel)
    handler.addFilter(filter_)

    def process_logger_event(sender, logger, loglevel, logfile, format,
                             colorize, **kw):
        # Attempt to find an existing SentryHandler, and if it exists ensure
        # that the CeleryFilter is installed.
        # If one is found, we do not attempt to install another one.
        for h in logger.handlers:
            if type(h) == SentryHandler:
                h.addFilter(filter_)
                return False

        logger.addHandler(handler)

    after_setup_logger.connect(process_logger_event, weak=False)
Ejemplo n.º 9
0
    async def start(self):
        self.client = Client(str(self.sentry_dsn),
                             transport=QueuedKeepaliveAioHttpTransport,
                             **self.client_options)

        # Initialize Transport object
        self.client.remote.get_transport()

        self.sentry_dsn = yarl.URL(
            self.sentry_dsn).with_password('').with_user('')

        log.info('Starting Raven for %r', self.sentry_dsn)

        handler = SentryHandler(client=self.client, level=self.min_level)

        # Add filters
        for fltr in self.filters:
            handler.addFilter(fltr)

        logging.getLogger().handlers.append(handler)
Ejemplo n.º 10
0
def start_logging():
    observer = log.PythonLoggingObserver()
    observer.start()

    for logtype, config in LOGGING.iteritems():
        if logtype == "raven":
            from raven.handlers.logging import SentryHandler
            lvl = getattr(logging, config.get('level', 'info').upper())
            handler = SentryHandler(config["dsn"])
            handler.setLevel(lvl)
            # don't try to log sentry errors with sentry
            handler.addFilter(InverseFilter('sentry'))
            logging.getLogger().addHandler(handler)
            print "Starting sentry logging [%s] with destination %s"% (
                config.get('level', 'info').upper(), config["dsn"])
        elif logtype == 'console':
            console = logging.StreamHandler()
            lvl = getattr(logging, config.get('level', 'info').upper())
            console.setLevel(lvl)
            formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
            console.setFormatter(formatter)
            logging.getLogger().addHandler(console)
            print "Starting console logging [%s]" % config.get('level', 'info').upper()
Ejemplo n.º 11
0
def setup_handlers():
    """
    sets up the sentry handler
    """
    if not __opts__.get("sentry_handler"):
        log.debug("'sentry_handler' config is empty or not defined")
        return False

    # Regenerating dunders can be expensive, so only do it if the user enables
    # `sentry_handler` as checked above
    __grains__ = salt.loader.grains(__opts__)
    __salt__ = salt.loader.minion_mods(__opts__)

    options = {}
    dsn = get_config_value("dsn")
    if dsn is not None:
        try:
            # support raven ver 5.5.0
            from raven.transport import TransportRegistry, default_transports
            from raven.utils.urlparse import urlparse

            transport_registry = TransportRegistry(default_transports)
            url = urlparse(dsn)
            if not transport_registry.supported_scheme(url.scheme):
                raise ValueError("Unsupported Sentry DSN scheme: {}".format(
                    url.scheme))
        except ValueError as exc:
            log.info(
                "Raven failed to parse the configuration provided DSN: %s",
                exc)

    if not dsn:
        for key in ("project", "servers", "public_key", "secret_key"):
            config_value = get_config_value(key)
            if config_value is None and key not in options:
                log.debug(
                    "The required 'sentry_handler' configuration key, "
                    "'%s', is not properly configured. Not configuring "
                    "the sentry logging handler.",
                    key,
                )
                return
            elif config_value is None:
                continue
            options[key] = config_value

    # site: An optional, arbitrary string to identify this client installation.
    options.update({
        # site: An optional, arbitrary string to identify this client
        # installation
        "site": get_config_value("site"),
        # name: This will override the server_name value for this installation.
        # Defaults to socket.gethostname()
        "name": get_config_value("name"),
        # exclude_paths: Extending this allow you to ignore module prefixes
        # when sentry attempts to discover which function an error comes from
        "exclude_paths": get_config_value("exclude_paths", ()),
        # include_paths: For example, in Django this defaults to your list of
        # INSTALLED_APPS, and is used for drilling down where an exception is
        # located
        "include_paths": get_config_value("include_paths", ()),
        # list_max_length: The maximum number of items a list-like container
        # should store.
        "list_max_length": get_config_value("list_max_length"),
        # string_max_length: The maximum characters of a string that should be
        # stored.
        "string_max_length": get_config_value("string_max_length"),
        # auto_log_stacks: Should Raven automatically log frame stacks
        # (including locals) all calls as it would for exceptions.
        "auto_log_stacks": get_config_value("auto_log_stacks"),
        # timeout: If supported, the timeout value for sending messages to
        # remote.
        "timeout": get_config_value("timeout", 1),
        # processors: A list of processors to apply to events before sending
        # them to the Sentry server. Useful for sending additional global state
        # data or sanitizing data that you want to keep off of the server.
        "processors": get_config_value("processors"),
        # dsn: Ensure the DSN is passed into the client
        "dsn": dsn,
    })

    client = raven.Client(**options)
    context = get_config_value("context")
    context_dict = {}
    if context is not None:
        for tag in context:
            try:
                tag_value = __grains__[tag]
            except KeyError:
                log.debug("Sentry tag '%s' not found in grains.", tag)
                continue
            if tag_value:
                context_dict[tag] = tag_value
        if context_dict:
            client.context.merge({"tags": context_dict})
    try:
        handler = SentryHandler(client)

        exclude_patterns = get_config_value("exclude_patterns", None)
        if exclude_patterns:
            filter_regexes = [
                re.compile(pattern) for pattern in exclude_patterns
            ]

            class FilterExcludedMessages:
                @staticmethod
                def filter(record):
                    m = record.getMessage()
                    return not any(regex.search(m) for regex in filter_regexes)

            handler.addFilter(FilterExcludedMessages())

        handler.setLevel(LOG_LEVELS[get_config_value("log_level", "error")])
        return handler
    except ValueError as exc:
        log.debug("Failed to setup the sentry logging handler", exc_info=True)
Ejemplo n.º 12
0
def setup_handlers():
    '''
    sets up the sentry handler
    '''
    __grains__ = salt.loader.grains(__opts__)
    __salt__ = salt.loader.minion_mods(__opts__)
    if 'sentry_handler' not in __opts__:
        log.debug('No \'sentry_handler\' key was found in the configuration')
        return False
    options = {}
    dsn = get_config_value('dsn')
    if dsn is not None:
        try:
            # support raven ver 5.5.0
            from raven.transport import TransportRegistry, default_transports
            from raven.utils.urlparse import urlparse
            transport_registry = TransportRegistry(default_transports)
            url = urlparse(dsn)
            if not transport_registry.supported_scheme(url.scheme):
                raise ValueError('Unsupported Sentry DSN scheme: {0}'.format(
                    url.scheme))
        except ValueError as exc:
            log.info(
                'Raven failed to parse the configuration provided DSN: %s',
                exc)

    if not dsn:
        for key in ('project', 'servers', 'public_key', 'secret_key'):
            config_value = get_config_value(key)
            if config_value is None and key not in options:
                log.debug(
                    'The required \'sentry_handler\' configuration key, '
                    '\'%s\', is not properly configured. Not configuring '
                    'the sentry logging handler.', key)
                return
            elif config_value is None:
                continue
            options[key] = config_value

    # site: An optional, arbitrary string to identify this client installation.
    options.update({
        # site: An optional, arbitrary string to identify this client
        # installation
        'site': get_config_value('site'),

        # name: This will override the server_name value for this installation.
        # Defaults to socket.gethostname()
        'name': get_config_value('name'),

        # exclude_paths: Extending this allow you to ignore module prefixes
        # when sentry attempts to discover which function an error comes from
        'exclude_paths': get_config_value('exclude_paths', ()),

        # include_paths: For example, in Django this defaults to your list of
        # INSTALLED_APPS, and is used for drilling down where an exception is
        # located
        'include_paths': get_config_value('include_paths', ()),

        # list_max_length: The maximum number of items a list-like container
        # should store.
        'list_max_length': get_config_value('list_max_length'),

        # string_max_length: The maximum characters of a string that should be
        # stored.
        'string_max_length': get_config_value('string_max_length'),

        # auto_log_stacks: Should Raven automatically log frame stacks
        # (including locals) all calls as it would for exceptions.
        'auto_log_stacks': get_config_value('auto_log_stacks'),

        # timeout: If supported, the timeout value for sending messages to
        # remote.
        'timeout': get_config_value('timeout', 1),

        # processors: A list of processors to apply to events before sending
        # them to the Sentry server. Useful for sending additional global state
        # data or sanitizing data that you want to keep off of the server.
        'processors': get_config_value('processors'),

        # dsn: Ensure the DSN is passed into the client
        'dsn': dsn
    })

    client = raven.Client(**options)
    context = get_config_value('context')
    context_dict = {}
    if context is not None:
        for tag in context:
            try:
                tag_value = __grains__[tag]
            except KeyError:
                log.debug('Sentry tag \'%s\' not found in grains.', tag)
                continue
            if len(tag_value) > 0:
                context_dict[tag] = tag_value
        if len(context_dict) > 0:
            client.context.merge({'tags': context_dict})
    try:
        handler = SentryHandler(client)

        exclude_patterns = get_config_value('exclude_patterns', None)
        if exclude_patterns:
            filter_regexes = [
                re.compile(pattern) for pattern in exclude_patterns
            ]

            class FilterExcludedMessages(object):
                @staticmethod
                def filter(record):
                    m = record.getMessage()
                    return not any(regex.search(m) for regex in filter_regexes)

            handler.addFilter(FilterExcludedMessages())

        handler.setLevel(LOG_LEVELS[get_config_value('log_level', 'error')])
        return handler
    except ValueError as exc:
        log.debug('Failed to setup the sentry logging handler', exc_info=True)