From e1ffc79018878b25819464b6037c48f20a3cd4bf Mon Sep 17 00:00:00 2001 From: MaX-Lo Date: Fri, 19 Dec 2025 14:52:42 +0100 Subject: [PATCH 1/2] [IMP] bump sentry_sdk version --- requirements.txt | 2 +- sentry/__manifest__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 2ffa3961279..8446c1e0da7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,4 @@ openupgradelib paramiko<4.0.0 pygount pysftp -sentry_sdk>=2.0.0,<=2.22.0 +sentry_sdk>=2.35.0 diff --git a/sentry/__manifest__.py b/sentry/__manifest__.py index 7f950bc3f0e..3236d73018d 100644 --- a/sentry/__manifest__.py +++ b/sentry/__manifest__.py @@ -17,7 +17,7 @@ "installable": True, "external_dependencies": { "python": [ - "sentry_sdk>=2.0.0,<=2.22.0", + "sentry_sdk>=2.35.0", ] }, "depends": [ From 3af8f521584784e4e98f4909119221996627b90b Mon Sep 17 00:00:00 2001 From: MaX-Lo Date: Fri, 19 Dec 2025 15:15:39 +0100 Subject: [PATCH 2/2] [IMP] sentry: adds an option to use sentry's structured log feature --- sentry/hooks.py | 3 +++ sentry/readme/CONFIGURE.md | 1 + sentry/static/description/index.html | 37 ++++++++++++---------------- sentry/tests/test_client.py | 37 ++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/sentry/hooks.py b/sentry/hooks.py index 6a6af920967..36db6897ed2 100644 --- a/sentry/hooks.py +++ b/sentry/hooks.py @@ -128,6 +128,9 @@ def initialize_sentry(config): # Remove logging_level, since in sentry_sdk is include in 'integrations' del options["logging_level"] + if config.get("sentry_enable_logs", False): + options["enable_logs"] = True + client = sentry_sdk.init(**options) sentry_sdk.set_tag("include_context", config.get("sentry_include_context", True)) diff --git a/sentry/readme/CONFIGURE.md b/sentry/readme/CONFIGURE.md index 92ee130add5..87608bbeb86 100644 --- a/sentry/readme/CONFIGURE.md +++ b/sentry/readme/CONFIGURE.md @@ -19,6 +19,7 @@ options: sentry_enabled = true sentry_logging_level = warn sentry_exclude_loggers = werkzeug + sentry_enable_logs = true sentry_ignore_exceptions = odoo.exceptions.AccessDenied, odoo.exceptions.AccessError,odoo.exceptions.MissingError, odoo.exceptions.RedirectWarning,odoo.exceptions.UserError, diff --git a/sentry/static/description/index.html b/sentry/static/description/index.html index 42117a52a2d..4d07541252d 100644 --- a/sentry/static/description/index.html +++ b/sentry/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Sentry -
+
+

Sentry

- - -Odoo Community Association - -
-

Sentry

-

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

This module allows painless Sentry integration with Odoo.

Table of contents

@@ -398,7 +393,7 @@

Sentry

-

Installation

+

Installation

The module can be installed just like any other Odoo module, by adding the module’s directory to Odoo addons_path. In order for the module to correctly wrap the Odoo WSGI application, it also needs to be loaded as @@ -412,7 +407,7 @@

Installation

-

Configuration

+

Configuration

The following additional configuration options can be added to your Odoo configuration file:

[TABLE]

@@ -423,7 +418,7 @@

Configuration

are: with_locals, max_breadcrumbs, release, environment, server_name, shutdown_timeout, in_app_include, in_app_exclude, default_integrations, dist, sample_rate, send_default_pii, http_proxy, https_proxy, request_bodies, debug, attach_stacktrace, ca_certs, propagate_traces, traces_sample_rate, auto_enabling_integrations.

-

Example Odoo configuration

+

Example Odoo configuration

Below is an example of Odoo configuration file with Odoo Sentry options:

@@ -432,6 +427,7 @@ 

Example Odoo configurationExample Odoo configuration

-

Usage

+

Usage

Once configured and installed, the module will report any logging event at and above the configured Sentry logging level, no additional actions are necessary.

Try me on Runbot

-

Known issues / Roadmap

+

Known issues / Roadmap

  • No database separation – This module functions by intercepting all Odoo logging records in a running Odoo process. This means that @@ -468,7 +464,7 @@

    Known issues / Roadmap

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -476,9 +472,9 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Mohammed Barsi
  • Versada
  • @@ -487,7 +483,7 @@

    Authors

-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -521,6 +517,5 @@

Maintainers

-
diff --git a/sentry/tests/test_client.py b/sentry/tests/test_client.py index e506582caad..643e227a94a 100644 --- a/sentry/tests/test_client.py +++ b/sentry/tests/test_client.py @@ -53,6 +53,23 @@ def has_event(self, event_level, event_msg): return event return False + def has_log_item(self, log_level: str, log_msg: str) -> bool: + for envelope in self.envelopes: + log_items = filter( + lambda envelope_item: envelope_item.data_category == "log_item", + envelope.items, + ) + payload_items = [] + for item in log_items: + payload_items.extend(item.payload.json["items"]) + if any( + (item["level"] == log_level and item["body"] == log_msg) + for item in payload_items + ): + return True + + return False + def flush(self, *args, **kwargs): pass @@ -123,6 +140,13 @@ def assertEventNotCaptured(self, client, event_level, event_msg): msg=f"Event: {event_msg} was captured", ) + def assertLogCaptured(self, client, log_level: str, log_msg: str): + client.flush() + self.assertTrue( + client.transport.has_log_item(log_level, log_msg), + msg=f"Log item: {log_msg} was not captured", + ) + def test_initialize_raven_sets_dsn(self): self.assertEqual(self.client.dsn, self.dsn) @@ -224,6 +248,19 @@ def test_exclude_logger(self): remove_handler_ignore(self.logger.name) self.assertEventNotCaptured(client, level, msg) + def test_enable_logs(self): + self.patch_config( + { + "sentry_enable_logs": True, + } + ) + client = initialize_sentry(config)._client + client.transport = InMemoryTransport({"dsn": self.dsn}) + level, msg = logging.WARNING, "Test log sending is enabled" + self.log(level, msg) + level = "warn" + self.assertLogCaptured(client, level, msg) + def test_invalid_logging_level(self): self.patch_config( {