From 28cf8a6c6a598f229ab3bb14365f84992cea43e5 Mon Sep 17 00:00:00 2001 From: tarteo Date: Tue, 29 Apr 2025 12:48:20 +0200 Subject: [PATCH] sentry: Add `sentry_ignore_regex` option --- sentry/README.rst | 4 ++ sentry/hooks.py | 75 +++++++++++++++++----------- sentry/readme/CONFIGURE.rst | 3 ++ sentry/readme/CONTRIBUTORS.rst | 1 + sentry/static/description/index.html | 6 +++ sentry/tests/test_client.py | 18 +++++++ 6 files changed, 79 insertions(+), 28 deletions(-) diff --git a/sentry/README.rst b/sentry/README.rst index fc7c2a894ef..2ebbd164ab1 100644 --- a/sentry/README.rst +++ b/sentry/README.rst @@ -98,6 +98,9 @@ configuration file: and will only be used to extract the Odoo Git commit, which will be sent to Sentry, to allow to distinguish between Odoo updates. Overridden by *sentry_release* + +``sentry_ignore_regex`` A regex pattern to filter / ignore logs. This is useful to ignore + specific log messages that are not relevant. ============================= ==================================================================== ========================================================== Other `client arguments @@ -186,6 +189,7 @@ Contributors * Florian Mounier * Jon Ashton * Mark Schuit +* Dennis Sluijk Other credits ~~~~~~~~~~~~~ diff --git a/sentry/hooks.py b/sentry/hooks.py index 2236977c358..a1cfd063b16 100644 --- a/sentry/hooks.py +++ b/sentry/hooks.py @@ -2,6 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import logging +import re import warnings from collections import abc @@ -32,39 +33,47 @@ ) # pragma: no cover -def before_send(event, hint): - """Prevent the capture of any exceptions in - the DEFAULT_IGNORED_EXCEPTIONS list - -- or -- - Add context to event if include_context is True - and sanitize sensitive data""" +def before_send_wrap(sentry_ignore_regex): + def before_send(event, hint): + """Prevent the capture of any exceptions in + the DEFAULT_IGNORED_EXCEPTIONS list + -- or -- + Add context to event if include_context is True + and sanitize sensitive data""" - exc_info = hint.get("exc_info") - if exc_info is None and "log_record" in hint: - # Odoo handles UserErrors by logging the raw exception rather - # than a message string in odoo/http.py - try: - module_name = hint["log_record"].msg.__module__ - class_name = hint["log_record"].msg.__class__.__name__ - qualified_name = module_name + "." + class_name - except AttributeError: - qualified_name = "not found" + exc_info = hint.get("exc_info") + if exc_info is None and "log_record" in hint: + # Odoo handles UserErrors by logging the raw exception rather + # than a message string in odoo/http.py + try: + module_name = hint["log_record"].msg.__module__ + class_name = hint["log_record"].msg.__class__.__name__ + qualified_name = module_name + "." + class_name + except AttributeError: + qualified_name = "not found" + + if qualified_name in const.DEFAULT_IGNORED_EXCEPTIONS: + return None - if qualified_name in const.DEFAULT_IGNORED_EXCEPTIONS: - return None + if sentry_ignore_regex is not None and type(hint["log_record"].msg) is str: + # Check if the message matches the regex + if sentry_ignore_regex.search(hint["log_record"].msg): + return None - if event.setdefault("tags", {})["include_context"]: - cxtest = get_extra_context(odoo.http.request) - info_request = ["tags", "user", "extra", "request"] + if event.setdefault("tags", {})["include_context"]: + cxtest = get_extra_context(odoo.http.request) + info_request = ["tags", "user", "extra", "request"] - for item in info_request: - info_item = event.setdefault(item, {}) - info_item.update(cxtest.setdefault(item, {})) + for item in info_request: + info_item = event.setdefault(item, {}) + info_item.update(cxtest.setdefault(item, {})) - raven_processor = SanitizeOdooCookiesProcessor() - raven_processor.process(event) + raven_processor = SanitizeOdooCookiesProcessor() + raven_processor.process(event) - return event + return event + + return before_send def get_odoo_commit(odoo_dir): @@ -97,6 +106,16 @@ def initialize_sentry(config): "Its not neccesary send it, will use `HttpTranport` by default.", DeprecationWarning, ) + sentry_ignore_regex = None + if regex_pattern := config.get("sentry_ignore_regex"): + try: + sentry_ignore_regex = re.compile(regex_pattern) + except re.error as e: + _logger.warning( + "Invalid regex pattern '%s' for 'sentry_ignore_regex': %s", + regex_pattern, + e, + ) options = {} for option in const.get_sentry_options(): value = config.get("sentry_%s" % option.key, option.default) @@ -118,7 +137,7 @@ def initialize_sentry(config): options["ignore_errors"] = options["ignore_exceptions"] del options["ignore_exceptions"] - options["before_send"] = before_send + options["before_send"] = before_send_wrap(sentry_ignore_regex) options["integrations"] = [ options["logging_level"], diff --git a/sentry/readme/CONFIGURE.rst b/sentry/readme/CONFIGURE.rst index 25de942df51..a7441f55d1d 100644 --- a/sentry/readme/CONFIGURE.rst +++ b/sentry/readme/CONFIGURE.rst @@ -43,6 +43,9 @@ configuration file: and will only be used to extract the Odoo Git commit, which will be sent to Sentry, to allow to distinguish between Odoo updates. Overridden by *sentry_release* + +``sentry_ignore_regex`` A regex pattern to filter / ignore logs. This is useful to ignore + specific log messages that are not relevant. ============================= ==================================================================== ========================================================== Other `client arguments diff --git a/sentry/readme/CONTRIBUTORS.rst b/sentry/readme/CONTRIBUTORS.rst index 8bd9e411f1f..18970f13dd2 100644 --- a/sentry/readme/CONTRIBUTORS.rst +++ b/sentry/readme/CONTRIBUTORS.rst @@ -5,3 +5,4 @@ * Florian Mounier * Jon Ashton * Mark Schuit +* Dennis Sluijk diff --git a/sentry/static/description/index.html b/sentry/static/description/index.html index 1d8f03a944b..ec2899864c6 100644 --- a/sentry/static/description/index.html +++ b/sentry/static/description/index.html @@ -480,6 +480,11 @@

Configuration

Overridden by sentry_release   +sentry_ignore_regex +A regex pattern to filter / ignore logs. This is useful to ignore +specific log messages that are not relevant. +  +

Other client arguments can be @@ -563,6 +568,7 @@

Contributors

  • Florian Mounier <florian.mounier@akretion.com>
  • Jon Ashton <jon@monkeyinferno.com>
  • Mark Schuit <mark@gig.solutions>
  • +
  • Dennis Sluijk <d.sluijk@onestein.nl>
  • diff --git a/sentry/tests/test_client.py b/sentry/tests/test_client.py index 9832c75ff34..2c43c6bee96 100644 --- a/sentry/tests/test_client.py +++ b/sentry/tests/test_client.py @@ -253,3 +253,21 @@ def test_config_release(self, get_odoo_commit): RELEASE, "Failed to use 'sentry_release' parameter appropriately", ) + + def test_ignore_regex(self): + level, msg = ( + logging.ERROR, + "ERROR: SerializationFailure('could not " + "serialize access due to concurrent update')", + ) + self.log(level, msg) + self.assertEventCaptured(self.client, "error", msg) + self.patch_config( + { + "sentry_ignore_regex": "SerializationFailure", + } + ) + client = initialize_sentry(config)._client + client.transport = InMemoryTransport({"dsn": self.dsn}) + self.log(level, msg) + self.assertEventNotCaptured(client, "error", msg)