# Add a GPUI-owned hang monitor and make hang_telemetry a consumer \(\#64944\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/0f9c923e674e13e2891aaf31b33bbbc43d08b699)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: 0f9c923e674e13e2891aaf31b33bbbc43d08b699

Requested commit: 0f9c923e674e13e2891aaf31b33bbbc43d08b699

Commit: 0f9c923e674e13e2891aaf31b33bbbc43d08b699

Tree: b6c9ec8bd4381c6a4ea558a2b6c4a343339e1e32

Author: Anthony Eid

Committer: GitHub

## Message

```
Add a GPUI-owned hang monitor and make hang_telemetry a consumer (#64944)

## Summary

Zed and Delta each run their own hang-detection thread, thresholds,
batching and "Hang Incidents" wire schema; Delta's copy predates the
`hang_telemetry` extraction (#64874). This PR is the first step toward
one shared system that any GPUI app can use, and the place the upcoming
watchdog and stall classification will land once.

- **gpui:** adds `App::start_hang_monitor(HangMonitorConfig, on_poll)`.
GPUI spawns and owns a thread that polls the app's `HangDetector` every
`config.interval` and calls `on_poll` with a `HangMonitorPoll`
(incidents, first-present time, and whether it was an `Interval` or
`Flush` poll). When the app shuts down, GPUI requests a final `Flush`
poll without blocking and awaits it alongside the quit handlers, within
`SHUTDOWN_TIMEOUT`. Starting the monitor twice returns
`HangMonitorError::AlreadyStarted` (and debug-asserts); a thread spawn
failure returns `HangMonitorError::Spawn`. Not available on wasm.
- **`hang_telemetry`:** now a pure consumer of that API.
`HangTelemetry::new(startup, send_event).start(cx)` batches incidents
from polls and sends a batch every 30 minutes (including empty batches)
and on the shutdown flush. `with_incident_observer` receives each poll's
serialized incidents, for Delta's feedback-report hang list. The crate
owns no threads or quit handlers. Thresholds, the reporter and the wire
schema are unchanged.
- **Zed:** hang telemetry is `HangTelemetry::new(..).start(cx)` plus an
`on_app_quit` that flushes the telemetry queue. The legacy log and
task-trace loop keeps its own thread, renamed `HangLogging`. The unused
`spin` dependency is removed.

Behavior is unchanged except that the journal is first polled 1 s after
startup rather than 1.2 s (the 200 ms delay remains on the legacy log
loop it was written for).

Follow-ups: migrate Delta onto `hang_telemetry`; add the watchdog
(freeze detection, CPU-time stall classification) to the GPUI hang
monitor; share crash-report uploading in a separate PR.

## Testing

- New tests: `hang_monitor_polls_on_its_interval_and_on_flush`,
`app_flushes_its_hang_monitor_on_shutdown`,
`starting_the_hang_monitor_twice_is_rejected` (also run in release).
- `cargo test -p gpui --features profiler --lib -- profiler::` (58
passed), `cargo test -p hang_telemetry` (4 passed), `cargo check -p
zed`, wasm32 check of gpui, and `./script/clippy -p gpui -p
hang_telemetry -p zed` are clean.

Release Notes:

- [GPUI] Added `App::start_hang_monitor`, which polls the hang detector
on a GPUI-owned thread so hang detection keeps running while the
foreground is stalled, with a final flush on shutdown

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Eric Holk <eric@zed.dev>
```

## Parents

- [017f9b89aa26bfcb015b3f05c3f2dff64704338d](https://git.cafe/gitcafe/zed/commit/017f9b89aa26bfcb015b3f05c3f2dff64704338d?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/0f9c923e674e13e2891aaf31b33bbbc43d08b699?format=markdown)
