You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
feat: add config.hub_isolation_level for fiber-safe hub storage (Falcon/async) (#3018)
* feat: add config.isolation_level for fiber-safe hub storage
The current hub is stored in thread-local storage. On a fiber-based
server (Falcon/async) many concurrent requests run as sibling fibers on
one thread, so they share a single hub. When a request holds a scope
across a reactor yield (streaming, IO), a concurrent request's with_scope
mutates the same scope stack and scope/transaction/breadcrumbs/user leak
between requests -- reproduced as 5/6 events attributed to the wrong user,
including their email (cross-user PII bleed).
Add an opt-in config.isolation_level (:thread default, :fiber) that routes
the current hub through Sentry::HubStorage. :fiber uses Ruby 3.2+ Fiber
Storage (Fiber[]), which gives per-request isolation AND child-fiber
inheritance, so it fixes Falcon without re-introducing the graphql-ruby
context loss that #1374/#1380 addressed (old fiber-local vars did not
inherit; Fiber Storage does). Requesting :fiber on Ruby < 3.2 warns and
falls back to :thread. Default :thread is byte-for-byte the previous
behaviour. Mirrors Rails' config.active_support.isolation_level.
Refs #1495.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(rails): route ActiveJob hub save/restore through HubStorage
The ActiveJob integration saved and restored the surrounding hub with
Thread.current.thread_variable_get/set(Sentry::THREAD_LOCAL) directly,
which is wrong under config.isolation_level = :fiber (it would read/write
thread storage while the active hub lives in fiber storage). Route both
sites through Sentry::HubStorage so the save/restore follows the
configured isolation level. Behaviour is byte-for-byte unchanged under
the default :thread level.
Verified with a real ActiveJob perform_now: under :thread the outer hub
is restored and the job's user does not leak; under :fiber, concurrent
jobs run as sibling fibers each keep their own user.
Refs #1495.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: sync HubStorage on post-init isolation_level change; stabilize specs
Two follow-ups from review:
- Configuration#isolation_level= now applies the level to HubStorage when
the SDK is already initialized, so changing Sentry.configuration.isolation_level
after Sentry.init takes effect instead of leaving the SDK on the old backend.
The default is assigned to the ivar directly in initialize so a throwaway
Configuration.new cannot clobber the active isolation level (only Sentry.init
builds the live config).
- Make the :fiber isolation_level specs deterministic across Ruby versions by
stubbing fiber_storage_available?, and add an explicit downgrade-to-:thread
spec. Previously these asserted :fiber unconditionally and would fail on the
Ruby < 3.2 CI cells, where :fiber correctly falls back to :thread.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* simplify, remove HubStorage, add internal apis
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Neel Shah <neel.shah@sentry.io>
0 commit comments