PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/log_handlers/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/log_handlers/sentry_mod.py |
""" Sentry Logging Handler ====================== .. versionadded:: 0.17.0 This module provides a `Sentry`_ logging handler. Sentry is an open source error tracking platform that provides deep context about exceptions that happen in production. Details about stack traces along with the context variables available at the time of the exception are easily browsable and filterable from the online interface. For more details please see `Sentry`_. .. admonition:: Note The `Raven`_ library needs to be installed on the system for this logging handler to be available. Configuring the python `Sentry`_ client, `Raven`_, should be done under the ``sentry_handler`` configuration key. Additional `context` may be provided for corresponding grain item(s). At the bare minimum, you need to define the `DSN`_. As an example: .. code-block:: yaml sentry_handler: dsn: https://pub-key:secret-key@app.getsentry.com/app-id More complex configurations can be achieved, for example: .. code-block:: yaml sentry_handler: servers: - https://sentry.example.com - http://192.168.1.1 project: app-id public_key: deadbeefdeadbeefdeadbeefdeadbeef secret_key: beefdeadbeefdeadbeefdeadbeefdead context: - os - master - saltversion - cpuarch - ec2.tags.environment .. admonition:: Note The ``public_key`` and ``secret_key`` variables are not supported with Sentry > 3.0. The `DSN`_ key should be used instead. All the client configuration keys are supported, please see the `Raven client documentation`_. The default logging level for the sentry handler is ``ERROR``. If you wish to define a different one, define ``log_level`` under the ``sentry_handler`` configuration key: .. code-block:: yaml sentry_handler: dsn: https://pub-key:secret-key@app.getsentry.com/app-id log_level: warning The available log levels are those also available for the salt ``cli`` tools and configuration; ``salt --help`` should give you the required information. Threaded Transports ------------------- Raven's documents rightly suggest using its threaded transport for critical applications. However, don't forget that if you start having troubles with Salt after enabling the threaded transport, please try switching to a non-threaded transport to see if that fixes your problem. .. _`DSN`: https://raven.readthedocs.io/en/latest/config/index.html#the-sentry-dsn .. _`Sentry`: https://getsentry.com .. _`Raven`: https://raven.readthedocs.io .. _`Raven client documentation`: https://raven.readthedocs.io/en/latest/config/index.html#client-arguments """ import logging import re import salt.loader from salt._logging import LOG_LEVELS try: import raven from raven.handlers.logging import SentryHandler HAS_RAVEN = True except ImportError: HAS_RAVEN = False log = logging.getLogger(__name__) # Define the module's virtual name __virtualname__ = "sentry" def __virtual__(): load_err_msg = [] if not HAS_RAVEN: load_err_msg.append("Cannot find 'raven' python library") if not __opts__.get("sentry_handler"): load_err_msg.append("'sentry_handler' config is empty or not defined") if load_err_msg: return False, ", ".join(load_err_msg) return __virtualname__ 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(f"Unsupported Sentry DSN scheme: {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) def get_config_value(name, default=None): """ returns a configuration option for the sentry_handler """ return __opts__["sentry_handler"].get(name, default)