Skip to content

[18.0][FIX] sentry_client: one event per error, no DSN secret, group tags opt-in (preview) - #17

Closed
dnplkndll wants to merge 2 commits into
18.0-add-sentry_clientfrom
18.0-sentry-isik
Closed

[18.0][FIX] sentry_client: one event per error, no DSN secret, group tags opt-in (preview)#17
dnplkndll wants to merge 2 commits into
18.0-add-sentry_clientfrom
18.0-sentry-isik

Conversation

@dnplkndll

@dnplkndll dnplkndll commented Sep 8, 2026

Copy link
Copy Markdown

SUPERSEDED 2026-09-08 — an equivalent rework landed directly on the upstream PR branch (OCA#3627 head 7c5d4f97, 19.0 port OCA#3622 head 68b40497), CI green on both. Kept open only as the reference for the parts upstream did not take: replay flush on server-side errors, the settings-form DSN-secret constraint, the informative odoo.rpc breadcrumb message, the 18.0 help-text fix. Close once those are decided.

Preview of the rework for isikerkan's review comment on OCA#3627. Not for merge here — once approved, the [FIX] commit is folded into the [ADD] commit and force-pushed to 18.0-add-sentry_client (the upstream PR branch), which is untouched by this PR. Based on that branch so the diff is the rework only.

What changed

  • Server-side errors are not captured from the browser. RPCError / ConnectionLostError / ConnectionAbortedError / RequestEntityTooLargeError get an odoo.rpc breadcrumb and a replay flush (Tier 2) instead of an event. New opt-in sentry_client.capture_rpc_errors for installs without the server-side sentry module.
  • One event per crash on the backend. The error_handlers registry entry (now sequence: 1) is the only capture path; Sentry's GlobalHandlers and BrowserApiErrors integrations are filtered out of the defaults when it is present. The beforeSend marker dedupe is deleted. Frontend pages (no error service) keep the SDK defaults.
  • DSN secret never served. _public_dsn() strips :<secret> from either source; the settings constraint refuses a browser DSN with one.
  • odoo.groups tag gone. Opt-in sentry_client.send_user_groups sends odoo.category as a tag and the group list as an odoo context.
  • Roadmap: OpenTelemetry entry replaced (trace propagation already works); Loader Script noted as a follow-up candidate. Settings help texts no longer mention the 19.0-only [sentry] section.

Verification

Stock odoo:18.0, fresh DB, -i sentry_client --test-tags /sentry_client: 36 tests, 0 failed, 0 errors (34 existing + _public_dsn, secret-stripping, constraint, groups default/opt-in, capture_rpc_errors flag). Pre-commit green.

Browser walk against a local envelope sink counting what the SDK actually sends, baseline (bbf5f102) vs this branch, same DB config (Tier 0 + Tier 2 on-error replay, groups opt-in on):

Scenario Baseline events Fixed events Notes (fixed)
Backend RPC error (unknown method) 1 (UncaughtPromiseError > RPC_ERROR) 0 odoo.rpc breadcrumb on the next event; replay uploaded
Sync throw in a timer 2 (BrowserApiErrors + UncaughtClientError) 1 (UncaughtClientError, owl: true)
Unhandled rejection 1 1
OWL setup() throw 1 1
Login page (frontend bundle): sync throw / rejection 1 / 1 SDK defaults kept

Tags on the fixed build: no odoo.groups; odoo.category (≤200 chars) + contexts.odoo.groups.

Gotcha worth knowing for anyone re-running this: Odoo serves the asset bundle under the same URL hash after a JS-only change, so the browser reuses its cached copy — hard-reload (⌘⇧R) or the old integrations stay live.

AI-assisted (Claude Code); every change reviewed, tested, and owned by the author.

…nfig

Backport of the 19.0 module (OCA#3622) to 18.0. Identical
feature set; only the API surfaces that changed between series are
adapted:

- `user.all_group_ids` (19.0) → `user.groups_id` (18.0). 19.0 split the
  groups field into a stored direct collection plus a computed
  transitive closure; on 18.0 `groups_id` already returns the full set.
- `group.privilege_id.category_id` (19.0) → `group.category_id` (18.0).
  19.0 introduced the privilege layer between groups and categories;
  on 18.0 groups carry the category directly.
- Config-file fallback reads the top-level `sentry_*` options from
  odoo.conf's `[options]` section — the layout the server-side `sentry`
  module actually uses on 18.0 (the dedicated `[sentry]` section only
  exists from 19.0).
- Manifest version `18.0.1.0.0`.

Everything else — Connection UI block (Browser DSN / Environment /
Release) with odoo.conf fallback, four tier toggles with sample-rate
knobs, vendored Sentry SDK under `static/lib`, OWL ErrorBoundary
capturing the wrapping error and dedup-marking it, per-tab UUID +
`workflow_id` + `surface` tags, per-user replay opt-out, and the public
`/sentry_client/config.json` endpoint — ports verbatim.

The OWL `error_handlers` registry, settings `<block>`/`<setting>`
pattern, and asset bundle keys are identical between 18.0 and 19.0.

The systray feedback launcher is an `o_nav_entry` button with
`fa-bullhorn` (Sentry's own feedback iconography) — deliberately not
`fa-bug`, which is the debug-mode systray icon beside it.

Assisted-by: Claude Fable 5
Assisted-by: Claude Opus 5
…pt-in

Addresses the findings from the shared-project test drive on OCA#3627:

- Server-side exceptions (RPCError, ConnectionLost/Aborted,
  RequestEntityTooLarge) are no longer captured from the browser: the
  server-side `sentry` module already reports them with a Python
  traceback. The handler leaves an `odoo.rpc` breadcrumb and flushes the
  buffered session replay instead. `sentry_client.capture_rpc_errors`
  restores the old behaviour for installs without the server module.
- On the backend the `error_handlers` registry entry is the single
  capture path: Sentry's `GlobalHandlers` and `BrowserApiErrors`
  integrations are filtered out of the defaults there, so a sync throw
  or an OWL crash produces one event instead of two. The marker-based
  `beforeSend` dedupe is gone with it. Frontend pages keep the defaults.
- `/sentry_client/config.json` strips the legacy `:<secret>` component
  from whichever DSN it serves; the settings constraint refuses a browser
  DSN carrying one.
- `odoo.groups` is no longer sent: it exceeded Sentry's 200-char tag
  limit for an administrator and is personal data. Opt-in
  `sentry_client.send_user_groups` sends the app categories as the
  `odoo.category` tag and the group names as an `odoo` event context.
- ROADMAP: browser/server trace correlation already works through the
  propagated `sentry-trace` headers; the OpenTelemetry entry was wrong.

Assisted-by: Claude Fable 5
@dnplkndll
dnplkndll force-pushed the 18.0-add-sentry_client branch 4 times, most recently from 7c5d4f9 to bebad7d Compare September 9, 2026 00:24
@dnplkndll dnplkndll closed this Sep 9, 2026
@dnplkndll
dnplkndll deleted the 18.0-sentry-isik branch September 9, 2026 00:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant