crashes: Replace user info with generic Sentry tags (#63344)
The crash handler models the crashing user as a fixed `UserInfo` struct
of `metrics_id` and `is_staff`. That is a reasonable fit for Zed and a
poor extension point in general: reporting any further piece of session
state with a crash means changing this crate, and every embedder along
with it.
The limitation has already produced a workaround in another consumer of
this crate. Wanting one field that `UserInfo` has no room for is enough
to push an embedder off the IPC channel entirely, onto persisting that
state beside the minidump and correlating it back at upload time. That
needs an atomic write, a retention window for records whose minidump
never uploads, and a cross-check so a stale record cannot be attributed
to the wrong crash — none of which the existing socket would have
required.
This replaces the `UserInfo` message with a generic `SetTags` message
carrying one or more updates. Each key is the Sentry submission field
the value is uploaded under, so an application can attach its own
session state and reach any part of Sentry's event schema without this
crate modelling what it means. Updates merge by key, and a `None` value
removes one, which is how an application withdraws state from crashes it
has not produced yet. A batch is applied while holding the tag-map lock
once, so a crash cannot observe part of one logical state change.
`set_user_info` keeps its signature and is now shorthand for setting the
two identity tags in one batch, so Zed's call site is unchanged.
`upload_minidump` loses its two bespoke user blocks in favour of
forwarding the map, and keeps its installation-id fallback by checking
whether the session ever reported a user.
Two consequences worth flagging for review. The first is that this crate
now knows it reports to Sentry, where previously it emitted neutral data
that `reliability.rs` translated. I think that is honest rather than
regrettable — its consumers upload to Sentry, and pretending otherwise
is what gave `UserInfo` a shape that fits only one of them. The
alternative considered was a well-known-key mapping table in the
uploader, which keeps the crate agnostic at the cost of a translation
layer that can silently file a value under the wrong namespace.
The second is a one-time compatibility loss. A crash is uploaded by the
build that starts after it, so an upgrade always reads crash data
written by the previous build. Crashes pending across this change carry
`user_info` and no `tags`, and will upload without user attribution.
They still parse and still upload; only the identity is dropped, for one
release. A test covers that.
Testing:
- New unit test for batch, merge, and removal semantics, driven through
`on_message` so it exercises the real wire format.
- New unit test that crash data written before `tags` existed still
deserializes.
- `cargo test -p crashes`, `./script/clippy -p crashes -p zed`, `cargo
check -p zed -p remote_server`, `cargo fmt --check`.
Release Notes:
- N/A
---------
Co-authored-by: morgankrey <morgan@zed.dev>
81df6f4af0Conrad Irwin committed on 8/31/2026, 3:29:14 PM· committed by GitHubparentff020dd