From 0926db91115ddfa10535ae16b4c528d2a99247b4 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 20 Nov 2023 15:51:36 -0500 Subject: [PATCH 01/11] Add app events --- crates/client/src/telemetry.rs | 38 ++++++++++++++++++++++----------- crates/client2/src/telemetry.rs | 38 ++++++++++++++++++++++----------- crates/zed/src/main.rs | 23 ++++++++++++++++---- crates/zed2/src/main.rs | 20 +++++++++++++---- 4 files changed, 87 insertions(+), 32 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 8f7fbeb83d3e974aadcbc64dbee0f3d5482242cd..a3e7449cf8a4be5a25b4f7eaaa4f3d2379d70d68 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -109,6 +109,10 @@ pub enum ClickhouseEvent { virtual_memory_in_bytes: u64, milliseconds_since_first_event: i64, }, + App { + operation: &'static str, + milliseconds_since_first_event: i64, + }, } #[cfg(debug_assertions)] @@ -168,13 +172,8 @@ impl Telemetry { let mut state = self.state.lock(); state.installation_id = installation_id.map(|id| id.into()); state.session_id = Some(session_id.into()); - let has_clickhouse_events = !state.clickhouse_events_queue.is_empty(); drop(state); - if has_clickhouse_events { - self.flush_clickhouse_events(); - } - let this = self.clone(); cx.spawn(|mut cx| async move { // Avoiding calling `System::new_all()`, as there have been crashes related to it @@ -256,7 +255,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_copilot_event( @@ -273,7 +272,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_assistant_event( @@ -290,7 +289,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_call_event( @@ -307,7 +306,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_cpu_event( @@ -322,7 +321,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_memory_event( @@ -337,7 +336,21 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) + } + + // app_events are called at app open and app close, so flush is set to immediately send + pub fn report_app_event( + self: &Arc, + telemetry_settings: TelemetrySettings, + operation: &'static str, + ) { + let event = ClickhouseEvent::App { + operation, + milliseconds_since_first_event: self.milliseconds_since_first_event(), + }; + + self.report_clickhouse_event(event, telemetry_settings, true) } fn milliseconds_since_first_event(&self) -> i64 { @@ -358,6 +371,7 @@ impl Telemetry { self: &Arc, event: ClickhouseEvent, telemetry_settings: TelemetrySettings, + immediate_flush: bool, ) { if !telemetry_settings.metrics { return; @@ -370,7 +384,7 @@ impl Telemetry { .push(ClickhouseEventWrapper { signed_in, event }); if state.installation_id.is_some() { - if state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { + if immediate_flush || state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { drop(state); self.flush_clickhouse_events(); } else { diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index 9c88d1102c255d6892212e6e28d5346e5b55b3fd..9bd24293a0a71f0c74f4d46212b7e473e084bfa2 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -107,6 +107,10 @@ pub enum ClickhouseEvent { virtual_memory_in_bytes: u64, milliseconds_since_first_event: i64, }, + App { + operation: &'static str, + milliseconds_since_first_event: i64, + }, } #[cfg(debug_assertions)] @@ -163,13 +167,8 @@ impl Telemetry { let mut state = self.state.lock(); state.installation_id = installation_id.map(|id| id.into()); state.session_id = Some(session_id.into()); - let has_clickhouse_events = !state.clickhouse_events_queue.is_empty(); drop(state); - if has_clickhouse_events { - self.flush_clickhouse_events(); - } - let this = self.clone(); cx.spawn(|cx| async move { // Avoiding calling `System::new_all()`, as there have been crashes related to it @@ -257,7 +256,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_copilot_event( @@ -274,7 +273,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_assistant_event( @@ -291,7 +290,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_call_event( @@ -308,7 +307,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_cpu_event( @@ -323,7 +322,7 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_memory_event( @@ -338,7 +337,21 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings) + self.report_clickhouse_event(event, telemetry_settings, false) + } + + // app_events are called at app open and app close, so flush is set to immediately send + pub fn report_app_event( + self: &Arc, + telemetry_settings: TelemetrySettings, + operation: &'static str, + ) { + let event = ClickhouseEvent::App { + operation, + milliseconds_since_first_event: self.milliseconds_since_first_event(), + }; + + self.report_clickhouse_event(event, telemetry_settings, true) } fn milliseconds_since_first_event(&self) -> i64 { @@ -359,6 +372,7 @@ impl Telemetry { self: &Arc, event: ClickhouseEvent, telemetry_settings: TelemetrySettings, + immediate_flush: bool, ) { if !telemetry_settings.metrics { return; @@ -371,7 +385,7 @@ impl Telemetry { .push(ClickhouseEventWrapper { signed_in, event }); if state.installation_id.is_some() { - if state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { + if immediate_flush || state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { drop(state); self.flush_clickhouse_events(); } else { diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 5f2a7c525e0aea471583af9e361ad2063397d4fc..992a433a7492a825c511f731d7a51b46142412e6 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -65,7 +65,8 @@ fn main() { log::info!("========== starting zed =========="); let mut app = gpui::App::new(Assets).unwrap(); - let installation_id = app.background().block(installation_id()).ok(); + let (installation_id, existing_installation_id_found) = + app.background().block(installation_id()).ok().unzip(); let session_id = Uuid::new_v4().to_string(); init_panic_hook(&app, installation_id.clone(), session_id.clone()); @@ -166,6 +167,20 @@ fn main() { .detach(); client.telemetry().start(installation_id, session_id, cx); + // TODO: + // Cleanly identify open / first open + // What should we do if we fail when looking for installation_id? + // - set to true, false, or skip? + // Report closed + // Copy logic to zed2 + let telemetry_settings = *settings::get::(cx); + let event_operation = match existing_installation_id_found { + Some(true) => "open", + _ => "first open", + }; + client + .telemetry() + .report_app_event(telemetry_settings, event_operation); let app_state = Arc::new(AppState { languages, @@ -317,11 +332,11 @@ async fn authenticate(client: Arc, cx: &AsyncAppContext) -> Result<()> { Ok::<_, anyhow::Error>(()) } -async fn installation_id() -> Result { +async fn installation_id() -> Result<(String, bool)> { let legacy_key_name = "device_id"; if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(legacy_key_name) { - Ok(installation_id) + Ok((installation_id, true)) } else { let installation_id = Uuid::new_v4().to_string(); @@ -329,7 +344,7 @@ async fn installation_id() -> Result { .write_kvp(legacy_key_name.to_string(), installation_id.clone()) .await?; - Ok(installation_id) + Ok((installation_id, false)) } } diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 0532d62c386a57daf4ab23a674c3fd3780a0a921..aacb3ed83cfab3580b1592c2334e741bd1bec773 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -71,7 +71,11 @@ fn main() { log::info!("========== starting zed =========="); let app = App::production(Arc::new(Assets)); - let installation_id = app.background_executor().block(installation_id()).ok(); + let (installation_id, existing_installation_id_found) = app + .background_executor() + .block(installation_id()) + .ok() + .unzip(); let session_id = Uuid::new_v4().to_string(); init_panic_hook(&app, installation_id.clone(), session_id.clone()); @@ -173,6 +177,14 @@ fn main() { // .detach(); client.telemetry().start(installation_id, session_id, cx); + let telemetry_settings = *settings::get::(cx); + let event_operation = match existing_installation_id_found { + Some(true) => "open", + _ => "first open", + }; + client + .telemetry() + .report_app_event(telemetry_settings, event_operation); let app_state = Arc::new(AppState { languages, @@ -333,11 +345,11 @@ fn main() { // Ok::<_, anyhow::Error>(()) // } -async fn installation_id() -> Result { +async fn installation_id() -> Result<(String, bool)> { let legacy_key_name = "device_id"; if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(legacy_key_name) { - Ok(installation_id) + Ok((installation_id, true)) } else { let installation_id = Uuid::new_v4().to_string(); @@ -345,7 +357,7 @@ async fn installation_id() -> Result { .write_kvp(legacy_key_name.to_string(), installation_id.clone()) .await?; - Ok(installation_id) + Ok((installation_id, false)) } } From db3f48747420b220b1d0f37916cdecd560106f5c Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 20 Nov 2023 16:00:05 -0500 Subject: [PATCH 02/11] Fix zed2 compile error --- crates/zed2/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index aacb3ed83cfab3580b1592c2334e741bd1bec773..0f6075f62ecdce170dcb6fd55c6ac69648a4dbf2 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -177,7 +177,7 @@ fn main() { // .detach(); client.telemetry().start(installation_id, session_id, cx); - let telemetry_settings = *settings::get::(cx); + let telemetry_settings = *client::TelemetrySettings::get_global(cx); let event_operation = match existing_installation_id_found { Some(true) => "open", _ => "first open", From a0dcc9618ed5575ceaa426165a2406b4ad765232 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 20 Nov 2023 16:04:15 -0500 Subject: [PATCH 03/11] Mark app event as `open` if we fail to get installation_id If we find a previous installation_id, then we send `open`. If we don't find a previous installation_id, then we sent as `first open`. If we fail, we mark it as `open` so that we don't accidentally bloat our `first open` stats. --- crates/zed/src/main.rs | 4 ++-- crates/zed2/src/main.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 992a433a7492a825c511f731d7a51b46142412e6..b953a782cee0998b93ee6b998db9526e5f988444 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -175,8 +175,8 @@ fn main() { // Copy logic to zed2 let telemetry_settings = *settings::get::(cx); let event_operation = match existing_installation_id_found { - Some(true) => "open", - _ => "first open", + Some(false) => "first open", + _ => "open", }; client .telemetry() diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 0f6075f62ecdce170dcb6fd55c6ac69648a4dbf2..9e851f10080f97ed30a21c2506f24fb68b20a93c 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -179,8 +179,8 @@ fn main() { client.telemetry().start(installation_id, session_id, cx); let telemetry_settings = *client::TelemetrySettings::get_global(cx); let event_operation = match existing_installation_id_found { - Some(true) => "open", - _ => "first open", + Some(false) => "first open", + _ => "open", }; client .telemetry() From daddb03e7a8fda0cb4adce35cfb629cd98ea271d Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 20 Nov 2023 16:04:32 -0500 Subject: [PATCH 04/11] Remove comments --- crates/zed/src/main.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index b953a782cee0998b93ee6b998db9526e5f988444..20b93ae6bb4f3ddf0368748fd949ddb5c6b83e63 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -167,12 +167,6 @@ fn main() { .detach(); client.telemetry().start(installation_id, session_id, cx); - // TODO: - // Cleanly identify open / first open - // What should we do if we fail when looking for installation_id? - // - set to true, false, or skip? - // Report closed - // Copy logic to zed2 let telemetry_settings = *settings::get::(cx); let event_operation = match existing_installation_id_found { Some(false) => "first open", From a4a1e6ba98cd68f66e07fa01e0f24885913c1bbe Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Tue, 21 Nov 2023 17:29:06 -0500 Subject: [PATCH 05/11] WIP Co-authored-by: Mikayla --- crates/call2/src/call2.rs | 4 ++-- crates/client2/src/client2.rs | 2 +- crates/client2/src/telemetry.rs | 18 +++++++++++++++++- crates/collab2/src/tests/test_server.rs | 2 +- crates/gpui2/src/app.rs | 17 +++++++++++++++++ crates/project2/src/worktree_tests.rs | 6 +++--- crates/zed/src/main.rs | 8 ++++++++ 7 files changed, 49 insertions(+), 8 deletions(-) diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index 1f11e0650ddf3808adce0997afbce58cdc389819..14cb28c32d6b932c8db9f2fa54b5c0125bbf8011 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -464,7 +464,7 @@ impl ActiveCall { &self.pending_invites } - pub fn report_call_event(&self, operation: &'static str, cx: &AppContext) { + pub fn report_call_event(&self, operation: &'static str, cx: &mut AppContext) { if let Some(room) = self.room() { let room = room.read(cx); report_call_event_for_room(operation, room.id(), room.channel_id(), &self.client, cx); @@ -477,7 +477,7 @@ pub fn report_call_event_for_room( room_id: u64, channel_id: Option, client: &Arc, - cx: &AppContext, + cx: &mut AppContext, ) { let telemetry = client.telemetry(); let telemetry_settings = *TelemetrySettings::get_global(cx); diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index b4279b023ecd7412d8ea0c4a69ddc0215be97fb2..4ad354f2f91bd56cdb0c1f657137d1beac9a3e4f 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -382,7 +382,7 @@ impl settings::Settings for TelemetrySettings { } impl Client { - pub fn new(http: Arc, cx: &AppContext) -> Arc { + pub fn new(http: Arc, cx: &mut AppContext) -> Arc { Arc::new(Self { id: AtomicU64::new(0), peer: Peer::new(0), diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index 9bd24293a0a71f0c74f4d46212b7e473e084bfa2..ddad1d5fda5eb6b31c6a5e90eb350fb949a381ec 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -1,5 +1,6 @@ use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use chrono::{DateTime, Utc}; +use futures::Future; use gpui::{serde_json, AppContext, AppMetadata, BackgroundExecutor, Task}; use lazy_static::lazy_static; use parking_lot::Mutex; @@ -126,12 +127,13 @@ const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); impl Telemetry { - pub fn new(client: Arc, cx: &AppContext) -> Arc { + pub fn new(client: Arc, cx: &mut AppContext) -> Arc { let release_channel = if cx.has_global::() { Some(cx.global::().display_name()) } else { None }; + // TODO: Replace all hardware stuff with nested SystemSpecs json let this = Arc::new(Self { http_client: client, @@ -151,9 +153,22 @@ impl Telemetry { }), }); + // We should only ever have one instance of Telemetry, leak the subscription to keep it alive + // rather than store in TelemetryState, complicating spawn as subscriptions are not Send + std::mem::forget(cx.on_app_quit({ + let this = this.clone(); + move |cx| this.shutdown_telemetry(cx) + })); + this } + fn shutdown_telemetry(self: &Arc, cx: &mut AppContext) -> impl Future { + let telemetry_settings = TelemetrySettings::get_global(cx).clone(); + self.report_app_event(telemetry_settings, "close"); + Task::ready(()) + } + pub fn log_file_path(&self) -> Option { Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) } @@ -455,6 +470,7 @@ impl Telemetry { release_channel: state.release_channel, events, }; + dbg!(&request_body); json_bytes.clear(); serde_json::to_writer(&mut json_bytes, &request_body)?; } diff --git a/crates/collab2/src/tests/test_server.rs b/crates/collab2/src/tests/test_server.rs index 090a32d4caef33386da38f0b5cd60f83a6db5afc..6bb57e11ab1d582031930f34b8bfe67b96a2581e 100644 --- a/crates/collab2/src/tests/test_server.rs +++ b/crates/collab2/src/tests/test_server.rs @@ -149,7 +149,7 @@ impl TestServer { .user_id }; let client_name = name.to_string(); - let mut client = cx.read(|cx| Client::new(http.clone(), cx)); + let mut client = cx.update(|cx| Client::new(http.clone(), cx)); let server = self.server.clone(); let db = self.app_state.db.clone(); let connection_killers = self.connection_killers.clone(); diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index ff601db37262e57bc08436c4344e024c24b59f42..e928c22e4933e7f10b9b5074a23e93976dd9c987 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -10,6 +10,7 @@ pub use entity_map::*; pub use model_context::*; use refineable::Refineable; use smallvec::SmallVec; +use smol::future::FutureExt; #[cfg(any(test, feature = "test-support"))] pub use test_context::*; @@ -983,6 +984,22 @@ impl AppContext { pub fn all_action_names(&self) -> &[SharedString] { self.actions.all_action_names() } + + pub fn on_app_quit( + &mut self, + mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static, + ) -> Subscription + where + Fut: 'static + Future, + { + self.quit_observers.insert( + (), + Box::new(move |cx| { + let future = on_quit(cx); + async move { future.await }.boxed_local() + }), + ) + } } impl Context for AppContext { diff --git a/crates/project2/src/worktree_tests.rs b/crates/project2/src/worktree_tests.rs index df7307f694cbead126690e6fa270023ff4847926..a77f5396e1503b662c5c1c8a6a0d223ba80fc240 100644 --- a/crates/project2/src/worktree_tests.rs +++ b/crates/project2/src/worktree_tests.rs @@ -1056,7 +1056,7 @@ async fn test_create_directory_during_initial_scan(cx: &mut TestAppContext) { async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { init_test(cx); cx.executor().allow_parking(); - let client_fake = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); + let client_fake = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); let fs_fake = FakeFs::new(cx.background_executor.clone()); fs_fake @@ -1096,7 +1096,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); }); - let client_real = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); + let client_real = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); let fs_real = Arc::new(RealFs); let temp_root = temp_tree(json!({ @@ -2181,7 +2181,7 @@ async fn test_propagate_git_statuses(cx: &mut TestAppContext) { fn build_client(cx: &mut TestAppContext) -> Arc { let http_client = FakeHttpClient::with_404_response(); - cx.read(|cx| Client::new(http_client, cx)) + cx.update(|cx| Client::new(http_client, cx)) } #[track_caller] diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 20b93ae6bb4f3ddf0368748fd949ddb5c6b83e63..6fb6b2476f8d025ccc9baf20192a597a81aa1fc1 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -766,3 +766,11 @@ pub fn background_actions() -> &'static [(&'static str, &'static dyn Action)] { ("Change your settings", &zed_actions::OpenSettings), ] } + +// TODO: +// Cleanly identify open / first open +// What should we do if we fail when looking for installation_id? +// - set to true, false, or skip? +// Report closed +// Copy logic to zed2 +// If we don't add an app close, we should prob add back the flush on startup? From 6e4268a471749449fff232fab5d65fe38bab57b2 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Tue, 21 Nov 2023 21:11:17 -0500 Subject: [PATCH 06/11] Convert telemetry into a model Co-Authored-By: Julia <30666851+ForLoveOfCats@users.noreply.github.com> --- crates/auto_update2/src/auto_update.rs | 6 +- crates/call2/src/call2.rs | 17 +- crates/client2/src/client2.rs | 12 +- crates/client2/src/telemetry.rs | 265 ++++++++++++------------- crates/client2/src/user.rs | 12 +- crates/editor2/src/editor.rs | 40 ++-- crates/gpui2/src/app.rs | 31 ++- crates/zed2/src/main.rs | 18 +- crates/zed2/src/zed2.rs | 10 +- 9 files changed, 210 insertions(+), 201 deletions(-) diff --git a/crates/auto_update2/src/auto_update.rs b/crates/auto_update2/src/auto_update.rs index aeff68965fd07ce7eda4cc0aac9bb8a7aaeb4649..88f225e412900d4a31682d5b9773417c42d4c5fa 100644 --- a/crates/auto_update2/src/auto_update.rs +++ b/crates/auto_update2/src/auto_update.rs @@ -302,7 +302,11 @@ impl AutoUpdater { let mut dmg_file = File::create(&dmg_path).await?; let (installation_id, release_channel, telemetry) = cx.update(|cx| { - let installation_id = cx.global::>().telemetry().installation_id(); + let installation_id = cx + .global::>() + .telemetry() + .read(cx) + .installation_id(); let release_channel = cx .has_global::() .then(|| cx.global::().display_name()); diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index 14cb28c32d6b932c8db9f2fa54b5c0125bbf8011..6a956a73d29466e67c9346c9b72986a72432bffb 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -482,27 +482,26 @@ pub fn report_call_event_for_room( let telemetry = client.telemetry(); let telemetry_settings = *TelemetrySettings::get_global(cx); - telemetry.report_call_event(telemetry_settings, operation, Some(room_id), channel_id) + telemetry.update(cx, |this, cx| { + this.report_call_event(telemetry_settings, operation, Some(room_id), channel_id, cx) + }); } pub fn report_call_event_for_channel( operation: &'static str, channel_id: u64, client: &Arc, - cx: &AppContext, + cx: &mut AppContext, ) { let room = ActiveCall::global(cx).read(cx).room(); + let room_id = room.map(|r| r.read(cx).id()); let telemetry = client.telemetry(); - let telemetry_settings = *TelemetrySettings::get_global(cx); - telemetry.report_call_event( - telemetry_settings, - operation, - room.map(|r| r.read(cx).id()), - Some(channel_id), - ) + telemetry.update(cx, |this, cx| { + this.report_call_event(telemetry_settings, operation, room_id, Some(channel_id), cx) + }); } #[cfg(test)] diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index 4ad354f2f91bd56cdb0c1f657137d1beac9a3e4f..f7d0b787c063f0dcf7635dc646c5f1305fe9f2e4 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -121,7 +121,7 @@ pub struct Client { id: AtomicU64, peer: Arc, http: Arc, - telemetry: Arc, + telemetry: Model, state: RwLock, #[allow(clippy::type_complexity)] @@ -501,8 +501,12 @@ impl Client { })); } Status::SignedOut | Status::UpgradeRequired => { - cx.update(|cx| self.telemetry.set_authenticated_user_info(None, false, cx)) - .log_err(); + cx.update(|cx| { + self.telemetry.update(cx, |this, cx| { + this.set_authenticated_user_info(None, false, cx) + }) + }) + .log_err(); state._reconnect_task.take(); } _ => {} @@ -1320,7 +1324,7 @@ impl Client { } } - pub fn telemetry(&self) -> &Arc { + pub fn telemetry(&self) -> &Model { &self.telemetry } } diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index ddad1d5fda5eb6b31c6a5e90eb350fb949a381ec..ca7ddcca97532736fc2d78f4cde358117c394ea2 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -1,12 +1,12 @@ use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use chrono::{DateTime, Utc}; use futures::Future; -use gpui::{serde_json, AppContext, AppMetadata, BackgroundExecutor, Task}; +use gpui::{serde_json, AppContext, AppMetadata, Context, Model, ModelContext, Task}; use lazy_static::lazy_static; -use parking_lot::Mutex; use serde::Serialize; use settings::Settings; -use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration}; +use std::io::Write; +use std::{env, mem, path::PathBuf, sync::Arc, time::Duration}; use sysinfo::{ CpuRefreshKind, Pid, PidExt, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt, }; @@ -16,11 +16,6 @@ use util::{channel::ReleaseChannel, TryFutureExt}; pub struct Telemetry { http_client: Arc, - executor: BackgroundExecutor, - state: Mutex, -} - -struct TelemetryState { metrics_id: Option>, // Per logged-in user installation_id: Option>, // Per app installation (different for dev, nightly, preview, and stable) session_id: Option>, // Per app launch @@ -127,7 +122,7 @@ const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); impl Telemetry { - pub fn new(client: Arc, cx: &mut AppContext) -> Arc { + pub fn new(client: Arc, cx: &mut AppContext) -> Model { let release_channel = if cx.has_global::() { Some(cx.global::().display_name()) } else { @@ -135,57 +130,48 @@ impl Telemetry { }; // TODO: Replace all hardware stuff with nested SystemSpecs json - let this = Arc::new(Self { + let this = cx.build_model(|cx| Self { http_client: client, - executor: cx.background_executor().clone(), - state: Mutex::new(TelemetryState { - app_metadata: cx.app_metadata(), - architecture: env::consts::ARCH, - release_channel, - installation_id: None, - metrics_id: None, - session_id: None, - clickhouse_events_queue: Default::default(), - flush_clickhouse_events_task: Default::default(), - log_file: None, - is_staff: None, - first_event_datetime: None, - }), + app_metadata: cx.app_metadata(), + architecture: env::consts::ARCH, + release_channel, + installation_id: None, + metrics_id: None, + session_id: None, + clickhouse_events_queue: Default::default(), + flush_clickhouse_events_task: Default::default(), + log_file: None, + is_staff: None, + first_event_datetime: None, }); // We should only ever have one instance of Telemetry, leak the subscription to keep it alive // rather than store in TelemetryState, complicating spawn as subscriptions are not Send - std::mem::forget(cx.on_app_quit({ - let this = this.clone(); - move |cx| this.shutdown_telemetry(cx) - })); + std::mem::forget(this.update(cx, |_, cx| cx.on_app_quit(Self::shutdown_telemetry))); this } - fn shutdown_telemetry(self: &Arc, cx: &mut AppContext) -> impl Future { + fn shutdown_telemetry(&mut self, cx: &mut ModelContext) -> impl Future { let telemetry_settings = TelemetrySettings::get_global(cx).clone(); - self.report_app_event(telemetry_settings, "close"); + self.report_app_event(telemetry_settings, "close", cx); Task::ready(()) } pub fn log_file_path(&self) -> Option { - Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) + Some(self.log_file.as_ref()?.path().to_path_buf()) } pub fn start( - self: &Arc, + &mut self, installation_id: Option, session_id: String, - cx: &mut AppContext, + cx: &mut ModelContext, ) { - let mut state = self.state.lock(); - state.installation_id = installation_id.map(|id| id.into()); - state.session_id = Some(session_id.into()); - drop(state); + self.installation_id = installation_id.map(|id| id.into()); + self.session_id = Some(session_id.into()); - let this = self.clone(); - cx.spawn(|cx| async move { + cx.spawn(|this, mut cx| async move { // Avoiding calling `System::new_all()`, as there have been crashes related to it let refresh_kind = RefreshKind::new() .with_memory() // For memory usage @@ -221,23 +207,28 @@ impl Telemetry { break; }; - this.report_memory_event( - telemetry_settings, - process.memory(), - process.virtual_memory(), - ); - this.report_cpu_event( - telemetry_settings, - process.cpu_usage(), - system.cpus().len() as u32, - ); + this.update(&mut cx, |this, cx| { + this.report_memory_event( + telemetry_settings, + process.memory(), + process.virtual_memory(), + cx, + ); + this.report_cpu_event( + telemetry_settings, + process.cpu_usage(), + system.cpus().len() as u32, + cx, + ); + }) + .ok(); } }) .detach(); } pub fn set_authenticated_user_info( - self: &Arc, + &mut self, metrics_id: Option, is_staff: bool, cx: &AppContext, @@ -246,21 +237,20 @@ impl Telemetry { return; } - let mut state = self.state.lock(); let metrics_id: Option> = metrics_id.map(|id| id.into()); - state.metrics_id = metrics_id.clone(); - state.is_staff = Some(is_staff); - drop(state); + self.metrics_id = metrics_id.clone(); + self.is_staff = Some(is_staff); } pub fn report_editor_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, file_extension: Option, vim_mode: bool, operation: &'static str, copilot_enabled: bool, copilot_enabled_for_language: bool, + cx: &ModelContext, ) { let event = ClickhouseEvent::Editor { file_extension, @@ -271,15 +261,16 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false) + self.report_clickhouse_event(event, telemetry_settings, false, cx) } pub fn report_copilot_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, suggestion_id: Option, suggestion_accepted: bool, file_extension: Option, + cx: &ModelContext, ) { let event = ClickhouseEvent::Copilot { suggestion_id, @@ -288,15 +279,16 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false) + self.report_clickhouse_event(event, telemetry_settings, false, cx) } pub fn report_assistant_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, conversation_id: Option, kind: AssistantKind, model: &'static str, + cx: &ModelContext, ) { let event = ClickhouseEvent::Assistant { conversation_id, @@ -305,15 +297,16 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false) + self.report_clickhouse_event(event, telemetry_settings, false, cx) } pub fn report_call_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, operation: &'static str, room_id: Option, channel_id: Option, + cx: &ModelContext, ) { let event = ClickhouseEvent::Call { operation, @@ -322,14 +315,15 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false) + self.report_clickhouse_event(event, telemetry_settings, false, cx) } pub fn report_cpu_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, usage_as_percentage: f32, core_count: u32, + cx: &ModelContext, ) { let event = ClickhouseEvent::Cpu { usage_as_percentage, @@ -337,14 +331,15 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false) + self.report_clickhouse_event(event, telemetry_settings, false, cx) } pub fn report_memory_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, memory_in_bytes: u64, virtual_memory_in_bytes: u64, + cx: &ModelContext, ) { let event = ClickhouseEvent::Memory { memory_in_bytes, @@ -352,94 +347,90 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false) + self.report_clickhouse_event(event, telemetry_settings, false, cx) } // app_events are called at app open and app close, so flush is set to immediately send pub fn report_app_event( - self: &Arc, + &mut self, telemetry_settings: TelemetrySettings, operation: &'static str, + cx: &ModelContext, ) { let event = ClickhouseEvent::App { operation, milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, true) + self.report_clickhouse_event(event, telemetry_settings, true, cx) } - fn milliseconds_since_first_event(&self) -> i64 { - let mut state = self.state.lock(); - match state.first_event_datetime { + fn milliseconds_since_first_event(&mut self) -> i64 { + match self.first_event_datetime { Some(first_event_datetime) => { let now: DateTime = Utc::now(); now.timestamp_millis() - first_event_datetime.timestamp_millis() } None => { - state.first_event_datetime = Some(Utc::now()); + self.first_event_datetime = Some(Utc::now()); 0 } } } fn report_clickhouse_event( - self: &Arc, + &mut self, event: ClickhouseEvent, telemetry_settings: TelemetrySettings, immediate_flush: bool, + cx: &ModelContext, ) { if !telemetry_settings.metrics { return; } - let mut state = self.state.lock(); - let signed_in = state.metrics_id.is_some(); - state - .clickhouse_events_queue + let signed_in = self.metrics_id.is_some(); + self.clickhouse_events_queue .push(ClickhouseEventWrapper { signed_in, event }); - if state.installation_id.is_some() { - if immediate_flush || state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { - drop(state); - self.flush_clickhouse_events(); + if self.installation_id.is_some() { + if immediate_flush || self.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { + self.flush_clickhouse_events(cx); } else { - let this = self.clone(); - let executor = self.executor.clone(); - state.flush_clickhouse_events_task = Some(self.executor.spawn(async move { - executor.timer(DEBOUNCE_INTERVAL).await; - this.flush_clickhouse_events(); + self.flush_clickhouse_events_task = Some(cx.spawn(|this, mut cx| async move { + smol::Timer::after(DEBOUNCE_INTERVAL).await; + this.update(&mut cx, |this, cx| this.flush_clickhouse_events(cx)) + .ok(); })); } } } - pub fn metrics_id(self: &Arc) -> Option> { - self.state.lock().metrics_id.clone() + pub fn metrics_id(&self) -> Option> { + self.metrics_id.clone() } - pub fn installation_id(self: &Arc) -> Option> { - self.state.lock().installation_id.clone() + pub fn installation_id(&self) -> Option> { + self.installation_id.clone() } - pub fn is_staff(self: &Arc) -> Option { - self.state.lock().is_staff + pub fn is_staff(&self) -> Option { + self.is_staff } - fn flush_clickhouse_events(self: &Arc) { - let mut state = self.state.lock(); - state.first_event_datetime = None; - let mut events = mem::take(&mut state.clickhouse_events_queue); - state.flush_clickhouse_events_task.take(); - drop(state); + fn flush_clickhouse_events(&mut self, cx: &ModelContext) { + self.first_event_datetime = None; + let mut events = mem::take(&mut self.clickhouse_events_queue); + self.flush_clickhouse_events_task.take(); + + let http_client = self.http_client.clone(); - let this = self.clone(); - self.executor - .spawn( - async move { - let mut json_bytes = Vec::new(); + cx.spawn(|this, mut cx| { + async move { + let mut json_bytes = Vec::new(); - if let Some(file) = &mut this.state.lock().log_file { + this.update(&mut cx, |this, _| { + if let Some(file) = &mut this.log_file { let file = file.as_file_mut(); for event in &mut events { json_bytes.clear(); @@ -449,39 +440,43 @@ impl Telemetry { } } - { - let state = this.state.lock(); - let request_body = ClickhouseEventRequestBody { - token: ZED_SECRET_CLIENT_TOKEN, - installation_id: state.installation_id.clone(), - session_id: state.session_id.clone(), - is_staff: state.is_staff.clone(), - app_version: state - .app_metadata - .app_version - .map(|version| version.to_string()), - os_name: state.app_metadata.os_name, - os_version: state - .app_metadata - .os_version - .map(|version| version.to_string()), - architecture: state.architecture, - - release_channel: state.release_channel, - events, - }; - dbg!(&request_body); - json_bytes.clear(); - serde_json::to_writer(&mut json_bytes, &request_body)?; - } - - this.http_client + std::io::Result::Ok(()) + })??; + + if let Ok(Ok(json_bytes)) = this.update(&mut cx, |this, _| { + let request_body = ClickhouseEventRequestBody { + token: ZED_SECRET_CLIENT_TOKEN, + installation_id: this.installation_id.clone(), + session_id: this.session_id.clone(), + is_staff: this.is_staff.clone(), + app_version: this + .app_metadata + .app_version + .map(|version| version.to_string()), + os_name: this.app_metadata.os_name, + os_version: this + .app_metadata + .os_version + .map(|version| version.to_string()), + architecture: this.architecture, + + release_channel: this.release_channel, + events, + }; + json_bytes.clear(); + serde_json::to_writer(&mut json_bytes, &request_body)?; + + std::io::Result::Ok(json_bytes) + }) { + http_client .post_json(CLICKHOUSE_EVENTS_URL.as_str(), json_bytes.into()) .await?; - anyhow::Ok(()) } - .log_err(), - ) - .detach(); + + anyhow::Ok(()) + } + .log_err() + }) + .detach(); } } diff --git a/crates/client2/src/user.rs b/crates/client2/src/user.rs index a5dba03d2da59e8277ed5f36a71d92fe51c63162..5d115a3785ba1da12e6fef44980ce2b187263b7a 100644 --- a/crates/client2/src/user.rs +++ b/crates/client2/src/user.rs @@ -168,11 +168,13 @@ impl UserStore { cx.update(|cx| { if let Some(info) = info { cx.update_flags(info.staff, info.flags); - client.telemetry.set_authenticated_user_info( - Some(info.metrics_id.clone()), - info.staff, - cx, - ) + client.telemetry.update(cx, |this, cx| { + this.set_authenticated_user_info( + Some(info.metrics_id.clone()), + info.staff, + cx, + ) + }) } })?; diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 5e40f5368ede0af07626e8baf6ef68887be66019..b53ae376d26c2bea757efe331c94850d4f644115 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -8951,7 +8951,7 @@ impl Editor { &self, suggestion_id: Option, suggestion_accepted: bool, - cx: &AppContext, + cx: &mut AppContext, ) { let Some(project) = &self.project else { return }; @@ -8968,12 +8968,15 @@ impl Editor { let telemetry = project.read(cx).client().telemetry().clone(); let telemetry_settings = *TelemetrySettings::get_global(cx); - telemetry.report_copilot_event( - telemetry_settings, - suggestion_id, - suggestion_accepted, - file_extension, - ) + telemetry.update(cx, |this, cx| { + this.report_copilot_event( + telemetry_settings, + suggestion_id, + suggestion_accepted, + file_extension, + cx, + ) + }); } #[cfg(any(test, feature = "test-support"))] @@ -8981,7 +8984,7 @@ impl Editor { &self, _operation: &'static str, _file_extension: Option, - _cx: &AppContext, + _cx: &mut AppContext, ) { } @@ -8990,7 +8993,7 @@ impl Editor { &self, operation: &'static str, file_extension: Option, - cx: &AppContext, + cx: &mut AppContext, ) { let Some(project) = &self.project else { return }; @@ -9020,14 +9023,17 @@ impl Editor { .show_copilot_suggestions; let telemetry = project.read(cx).client().telemetry().clone(); - telemetry.report_editor_event( - telemetry_settings, - file_extension, - vim_mode, - operation, - copilot_enabled, - copilot_enabled_for_language, - ) + telemetry.update(cx, |this, cx| { + this.report_editor_event( + telemetry_settings, + file_extension, + vim_mode, + operation, + copilot_enabled, + copilot_enabled_for_language, + cx, + ) + }); } /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines, diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index e928c22e4933e7f10b9b5074a23e93976dd9c987..41b514c137dfb7706ee9399599fcd004fca582f9 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -10,7 +10,6 @@ pub use entity_map::*; pub use model_context::*; use refineable::Refineable; use smallvec::SmallVec; -use smol::future::FutureExt; #[cfg(any(test, feature = "test-support"))] pub use test_context::*; @@ -985,21 +984,21 @@ impl AppContext { self.actions.all_action_names() } - pub fn on_app_quit( - &mut self, - mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static, - ) -> Subscription - where - Fut: 'static + Future, - { - self.quit_observers.insert( - (), - Box::new(move |cx| { - let future = on_quit(cx); - async move { future.await }.boxed_local() - }), - ) - } + // pub fn on_app_quit( + // &mut self, + // mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static, + // ) -> Subscription + // where + // Fut: 'static + Future, + // { + // self.quit_observers.insert( + // (), + // Box::new(move |cx| { + // let future = on_quit(cx); + // async move { future.await }.boxed_local() + // }), + // ) + // } } impl Context for AppContext { diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 9e851f10080f97ed30a21c2506f24fb68b20a93c..18f7f4786128d26f5f289e17f82ef7e84bd80ded 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -176,15 +176,15 @@ fn main() { // }) // .detach(); - client.telemetry().start(installation_id, session_id, cx); - let telemetry_settings = *client::TelemetrySettings::get_global(cx); - let event_operation = match existing_installation_id_found { - Some(false) => "first open", - _ => "open", - }; - client - .telemetry() - .report_app_event(telemetry_settings, event_operation); + client.telemetry().update(cx, |this, cx| { + this.start(installation_id, session_id, cx); + let telemetry_settings = *client::TelemetrySettings::get_global(cx); + let event_operation = match existing_installation_id_found { + Some(false) => "first open", + _ => "open", + }; + this.report_app_event(telemetry_settings, event_operation, cx); + }); let app_state = Arc::new(AppState { languages, diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 6427fdabe8191c81597515727c5bde8bcab80cb3..50bd80b818c74a4ce6b961d0e33ce94d2f67ca7e 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -10,8 +10,8 @@ pub use assets::*; use collections::VecDeque; use editor::{Editor, MultiBuffer}; use gpui::{ - actions, point, px, AppContext, Context, FocusableView, PromptLevel, TitlebarOptions, - ViewContext, VisualContext, WindowBounds, WindowKind, WindowOptions, + actions, point, px, AppContext, AsyncAppContext, Context, FocusableView, PromptLevel, + TitlebarOptions, ViewContext, VisualContext, WindowBounds, WindowKind, WindowOptions, }; pub use only_instance::*; pub use open_listener::*; @@ -628,12 +628,12 @@ fn open_telemetry_log_file(workspace: &mut Workspace, cx: &mut ViewContext) -> Option { - let path = app_state.client.telemetry().log_file_path()?; + async fn fetch_log_string(app_state: &Arc, cx: &AsyncAppContext) -> Option { + let path = cx.update(|cx| app_state.client.telemetry().read(cx).log_file_path()).ok()??; app_state.fs.load(&path).await.log_err() } - let log = fetch_log_string(&app_state).await.unwrap_or_else(|| "// No data has been collected yet".to_string()); + let log = fetch_log_string(&app_state, &cx).await.unwrap_or_else(|| "// No data has been collected yet".to_string()); const MAX_TELEMETRY_LOG_LEN: usize = 5 * 1024 * 1024; let mut start_offset = log.len().saturating_sub(MAX_TELEMETRY_LOG_LEN); From ee2b6834bdcd88b5fd5aca2ca834870062fb74ad Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 22 Nov 2023 16:16:44 -0500 Subject: [PATCH 07/11] Revert "Convert telemetry into a model" This reverts commit 6e4268a471749449fff232fab5d65fe38bab57b2. --- crates/auto_update2/src/auto_update.rs | 6 +- crates/call2/src/call2.rs | 17 +- crates/client2/src/client2.rs | 12 +- crates/client2/src/telemetry.rs | 265 +++++++++++++------------ crates/client2/src/user.rs | 12 +- crates/editor2/src/editor.rs | 40 ++-- crates/gpui2/src/app.rs | 31 +-- crates/zed2/src/main.rs | 18 +- crates/zed2/src/zed2.rs | 10 +- 9 files changed, 201 insertions(+), 210 deletions(-) diff --git a/crates/auto_update2/src/auto_update.rs b/crates/auto_update2/src/auto_update.rs index 88f225e412900d4a31682d5b9773417c42d4c5fa..aeff68965fd07ce7eda4cc0aac9bb8a7aaeb4649 100644 --- a/crates/auto_update2/src/auto_update.rs +++ b/crates/auto_update2/src/auto_update.rs @@ -302,11 +302,7 @@ impl AutoUpdater { let mut dmg_file = File::create(&dmg_path).await?; let (installation_id, release_channel, telemetry) = cx.update(|cx| { - let installation_id = cx - .global::>() - .telemetry() - .read(cx) - .installation_id(); + let installation_id = cx.global::>().telemetry().installation_id(); let release_channel = cx .has_global::() .then(|| cx.global::().display_name()); diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index 6a956a73d29466e67c9346c9b72986a72432bffb..14cb28c32d6b932c8db9f2fa54b5c0125bbf8011 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -482,26 +482,27 @@ pub fn report_call_event_for_room( let telemetry = client.telemetry(); let telemetry_settings = *TelemetrySettings::get_global(cx); - telemetry.update(cx, |this, cx| { - this.report_call_event(telemetry_settings, operation, Some(room_id), channel_id, cx) - }); + telemetry.report_call_event(telemetry_settings, operation, Some(room_id), channel_id) } pub fn report_call_event_for_channel( operation: &'static str, channel_id: u64, client: &Arc, - cx: &mut AppContext, + cx: &AppContext, ) { let room = ActiveCall::global(cx).read(cx).room(); - let room_id = room.map(|r| r.read(cx).id()); let telemetry = client.telemetry(); + let telemetry_settings = *TelemetrySettings::get_global(cx); - telemetry.update(cx, |this, cx| { - this.report_call_event(telemetry_settings, operation, room_id, Some(channel_id), cx) - }); + telemetry.report_call_event( + telemetry_settings, + operation, + room.map(|r| r.read(cx).id()), + Some(channel_id), + ) } #[cfg(test)] diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index f7d0b787c063f0dcf7635dc646c5f1305fe9f2e4..4ad354f2f91bd56cdb0c1f657137d1beac9a3e4f 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -121,7 +121,7 @@ pub struct Client { id: AtomicU64, peer: Arc, http: Arc, - telemetry: Model, + telemetry: Arc, state: RwLock, #[allow(clippy::type_complexity)] @@ -501,12 +501,8 @@ impl Client { })); } Status::SignedOut | Status::UpgradeRequired => { - cx.update(|cx| { - self.telemetry.update(cx, |this, cx| { - this.set_authenticated_user_info(None, false, cx) - }) - }) - .log_err(); + cx.update(|cx| self.telemetry.set_authenticated_user_info(None, false, cx)) + .log_err(); state._reconnect_task.take(); } _ => {} @@ -1324,7 +1320,7 @@ impl Client { } } - pub fn telemetry(&self) -> &Model { + pub fn telemetry(&self) -> &Arc { &self.telemetry } } diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index ca7ddcca97532736fc2d78f4cde358117c394ea2..ddad1d5fda5eb6b31c6a5e90eb350fb949a381ec 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -1,12 +1,12 @@ use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use chrono::{DateTime, Utc}; use futures::Future; -use gpui::{serde_json, AppContext, AppMetadata, Context, Model, ModelContext, Task}; +use gpui::{serde_json, AppContext, AppMetadata, BackgroundExecutor, Task}; use lazy_static::lazy_static; +use parking_lot::Mutex; use serde::Serialize; use settings::Settings; -use std::io::Write; -use std::{env, mem, path::PathBuf, sync::Arc, time::Duration}; +use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration}; use sysinfo::{ CpuRefreshKind, Pid, PidExt, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt, }; @@ -16,6 +16,11 @@ use util::{channel::ReleaseChannel, TryFutureExt}; pub struct Telemetry { http_client: Arc, + executor: BackgroundExecutor, + state: Mutex, +} + +struct TelemetryState { metrics_id: Option>, // Per logged-in user installation_id: Option>, // Per app installation (different for dev, nightly, preview, and stable) session_id: Option>, // Per app launch @@ -122,7 +127,7 @@ const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); impl Telemetry { - pub fn new(client: Arc, cx: &mut AppContext) -> Model { + pub fn new(client: Arc, cx: &mut AppContext) -> Arc { let release_channel = if cx.has_global::() { Some(cx.global::().display_name()) } else { @@ -130,48 +135,57 @@ impl Telemetry { }; // TODO: Replace all hardware stuff with nested SystemSpecs json - let this = cx.build_model(|cx| Self { + let this = Arc::new(Self { http_client: client, - app_metadata: cx.app_metadata(), - architecture: env::consts::ARCH, - release_channel, - installation_id: None, - metrics_id: None, - session_id: None, - clickhouse_events_queue: Default::default(), - flush_clickhouse_events_task: Default::default(), - log_file: None, - is_staff: None, - first_event_datetime: None, + executor: cx.background_executor().clone(), + state: Mutex::new(TelemetryState { + app_metadata: cx.app_metadata(), + architecture: env::consts::ARCH, + release_channel, + installation_id: None, + metrics_id: None, + session_id: None, + clickhouse_events_queue: Default::default(), + flush_clickhouse_events_task: Default::default(), + log_file: None, + is_staff: None, + first_event_datetime: None, + }), }); // We should only ever have one instance of Telemetry, leak the subscription to keep it alive // rather than store in TelemetryState, complicating spawn as subscriptions are not Send - std::mem::forget(this.update(cx, |_, cx| cx.on_app_quit(Self::shutdown_telemetry))); + std::mem::forget(cx.on_app_quit({ + let this = this.clone(); + move |cx| this.shutdown_telemetry(cx) + })); this } - fn shutdown_telemetry(&mut self, cx: &mut ModelContext) -> impl Future { + fn shutdown_telemetry(self: &Arc, cx: &mut AppContext) -> impl Future { let telemetry_settings = TelemetrySettings::get_global(cx).clone(); - self.report_app_event(telemetry_settings, "close", cx); + self.report_app_event(telemetry_settings, "close"); Task::ready(()) } pub fn log_file_path(&self) -> Option { - Some(self.log_file.as_ref()?.path().to_path_buf()) + Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) } pub fn start( - &mut self, + self: &Arc, installation_id: Option, session_id: String, - cx: &mut ModelContext, + cx: &mut AppContext, ) { - self.installation_id = installation_id.map(|id| id.into()); - self.session_id = Some(session_id.into()); + let mut state = self.state.lock(); + state.installation_id = installation_id.map(|id| id.into()); + state.session_id = Some(session_id.into()); + drop(state); - cx.spawn(|this, mut cx| async move { + let this = self.clone(); + cx.spawn(|cx| async move { // Avoiding calling `System::new_all()`, as there have been crashes related to it let refresh_kind = RefreshKind::new() .with_memory() // For memory usage @@ -207,28 +221,23 @@ impl Telemetry { break; }; - this.update(&mut cx, |this, cx| { - this.report_memory_event( - telemetry_settings, - process.memory(), - process.virtual_memory(), - cx, - ); - this.report_cpu_event( - telemetry_settings, - process.cpu_usage(), - system.cpus().len() as u32, - cx, - ); - }) - .ok(); + this.report_memory_event( + telemetry_settings, + process.memory(), + process.virtual_memory(), + ); + this.report_cpu_event( + telemetry_settings, + process.cpu_usage(), + system.cpus().len() as u32, + ); } }) .detach(); } pub fn set_authenticated_user_info( - &mut self, + self: &Arc, metrics_id: Option, is_staff: bool, cx: &AppContext, @@ -237,20 +246,21 @@ impl Telemetry { return; } + let mut state = self.state.lock(); let metrics_id: Option> = metrics_id.map(|id| id.into()); - self.metrics_id = metrics_id.clone(); - self.is_staff = Some(is_staff); + state.metrics_id = metrics_id.clone(); + state.is_staff = Some(is_staff); + drop(state); } pub fn report_editor_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, file_extension: Option, vim_mode: bool, operation: &'static str, copilot_enabled: bool, copilot_enabled_for_language: bool, - cx: &ModelContext, ) { let event = ClickhouseEvent::Editor { file_extension, @@ -261,16 +271,15 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false, cx) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_copilot_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, suggestion_id: Option, suggestion_accepted: bool, file_extension: Option, - cx: &ModelContext, ) { let event = ClickhouseEvent::Copilot { suggestion_id, @@ -279,16 +288,15 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false, cx) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_assistant_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, conversation_id: Option, kind: AssistantKind, model: &'static str, - cx: &ModelContext, ) { let event = ClickhouseEvent::Assistant { conversation_id, @@ -297,16 +305,15 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false, cx) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_call_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, operation: &'static str, room_id: Option, channel_id: Option, - cx: &ModelContext, ) { let event = ClickhouseEvent::Call { operation, @@ -315,15 +322,14 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false, cx) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_cpu_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, usage_as_percentage: f32, core_count: u32, - cx: &ModelContext, ) { let event = ClickhouseEvent::Cpu { usage_as_percentage, @@ -331,15 +337,14 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false, cx) + self.report_clickhouse_event(event, telemetry_settings, false) } pub fn report_memory_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, memory_in_bytes: u64, virtual_memory_in_bytes: u64, - cx: &ModelContext, ) { let event = ClickhouseEvent::Memory { memory_in_bytes, @@ -347,90 +352,94 @@ impl Telemetry { milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, false, cx) + self.report_clickhouse_event(event, telemetry_settings, false) } // app_events are called at app open and app close, so flush is set to immediately send pub fn report_app_event( - &mut self, + self: &Arc, telemetry_settings: TelemetrySettings, operation: &'static str, - cx: &ModelContext, ) { let event = ClickhouseEvent::App { operation, milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, true, cx) + self.report_clickhouse_event(event, telemetry_settings, true) } - fn milliseconds_since_first_event(&mut self) -> i64 { - match self.first_event_datetime { + fn milliseconds_since_first_event(&self) -> i64 { + let mut state = self.state.lock(); + match state.first_event_datetime { Some(first_event_datetime) => { let now: DateTime = Utc::now(); now.timestamp_millis() - first_event_datetime.timestamp_millis() } None => { - self.first_event_datetime = Some(Utc::now()); + state.first_event_datetime = Some(Utc::now()); 0 } } } fn report_clickhouse_event( - &mut self, + self: &Arc, event: ClickhouseEvent, telemetry_settings: TelemetrySettings, immediate_flush: bool, - cx: &ModelContext, ) { if !telemetry_settings.metrics { return; } - let signed_in = self.metrics_id.is_some(); - self.clickhouse_events_queue + let mut state = self.state.lock(); + let signed_in = state.metrics_id.is_some(); + state + .clickhouse_events_queue .push(ClickhouseEventWrapper { signed_in, event }); - if self.installation_id.is_some() { - if immediate_flush || self.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { - self.flush_clickhouse_events(cx); + if state.installation_id.is_some() { + if immediate_flush || state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { + drop(state); + self.flush_clickhouse_events(); } else { - self.flush_clickhouse_events_task = Some(cx.spawn(|this, mut cx| async move { - smol::Timer::after(DEBOUNCE_INTERVAL).await; - this.update(&mut cx, |this, cx| this.flush_clickhouse_events(cx)) - .ok(); + let this = self.clone(); + let executor = self.executor.clone(); + state.flush_clickhouse_events_task = Some(self.executor.spawn(async move { + executor.timer(DEBOUNCE_INTERVAL).await; + this.flush_clickhouse_events(); })); } } } - pub fn metrics_id(&self) -> Option> { - self.metrics_id.clone() + pub fn metrics_id(self: &Arc) -> Option> { + self.state.lock().metrics_id.clone() } - pub fn installation_id(&self) -> Option> { - self.installation_id.clone() + pub fn installation_id(self: &Arc) -> Option> { + self.state.lock().installation_id.clone() } - pub fn is_staff(&self) -> Option { - self.is_staff + pub fn is_staff(self: &Arc) -> Option { + self.state.lock().is_staff } - fn flush_clickhouse_events(&mut self, cx: &ModelContext) { - self.first_event_datetime = None; - let mut events = mem::take(&mut self.clickhouse_events_queue); - self.flush_clickhouse_events_task.take(); - - let http_client = self.http_client.clone(); + fn flush_clickhouse_events(self: &Arc) { + let mut state = self.state.lock(); + state.first_event_datetime = None; + let mut events = mem::take(&mut state.clickhouse_events_queue); + state.flush_clickhouse_events_task.take(); + drop(state); - cx.spawn(|this, mut cx| { - async move { - let mut json_bytes = Vec::new(); + let this = self.clone(); + self.executor + .spawn( + async move { + let mut json_bytes = Vec::new(); - this.update(&mut cx, |this, _| { - if let Some(file) = &mut this.log_file { + if let Some(file) = &mut this.state.lock().log_file { let file = file.as_file_mut(); for event in &mut events { json_bytes.clear(); @@ -440,43 +449,39 @@ impl Telemetry { } } - std::io::Result::Ok(()) - })??; - - if let Ok(Ok(json_bytes)) = this.update(&mut cx, |this, _| { - let request_body = ClickhouseEventRequestBody { - token: ZED_SECRET_CLIENT_TOKEN, - installation_id: this.installation_id.clone(), - session_id: this.session_id.clone(), - is_staff: this.is_staff.clone(), - app_version: this - .app_metadata - .app_version - .map(|version| version.to_string()), - os_name: this.app_metadata.os_name, - os_version: this - .app_metadata - .os_version - .map(|version| version.to_string()), - architecture: this.architecture, - - release_channel: this.release_channel, - events, - }; - json_bytes.clear(); - serde_json::to_writer(&mut json_bytes, &request_body)?; - - std::io::Result::Ok(json_bytes) - }) { - http_client + { + let state = this.state.lock(); + let request_body = ClickhouseEventRequestBody { + token: ZED_SECRET_CLIENT_TOKEN, + installation_id: state.installation_id.clone(), + session_id: state.session_id.clone(), + is_staff: state.is_staff.clone(), + app_version: state + .app_metadata + .app_version + .map(|version| version.to_string()), + os_name: state.app_metadata.os_name, + os_version: state + .app_metadata + .os_version + .map(|version| version.to_string()), + architecture: state.architecture, + + release_channel: state.release_channel, + events, + }; + dbg!(&request_body); + json_bytes.clear(); + serde_json::to_writer(&mut json_bytes, &request_body)?; + } + + this.http_client .post_json(CLICKHOUSE_EVENTS_URL.as_str(), json_bytes.into()) .await?; + anyhow::Ok(()) } - - anyhow::Ok(()) - } - .log_err() - }) - .detach(); + .log_err(), + ) + .detach(); } } diff --git a/crates/client2/src/user.rs b/crates/client2/src/user.rs index 5d115a3785ba1da12e6fef44980ce2b187263b7a..a5dba03d2da59e8277ed5f36a71d92fe51c63162 100644 --- a/crates/client2/src/user.rs +++ b/crates/client2/src/user.rs @@ -168,13 +168,11 @@ impl UserStore { cx.update(|cx| { if let Some(info) = info { cx.update_flags(info.staff, info.flags); - client.telemetry.update(cx, |this, cx| { - this.set_authenticated_user_info( - Some(info.metrics_id.clone()), - info.staff, - cx, - ) - }) + client.telemetry.set_authenticated_user_info( + Some(info.metrics_id.clone()), + info.staff, + cx, + ) } })?; diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 0b367b76565366032da752e3f6324b7569996f04..fa5f4dfa42975700f0cba6276a276273b2454de9 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -8954,7 +8954,7 @@ impl Editor { &self, suggestion_id: Option, suggestion_accepted: bool, - cx: &mut AppContext, + cx: &AppContext, ) { let Some(project) = &self.project else { return }; @@ -8971,15 +8971,12 @@ impl Editor { let telemetry = project.read(cx).client().telemetry().clone(); let telemetry_settings = *TelemetrySettings::get_global(cx); - telemetry.update(cx, |this, cx| { - this.report_copilot_event( - telemetry_settings, - suggestion_id, - suggestion_accepted, - file_extension, - cx, - ) - }); + telemetry.report_copilot_event( + telemetry_settings, + suggestion_id, + suggestion_accepted, + file_extension, + ) } #[cfg(any(test, feature = "test-support"))] @@ -8987,7 +8984,7 @@ impl Editor { &self, _operation: &'static str, _file_extension: Option, - _cx: &mut AppContext, + _cx: &AppContext, ) { } @@ -8996,7 +8993,7 @@ impl Editor { &self, operation: &'static str, file_extension: Option, - cx: &mut AppContext, + cx: &AppContext, ) { let Some(project) = &self.project else { return }; @@ -9026,17 +9023,14 @@ impl Editor { .show_copilot_suggestions; let telemetry = project.read(cx).client().telemetry().clone(); - telemetry.update(cx, |this, cx| { - this.report_editor_event( - telemetry_settings, - file_extension, - vim_mode, - operation, - copilot_enabled, - copilot_enabled_for_language, - cx, - ) - }); + telemetry.report_editor_event( + telemetry_settings, + file_extension, + vim_mode, + operation, + copilot_enabled, + copilot_enabled_for_language, + ) } /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines, diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 1d599eaede0ae96c5dbb5fcc61d8a1a5dbba32d6..617c0b5600742a07029863468b785376c1d53224 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -10,6 +10,7 @@ pub use entity_map::*; pub use model_context::*; use refineable::Refineable; use smallvec::SmallVec; +use smol::future::FutureExt; #[cfg(any(test, feature = "test-support"))] pub use test_context::*; @@ -984,21 +985,21 @@ impl AppContext { self.actions.all_action_names() } - // pub fn on_app_quit( - // &mut self, - // mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static, - // ) -> Subscription - // where - // Fut: 'static + Future, - // { - // self.quit_observers.insert( - // (), - // Box::new(move |cx| { - // let future = on_quit(cx); - // async move { future.await }.boxed_local() - // }), - // ) - // } + pub fn on_app_quit( + &mut self, + mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static, + ) -> Subscription + where + Fut: 'static + Future, + { + self.quit_observers.insert( + (), + Box::new(move |cx| { + let future = on_quit(cx); + async move { future.await }.boxed_local() + }), + ) + } } impl Context for AppContext { diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index d380d1f47c0e0f9d5c7ae5b4c65f0020d7f60489..46be582129685b125b3a17806f6a7c265b620e08 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -176,15 +176,15 @@ fn main() { // }) // .detach(); - client.telemetry().update(cx, |this, cx| { - this.start(installation_id, session_id, cx); - let telemetry_settings = *client::TelemetrySettings::get_global(cx); - let event_operation = match existing_installation_id_found { - Some(false) => "first open", - _ => "open", - }; - this.report_app_event(telemetry_settings, event_operation, cx); - }); + client.telemetry().start(installation_id, session_id, cx); + let telemetry_settings = *client::TelemetrySettings::get_global(cx); + let event_operation = match existing_installation_id_found { + Some(false) => "first open", + _ => "open", + }; + client + .telemetry() + .report_app_event(telemetry_settings, event_operation); let app_state = Arc::new(AppState { languages, diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 09880b858f30bc53aadbbda1136c9cb68aa7eff5..1286594138f2e4b32310dbde972f348c3b9719d2 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -10,8 +10,8 @@ pub use assets::*; use collections::VecDeque; use editor::{Editor, MultiBuffer}; use gpui::{ - actions, point, px, AppContext, AsyncAppContext, Context, FocusableView, PromptLevel, - TitlebarOptions, ViewContext, VisualContext, WindowBounds, WindowKind, WindowOptions, + actions, point, px, AppContext, Context, FocusableView, PromptLevel, TitlebarOptions, + ViewContext, VisualContext, WindowBounds, WindowKind, WindowOptions, }; pub use only_instance::*; pub use open_listener::*; @@ -628,12 +628,12 @@ fn open_telemetry_log_file(workspace: &mut Workspace, cx: &mut ViewContext, cx: &AsyncAppContext) -> Option { - let path = cx.update(|cx| app_state.client.telemetry().read(cx).log_file_path()).ok()??; + async fn fetch_log_string(app_state: &Arc) -> Option { + let path = app_state.client.telemetry().log_file_path()?; app_state.fs.load(&path).await.log_err() } - let log = fetch_log_string(&app_state, &cx).await.unwrap_or_else(|| "// No data has been collected yet".to_string()); + let log = fetch_log_string(&app_state).await.unwrap_or_else(|| "// No data has been collected yet".to_string()); const MAX_TELEMETRY_LOG_LEN: usize = 5 * 1024 * 1024; let mut start_offset = log.len().saturating_sub(MAX_TELEMETRY_LOG_LEN); From 0def2bc0d2563dae9b6c4904ae06ec27e74230a1 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 22 Nov 2023 16:26:15 -0500 Subject: [PATCH 08/11] Remove dbg --- crates/client2/src/telemetry.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index ddad1d5fda5eb6b31c6a5e90eb350fb949a381ec..c7be5f687d853a5d41813eed9f7e97b2aa978932 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -470,7 +470,6 @@ impl Telemetry { release_channel: state.release_channel, events, }; - dbg!(&request_body); json_bytes.clear(); serde_json::to_writer(&mut json_bytes, &request_body)?; } From a876b6f700a73051848e0ffdff601b78a339b82c Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 22 Nov 2023 23:01:18 -0500 Subject: [PATCH 09/11] Remove comments --- crates/zed/src/main.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 6fb6b2476f8d025ccc9baf20192a597a81aa1fc1..20b93ae6bb4f3ddf0368748fd949ddb5c6b83e63 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -766,11 +766,3 @@ pub fn background_actions() -> &'static [(&'static str, &'static dyn Action)] { ("Change your settings", &zed_actions::OpenSettings), ] } - -// TODO: -// Cleanly identify open / first open -// What should we do if we fail when looking for installation_id? -// - set to true, false, or skip? -// Report closed -// Copy logic to zed2 -// If we don't add an app close, we should prob add back the flush on startup? From 575ab81409a2378b9148b6f753453e78bee9ff51 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 22 Nov 2023 23:01:31 -0500 Subject: [PATCH 10/11] Disable app close event --- crates/client2/src/telemetry.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index c7be5f687d853a5d41813eed9f7e97b2aa978932..31d0a9f5d97d3ec39dc42524ed88a2fdc462e2b1 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -155,19 +155,19 @@ impl Telemetry { // We should only ever have one instance of Telemetry, leak the subscription to keep it alive // rather than store in TelemetryState, complicating spawn as subscriptions are not Send - std::mem::forget(cx.on_app_quit({ - let this = this.clone(); - move |cx| this.shutdown_telemetry(cx) - })); + // std::mem::forget(cx.on_app_quit({ + // let this = this.clone(); + // move |cx| this.shutdown_telemetry(cx) + // })); this } - fn shutdown_telemetry(self: &Arc, cx: &mut AppContext) -> impl Future { - let telemetry_settings = TelemetrySettings::get_global(cx).clone(); - self.report_app_event(telemetry_settings, "close"); - Task::ready(()) - } + // fn shutdown_telemetry(self: &Arc, cx: &mut AppContext) -> impl Future { + // let telemetry_settings = TelemetrySettings::get_global(cx).clone(); + // self.report_app_event(telemetry_settings, "close"); + // Task::ready(()) + // } pub fn log_file_path(&self) -> Option { Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) From 35f35dd47646edfef37f432dd971be34f6d02288 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 22 Nov 2023 23:03:11 -0500 Subject: [PATCH 11/11] Remove unused import --- crates/client2/src/telemetry.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index 31d0a9f5d97d3ec39dc42524ed88a2fdc462e2b1..37651ebcfbd5d22e8e7c372e894e820f88d7004c 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -1,6 +1,5 @@ use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use chrono::{DateTime, Utc}; -use futures::Future; use gpui::{serde_json, AppContext, AppMetadata, BackgroundExecutor, Task}; use lazy_static::lazy_static; use parking_lot::Mutex;