Skip to repository content124 lines · 4.4 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T06:50:38.498Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
hang_detection.rs
1use std::sync::Arc;
2use std::thread;
3use std::time::Duration;
4
5use client::Client;
6use gpui::{AppContext, TasksIncluded, profiler};
7use parking_lot::Mutex;
8use ui::App;
9
10mod logging;
11mod task_traces;
12mod telemetry;
13
14gpui::actions!(
15 dev,
16 [
17 /// Causes a performance hang to test performance monitoring
18 HangAction,
19 /// Causes a performance hang to test performance monitoring
20 HangBackground,
21 /// Causes a performance hang to test performance monitoring
22 HangForeground,
23 ]
24);
25
26pub(crate) fn start(client: Arc<Client>, cx: &mut App) {
27 let hang_time = if cfg!(debug_assertions) {
28 if cfg!(windows) {
29 // yes windows debug builds are horribly slow
30 Duration::from_secs(30)
31 } else {
32 Duration::from_secs(5)
33 }
34 } else {
35 // will be lowered over time or turned into a setting
36 Duration::from_millis(100)
37 };
38
39 if cfg!(debug_assertions) {
40 log::warn!("debug build, only reporting hangs longer then {hang_time:?}");
41 }
42
43 start_hang_detection(hang_time, client, cx);
44
45 cx.on_action(move |_: &HangAction, _| {
46 log::warn!(
47 "Hanging the foreground for {hang_time:?} by blocking in an action. \
48 Omega will be unresponsive for that time. This should trigger a report in the log",
49 );
50 thread::sleep(hang_time + Duration::from_micros(1));
51 log::warn!("Hang ended");
52 });
53 cx.on_action(move |_: &HangBackground, cx| {
54 cx.background_spawn(async move {
55 log::warn!(
56 "Hanging one background executor for {hang_time:?}. \
57 This should trigger a report in the log",
58 );
59 thread::sleep(hang_time + Duration::from_micros(1));
60 log::warn!("Hang ended");
61 })
62 .detach();
63 });
64 cx.on_action(move |_: &HangForeground, cx| {
65 cx.spawn(async move |_| {
66 log::warn!(
67 "Hanging the foreground executor for {hang_time:?} seconds to test \
68 performance monitoring! Omega will be unresponsive for that time. \
69 This should trigger a report in the log"
70 );
71 thread::sleep(hang_time + Duration::from_micros(1));
72 log::warn!("Hang ended");
73 })
74 .detach();
75 });
76}
77
78fn start_hang_detection(report_longer_then: Duration, client: Arc<Client>, cx: &App) {
79 let foreground_thread = thread::current().id();
80 let monitor_interval = Duration::from_secs(1);
81 let telemetry = Arc::new(Mutex::new(telemetry::Reporter::new(foreground_thread)));
82 let mut log = logging::Reporter::new(monitor_interval, report_longer_then, foreground_thread);
83
84 let telemetry2 = Arc::clone(&telemetry);
85 cx.on_app_quit({
86 move |_| {
87 telemetry2.lock().send();
88 client.telemetry().flush_events()
89 }
90 })
91 .detach();
92
93 // an OS thread to insulate detection and reporting from hangs on the fore
94 // or background.
95 thread::Builder::new()
96 .name("HangDetection".to_string())
97 .spawn(move || {
98 // allow "bad" tasks during startup. Not because we should but since here
99 // they are not observed by the user and to lower on clutter from the reporter
100 thread::sleep(Duration::from_millis(200));
101 loop {
102 thread::sleep(monitor_interval);
103 // TODO(yara) the telemetry should not include still running tasks while the
104 // reports being logged should.
105 let task_stats = profiler::take_all_stats(TasksIncluded::CompletedAndRunning);
106 let action_stats = profiler::take_action_stats();
107
108 {
109 let mut telemetry = telemetry.lock();
110 telemetry.update(&task_stats, &action_stats);
111 telemetry.send_periodically();
112 }
113
114 let should_write_trace = log.check_and_report(&task_stats, &action_stats);
115 if should_write_trace {
116 if let Some(path) = task_traces::save_any(foreground_thread) {
117 log::info!("Task trace has been saved to: {}", path.display());
118 }
119 }
120 }
121 })
122 .expect("App can always spawn threads");
123}
124