Add more open events (#4061)

Joseph T. Lyons created

Adds open events for

- Welcome page
- Project search
- Project diagnostics

Release Notes:

- N/A

Change summary

crates/client/src/telemetry.rs                | 35 ++++++++++----------
crates/collab_ui/src/channel_view.rs          |  4 ++
crates/diagnostics/src/diagnostics.rs         |  4 ++
crates/editor/src/items.rs                    |  4 ++
crates/language_tools/src/lsp_log.rs          |  4 ++
crates/language_tools/src/syntax_tree_view.rs |  4 ++
crates/search/src/project_search.rs           |  4 ++
crates/terminal_view/src/terminal_view.rs     |  4 ++
crates/welcome/src/welcome.rs                 | 27 ++++++++++-----
crates/workspace/src/item.rs                  | 11 ++++++
crates/workspace/src/shared_screen.rs         |  4 ++
crates/workspace/src/workspace.rs             | 10 +++++
crates/zed/src/main.rs                        | 11 ++++--
13 files changed, 95 insertions(+), 31 deletions(-)

Detailed changes

crates/client/src/telemetry.rs 🔗

@@ -116,7 +116,7 @@ pub enum Event {
         milliseconds_since_first_event: i64,
     },
     App {
-        operation: &'static str,
+        operation: String,
         milliseconds_since_first_event: i64,
     },
     Setting {
@@ -219,7 +219,7 @@ impl Telemetry {
     // TestAppContext ends up calling this function on shutdown and it panics when trying to find the TelemetrySettings
     #[cfg(not(any(test, feature = "test-support")))]
     fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> {
-        self.report_app_event("close");
+        self.report_app_event("close".to_string());
         // TODO: close final edit period and make sure it's sent
         Task::ready(())
     }
@@ -385,7 +385,7 @@ impl Telemetry {
         self.report_event(event)
     }
 
-    pub fn report_app_event(self: &Arc<Self>, operation: &'static str) {
+    pub fn report_app_event(self: &Arc<Self>, operation: String) {
         let event = Event::App {
             operation,
             milliseconds_since_first_event: self.milliseconds_since_first_event(),
@@ -404,20 +404,6 @@ impl Telemetry {
         self.report_event(event)
     }
 
-    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> = Utc::now();
-                now.timestamp_millis() - first_event_datetime.timestamp_millis()
-            }
-            None => {
-                state.first_event_datetime = Some(Utc::now());
-                0
-            }
-        }
-    }
-
     pub fn log_edit_event(self: &Arc<Self>, environment: &'static str) {
         let mut state = self.state.lock();
         let period_data = state.event_coalescer.log_event(environment);
@@ -434,6 +420,21 @@ impl Telemetry {
         }
     }
 
+    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> = Utc::now();
+                now.timestamp_millis() - first_event_datetime.timestamp_millis()
+            }
+            None => {
+                state.first_event_datetime = Some(Utc::now());
+                0
+            }
+        }
+    }
+
     fn report_event(self: &Arc<Self>, event: Event) {
         let mut state = self.state.lock();
 

crates/collab_ui/src/channel_view.rs 🔗

@@ -266,6 +266,10 @@ impl Item for ChannelView {
             .into_any_element()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        None
+    }
+
     fn clone_on_split(&self, _: WorkspaceId, cx: &mut ViewContext<Self>) -> Option<View<Self>> {
         Some(cx.new_view(|cx| {
             Self::new(

crates/diagnostics/src/diagnostics.rs 🔗

@@ -688,6 +688,10 @@ impl Item for ProjectDiagnosticsEditor {
         }
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        Some("project diagnostics")
+    }
+
     fn for_each_project_item(
         &self,
         cx: &AppContext,

crates/editor/src/items.rs 🔗

@@ -578,6 +578,10 @@ impl Item for Editor {
         Some(file_path.into())
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        None
+    }
+
     fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option<SharedString> {
         let path = path_for_buffer(&self.buffer, detail, true, cx)?;
         Some(path.to_string_lossy().to_string().into())

crates/language_tools/src/lsp_log.rs 🔗

@@ -631,6 +631,10 @@ impl Item for LspLogView {
             .into_any_element()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        None
+    }
+
     fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
         Some(Box::new(handle.clone()))
     }

crates/language_tools/src/syntax_tree_view.rs 🔗

@@ -397,6 +397,10 @@ impl Item for SyntaxTreeView {
             .into_any_element()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        None
+    }
+
     fn clone_on_split(
         &self,
         _: workspace::WorkspaceId,

crates/search/src/project_search.rs 🔗

@@ -446,6 +446,10 @@ impl Item for ProjectSearchView {
             .into_any()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        Some("project search")
+    }
+
     fn for_each_project_item(
         &self,
         cx: &AppContext,

crates/terminal_view/src/terminal_view.rs 🔗

@@ -708,6 +708,10 @@ impl Item for TerminalView {
             .into_any()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        None
+    }
+
     fn clone_on_split(
         &self,
         _workspace_id: WorkspaceId,

crates/welcome/src/welcome.rs 🔗

@@ -86,7 +86,7 @@ impl Render for WelcomePage {
                                 .full_width()
                                 .on_click(cx.listener(|this, _, cx| {
                                     this.telemetry
-                                        .report_app_event("welcome page: change theme");
+                                        .report_app_event("welcome page: change theme".to_string());
                                     this.workspace
                                         .update(cx, |workspace, cx| {
                                             theme_selector::toggle(
@@ -102,8 +102,9 @@ impl Render for WelcomePage {
                             Button::new("choose-keymap", "Choose a keymap")
                                 .full_width()
                                 .on_click(cx.listener(|this, _, cx| {
-                                    this.telemetry
-                                        .report_app_event("welcome page: change keymap");
+                                    this.telemetry.report_app_event(
+                                        "welcome page: change keymap".to_string(),
+                                    );
                                     this.workspace
                                         .update(cx, |workspace, cx| {
                                             base_keymap_picker::toggle(
@@ -119,7 +120,8 @@ impl Render for WelcomePage {
                             Button::new("install-cli", "Install the CLI")
                                 .full_width()
                                 .on_click(cx.listener(|this, _, cx| {
-                                    this.telemetry.report_app_event("welcome page: install cli");
+                                    this.telemetry
+                                        .report_app_event("welcome page: install cli".to_string());
                                     cx.app_mut()
                                         .spawn(
                                             |cx| async move { install_cli::install_cli(&cx).await },
@@ -150,8 +152,9 @@ impl Render for WelcomePage {
                                     )
                                     .on_click(cx.listener(
                                         move |this, selection, cx| {
-                                            this.telemetry
-                                                .report_app_event("welcome page: toggle vim");
+                                            this.telemetry.report_app_event(
+                                                "welcome page: toggle vim".to_string(),
+                                            );
                                             this.update_settings::<VimModeSetting>(
                                                 selection,
                                                 cx,
@@ -177,7 +180,7 @@ impl Render for WelcomePage {
                                     .on_click(cx.listener(
                                         move |this, selection, cx| {
                                             this.telemetry.report_app_event(
-                                                "welcome page: toggle metric telemetry",
+                                                "welcome page: toggle metric telemetry".to_string(),
                                             );
                                             this.update_settings::<TelemetrySettings>(
                                                 selection,
@@ -215,7 +218,8 @@ impl Render for WelcomePage {
                                     .on_click(cx.listener(
                                         move |this, selection, cx| {
                                             this.telemetry.report_app_event(
-                                                "welcome page: toggle diagnostic telemetry",
+                                                "welcome page: toggle diagnostic telemetry"
+                                                    .to_string(),
                                             );
                                             this.update_settings::<TelemetrySettings>(
                                                 selection,
@@ -247,7 +251,8 @@ impl WelcomePage {
     pub fn new(workspace: &Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
         let this = cx.new_view(|cx| {
             cx.on_release(|this: &mut Self, _, _| {
-                this.telemetry.report_app_event("welcome page: close");
+                this.telemetry
+                    .report_app_event("welcome page: close".to_string());
             })
             .detach();
 
@@ -306,6 +311,10 @@ impl Item for WelcomePage {
             .into_any_element()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        Some("welcome page")
+    }
+
     fn show_toolbar(&self) -> bool {
         false
     }

crates/workspace/src/item.rs 🔗

@@ -114,6 +114,8 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
     }
     fn tab_content(&self, detail: Option<usize>, selected: bool, cx: &WindowContext) -> AnyElement;
 
+    fn telemetry_event_text(&self) -> Option<&'static str>;
+
     /// (model id, Item)
     fn for_each_project_item(
         &self,
@@ -225,6 +227,7 @@ pub trait ItemHandle: 'static + Send {
     fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>;
     fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>;
     fn tab_content(&self, detail: Option<usize>, selected: bool, cx: &WindowContext) -> AnyElement;
+    fn telemetry_event_text(&self, cx: &WindowContext) -> Option<&'static str>;
     fn dragged_tab_content(&self, detail: Option<usize>, cx: &WindowContext) -> AnyElement;
     fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
     fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>;
@@ -313,6 +316,10 @@ impl<T: Item> ItemHandle for View<T> {
         self.read(cx).tab_tooltip_text(cx)
     }
 
+    fn telemetry_event_text(&self, cx: &WindowContext) -> Option<&'static str> {
+        self.read(cx).telemetry_event_text()
+    }
+
     fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString> {
         self.read(cx).tab_description(detail, cx)
     }
@@ -922,6 +929,10 @@ pub mod test {
             })
         }
 
+        fn telemetry_event_text(&self) -> Option<&'static str> {
+            None
+        }
+
         fn tab_content(
             &self,
             detail: Option<usize>,

crates/workspace/src/shared_screen.rs 🔗

@@ -111,6 +111,10 @@ impl Item for SharedScreen {
             .into_any()
     }
 
+    fn telemetry_event_text(&self) -> Option<&'static str> {
+        None
+    }
+
     fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
         self.nav_history = Some(history);
     }

crates/workspace/src/workspace.rs 🔗

@@ -1271,7 +1271,9 @@ impl Workspace {
     }
 
     pub fn open(&mut self, _: &Open, cx: &mut ViewContext<Self>) {
-        self.client().telemetry().report_app_event("open project");
+        self.client()
+            .telemetry()
+            .report_app_event("open project".to_string());
         let paths = cx.prompt_for_paths(PathPromptOptions {
             files: true,
             directories: true,
@@ -1776,6 +1778,12 @@ impl Workspace {
     }
 
     pub fn add_item(&mut self, item: Box<dyn ItemHandle>, cx: &mut ViewContext<Self>) {
+        if let Some(text) = item.telemetry_event_text(cx) {
+            self.client()
+                .telemetry()
+                .report_app_event(format!("{}: open", text));
+        }
+
         self.active_pane
             .update(cx, |pane, cx| pane.add_item(item, true, true, None, cx));
     }

crates/zed/src/main.rs 🔗

@@ -176,10 +176,13 @@ fn main() {
         telemetry.start(installation_id, session_id, cx);
         telemetry.report_setting_event("theme", cx.theme().name.to_string());
         telemetry.report_setting_event("keymap", BaseKeymap::get_global(cx).to_string());
-        telemetry.report_app_event(match existing_installation_id_found {
-            Some(false) => "first open",
-            _ => "open",
-        });
+        telemetry.report_app_event(
+            match existing_installation_id_found {
+                Some(false) => "first open",
+                _ => "open",
+            }
+            .to_string(),
+        );
         telemetry.flush_events();
 
         let app_state = Arc::new(AppState {