Skip to content

[18.0][ADD] sentry_client: tiered browser SDK with vendoring, profiling, replay opt-out, OWL boundary#3627

Open
dnplkndll wants to merge 1 commit into
OCA:18.0from
ledoent:18.0-add-sentry_client
Open

[18.0][ADD] sentry_client: tiered browser SDK with vendoring, profiling, replay opt-out, OWL boundary#3627
dnplkndll wants to merge 1 commit into
OCA:18.0from
ledoent:18.0-add-sentry_client

Conversation

@dnplkndll
Copy link
Copy Markdown
Contributor

@dnplkndll dnplkndll commented May 25, 2026

New module: a browser-side companion to the OCA sentry Python module.
Loads the Sentry browser SDK into the Odoo web client and reports
uncaught JS errors, optional performance traces, session replays on
error, and a user-feedback widget — all toggleable per tier under
Settings → General Settings → Sentry Browser Monitoring.

Browser DSN, environment, and release are settable via the UI
(ir.config_parameter sentry_client.{browser_dsn,environment,release}).
Empty UI values fall back to the [sentry] section of odoo.conf so a
single-project deployment shared with the server-side sentry module
keeps working without UI clicks. Matches Sentry's recommended
one-project-per-platform setup when the values are split.

Lead PR for the module; 19.0 port at
#3622 (DRAFT,
[19.0][MIG] — cherry-pick of this commit plus three API adaptations).

Non-mechanical adaptations worth flagging

  • @web/core/error_handlers registry hook captures the OWL-wrapping
    error (error || originalException) rather than the inner one and
    marks it with __sentry_owl_captured__ so the global
    onunhandledrejection handler's beforeSend drops the duplicate.
    Result: one Sentry issue per OWL crash, tagged owl: true, with the
    component tree in extra.component_tree. Returns false so Odoo's
    own Oops! dialog still renders alongside.
  • Public /sentry_client/config.json endpoint is auth="public" on
    purpose — the loader runs on portal/login pages before auth. Only
    behaviour flags and the numeric uid leave the server; email and name
    are read client-side from window.odoo.session_info (already gated by
    the session cookie). DSN is a public DSN, safe to expose.
  • Per-user replay opt-out under My Profile → Preferences → Privacy.
    Even with Tier 2 enabled DB-wide, an opted-out user's Replay
    integration never registers, so no DOM observer runs for them.
  • Per-tab UUID + workflow tags. tab_id (sessionStorage-persisted
    UUID), workflow_id (<action_id>|<model>|<view_type>), and the
    surface tag ship on every event so downstream harvesting can split a
    user's parallel windows into distinct streams.
  • surface tag classifies the source of every browser event:
    backend (/odoo, /web), portal (/my), or frontend (public
    website). Lets Sentry queries filter cleanly when both browser and
    Python ship to the same project — environment distinguishes
    Python vs JS, surface distinguishes browser sub-streams.
  • Bundle selection. Sentry's CDN doesn't ship a
    bundle.tracing.feedback.min.js; the controller's _bundle_name
    helper falls back to bundle.tracing.replay.feedback.min.js for that
    combination — extra replay code is inert without the integration
    registered.
  • Vendored SDK under static/lib/sentry/<version>/ with a refresh
    script that SRI-verifies each bundle against Sentry's published
    hashes. Browser loads from the same origin as Odoo — air-gap safe.

Demo on the runboat preview

Installed against the PR preview build
with all four tiers enabled and a test DSN:

sentry_client.browser_dsn      = https://<key>@<host>/<project_id>
sentry_client.environment      = demo-18
sentry_client.enabled          = True
sentry_client.tier1_tracing_enabled    = True   # traces_sample_rate=1.0
sentry_client.tier2_replay_enabled     = True   # session=0.0, on-error=1.0
sentry_client.tier3_feedback_enabled   = True

Runtime config returned by the public endpoint:

{
  "enabled": true,
  "environment": "demo-18",
  "integrations": {"tracing": true, "replay": true, "feedback": true, "profiling": false, "logs": false},
  "traces_sample_rate": 1.0,
  "replay_session_sample_rate": 0.0,
  "replay_error_sample_rate": 1.0
}

Reviewers running the runboat preview themselves can reproduce by
configuring a DSN for their own project, then triggering a JS exception
in the browser console — events land within seconds tagged with
environment + surface for query separation:

Filter Result
environment:demo-18 surface:python-backend server-side Python events
environment:demo-18 surface:backend webclient JS errors
environment:demo-18 surface:portal /my portal JS errors
environment:demo-18 surface:frontend public-site JS errors

@dnplkndll dnplkndll marked this pull request as ready for review May 25, 2026 20:08
…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.
- Manifest version `18.0.1.0.0`.

Everything else — Connection UI block (Browser DSN / Environment /
Release) with `odoo.conf [sentry]` 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.
@dnplkndll dnplkndll force-pushed the 18.0-add-sentry_client branch from 91d7713 to 0d828a8 Compare May 25, 2026 20:18
@dnplkndll
Copy link
Copy Markdown
Contributor Author

dnplkndll commented May 25, 2026

@LoisRForgeFlow @victoralmau

I think you guys had some contributions on sentry. how does this look? I was actually going to look into if there might be some way to use the data on an instances use to build roles and skills for agents or just keeping process documentation up to date. I created a drop in seer app that runs the lower cost 3.5-flash to keep costs down on error fixes as well. need more use to verify.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants