Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Joseph T. Lyons 2023-11-21 17:29:06 -05:00
parent daddb03e7a
commit a4a1e6ba98
7 changed files with 49 additions and 8 deletions

View file

@ -464,7 +464,7 @@ impl ActiveCall {
&self.pending_invites &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() { if let Some(room) = self.room() {
let room = room.read(cx); let room = room.read(cx);
report_call_event_for_room(operation, room.id(), room.channel_id(), &self.client, 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, room_id: u64,
channel_id: Option<u64>, channel_id: Option<u64>,
client: &Arc<Client>, client: &Arc<Client>,
cx: &AppContext, cx: &mut AppContext,
) { ) {
let telemetry = client.telemetry(); let telemetry = client.telemetry();
let telemetry_settings = *TelemetrySettings::get_global(cx); let telemetry_settings = *TelemetrySettings::get_global(cx);

View file

@ -382,7 +382,7 @@ impl settings::Settings for TelemetrySettings {
} }
impl Client { impl Client {
pub fn new(http: Arc<dyn HttpClient>, cx: &AppContext) -> Arc<Self> { pub fn new(http: Arc<dyn HttpClient>, cx: &mut AppContext) -> Arc<Self> {
Arc::new(Self { Arc::new(Self {
id: AtomicU64::new(0), id: AtomicU64::new(0),
peer: Peer::new(0), peer: Peer::new(0),

View file

@ -1,5 +1,6 @@
use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use futures::Future;
use gpui::{serde_json, AppContext, AppMetadata, BackgroundExecutor, Task}; use gpui::{serde_json, AppContext, AppMetadata, BackgroundExecutor, Task};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -126,12 +127,13 @@ const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1);
const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30);
impl Telemetry { impl Telemetry {
pub fn new(client: Arc<dyn HttpClient>, cx: &AppContext) -> Arc<Self> { pub fn new(client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Arc<Self> {
let release_channel = if cx.has_global::<ReleaseChannel>() { let release_channel = if cx.has_global::<ReleaseChannel>() {
Some(cx.global::<ReleaseChannel>().display_name()) Some(cx.global::<ReleaseChannel>().display_name())
} else { } else {
None None
}; };
// TODO: Replace all hardware stuff with nested SystemSpecs json // TODO: Replace all hardware stuff with nested SystemSpecs json
let this = Arc::new(Self { let this = Arc::new(Self {
http_client: client, 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 this
} }
fn shutdown_telemetry(self: &Arc<Self>, cx: &mut AppContext) -> impl Future<Output = ()> {
let telemetry_settings = TelemetrySettings::get_global(cx).clone();
self.report_app_event(telemetry_settings, "close");
Task::ready(())
}
pub fn log_file_path(&self) -> Option<PathBuf> { pub fn log_file_path(&self) -> Option<PathBuf> {
Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) Some(self.state.lock().log_file.as_ref()?.path().to_path_buf())
} }
@ -455,6 +470,7 @@ impl Telemetry {
release_channel: state.release_channel, release_channel: state.release_channel,
events, events,
}; };
dbg!(&request_body);
json_bytes.clear(); json_bytes.clear();
serde_json::to_writer(&mut json_bytes, &request_body)?; serde_json::to_writer(&mut json_bytes, &request_body)?;
} }

View file

@ -149,7 +149,7 @@ impl TestServer {
.user_id .user_id
}; };
let client_name = name.to_string(); 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 server = self.server.clone();
let db = self.app_state.db.clone(); let db = self.app_state.db.clone();
let connection_killers = self.connection_killers.clone(); let connection_killers = self.connection_killers.clone();

View file

@ -10,6 +10,7 @@ pub use entity_map::*;
pub use model_context::*; pub use model_context::*;
use refineable::Refineable; use refineable::Refineable;
use smallvec::SmallVec; use smallvec::SmallVec;
use smol::future::FutureExt;
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub use test_context::*; pub use test_context::*;
@ -983,6 +984,22 @@ impl AppContext {
pub fn all_action_names(&self) -> &[SharedString] { pub fn all_action_names(&self) -> &[SharedString] {
self.actions.all_action_names() self.actions.all_action_names()
} }
pub fn on_app_quit<Fut>(
&mut self,
mut on_quit: impl FnMut(&mut AppContext) -> Fut + 'static,
) -> Subscription
where
Fut: 'static + Future<Output = ()>,
{
self.quit_observers.insert(
(),
Box::new(move |cx| {
let future = on_quit(cx);
async move { future.await }.boxed_local()
}),
)
}
} }
impl Context for AppContext { impl Context for AppContext {

View file

@ -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) { async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
init_test(cx); init_test(cx);
cx.executor().allow_parking(); 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()); let fs_fake = FakeFs::new(cx.background_executor.clone());
fs_fake 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()); 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 fs_real = Arc::new(RealFs);
let temp_root = temp_tree(json!({ 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<Client> { fn build_client(cx: &mut TestAppContext) -> Arc<Client> {
let http_client = FakeHttpClient::with_404_response(); 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] #[track_caller]

View file

@ -766,3 +766,11 @@ pub fn background_actions() -> &'static [(&'static str, &'static dyn Action)] {
("Change your settings", &zed_actions::OpenSettings), ("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?