Detailed changes
@@ -340,22 +340,35 @@ impl Telemetry {
}
pub fn log_edit_event(self: &Arc<Self>, environment: &'static str, is_via_ssh: bool) {
+ static LAST_EVENT_TIME: Mutex<Option<Instant>> = Mutex::new(None);
+
let mut state = self.state.lock();
let period_data = state.event_coalescer.log_event(environment);
drop(state);
- if let Some((start, end, environment)) = period_data {
- let duration = end
- .saturating_duration_since(start)
- .min(Duration::from_secs(60 * 60 * 24))
- .as_millis() as i64;
+ if let Some(mut last_event) = LAST_EVENT_TIME.try_lock() {
+ let current_time = std::time::Instant::now();
+ let last_time = last_event.get_or_insert(current_time);
- telemetry::event!(
- "Editor Edited",
- duration = duration,
- environment = environment,
- is_via_ssh = is_via_ssh
- );
+ if current_time.duration_since(*last_time) > Duration::from_secs(60 * 10) {
+ *last_time = current_time;
+ } else {
+ return;
+ }
+
+ if let Some((start, end, environment)) = period_data {
+ let duration = end
+ .saturating_duration_since(start)
+ .min(Duration::from_secs(60 * 60 * 24))
+ .as_millis() as i64;
+
+ telemetry::event!(
+ "Editor Edited",
+ duration = duration,
+ environment = environment,
+ is_via_ssh = is_via_ssh
+ );
+ }
}
}
@@ -250,6 +250,24 @@ pub type RenderDiffHunkControlsFn = Arc<
) -> AnyElement,
>;
+enum ReportEditorEvent {
+ Saved { auto_saved: bool },
+ EditorOpened,
+ ZetaTosClicked,
+ Closed,
+}
+
+impl ReportEditorEvent {
+ pub fn event_type(&self) -> &'static str {
+ match self {
+ Self::Saved { .. } => "Editor Saved",
+ Self::EditorOpened => "Editor Opened",
+ Self::ZetaTosClicked => "Edit Prediction Provider ToS Clicked",
+ Self::Closed => "Editor Closed",
+ }
+ }
+}
+
struct InlineValueCache {
enabled: bool,
inlays: Vec<InlayId>,
@@ -2325,7 +2343,7 @@ impl Editor {
}
if editor.mode.is_full() {
- editor.report_editor_event("Editor Opened", None, cx);
+ editor.report_editor_event(ReportEditorEvent::EditorOpened, None, cx);
}
editor
@@ -9124,7 +9142,7 @@ impl Editor {
.on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
.on_click(cx.listener(|this, _event, window, cx| {
cx.stop_propagation();
- this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
+ this.report_editor_event(ReportEditorEvent::ZetaTosClicked, None, cx);
window.dispatch_action(
zed_actions::OpenZedPredictOnboarding.boxed_clone(),
cx,
@@ -20547,7 +20565,7 @@ impl Editor {
fn report_editor_event(
&self,
- event_type: &'static str,
+ reported_event: ReportEditorEvent,
file_extension: Option<String>,
cx: &App,
) {
@@ -20581,15 +20599,30 @@ impl Editor {
.show_edit_predictions;
let project = project.read(cx);
- telemetry::event!(
- event_type,
- file_extension,
- vim_mode,
- copilot_enabled,
- copilot_enabled_for_language,
- edit_predictions_provider,
- is_via_ssh = project.is_via_ssh(),
- );
+ let event_type = reported_event.event_type();
+
+ if let ReportEditorEvent::Saved { auto_saved } = reported_event {
+ telemetry::event!(
+ event_type,
+ type = if auto_saved {"autosave"} else {"manual"},
+ file_extension,
+ vim_mode,
+ copilot_enabled,
+ copilot_enabled_for_language,
+ edit_predictions_provider,
+ is_via_ssh = project.is_via_ssh(),
+ );
+ } else {
+ telemetry::event!(
+ event_type,
+ file_extension,
+ vim_mode,
+ copilot_enabled,
+ copilot_enabled_for_language,
+ edit_predictions_provider,
+ is_via_ssh = project.is_via_ssh(),
+ );
+ };
}
/// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
@@ -1,7 +1,7 @@
use crate::{
Anchor, Autoscroll, Editor, EditorEvent, EditorSettings, ExcerptId, ExcerptRange, FormatTarget,
- MultiBuffer, MultiBufferSnapshot, NavigationData, SearchWithinRange, SelectionEffects,
- ToPoint as _,
+ MultiBuffer, MultiBufferSnapshot, NavigationData, ReportEditorEvent, SearchWithinRange,
+ SelectionEffects, ToPoint as _,
display_map::HighlightKey,
editor_settings::SeedQuerySetting,
persistence::{DB, SerializedEditor},
@@ -776,6 +776,10 @@ impl Item for Editor {
}
}
+ fn on_removed(&self, cx: &App) {
+ self.report_editor_event(ReportEditorEvent::Closed, None, cx);
+ }
+
fn deactivated(&mut self, _: &mut Window, cx: &mut Context<Self>) {
let selection = self.selections.newest_anchor();
self.push_to_nav_history(selection.head(), None, true, false, cx);
@@ -815,9 +819,9 @@ impl Item for Editor {
) -> Task<Result<()>> {
// Add meta data tracking # of auto saves
if options.autosave {
- self.report_editor_event("Editor Autosaved", None, cx);
+ self.report_editor_event(ReportEditorEvent::Saved { auto_saved: true }, None, cx);
} else {
- self.report_editor_event("Editor Saved", None, cx);
+ self.report_editor_event(ReportEditorEvent::Saved { auto_saved: false }, None, cx);
}
let buffers = self.buffer().clone().read(cx).all_buffers();
@@ -896,7 +900,11 @@ impl Item for Editor {
.path
.extension()
.map(|a| a.to_string_lossy().to_string());
- self.report_editor_event("Editor Saved", file_extension, cx);
+ self.report_editor_event(
+ ReportEditorEvent::Saved { auto_saved: false },
+ file_extension,
+ cx,
+ );
project.update(cx, |project, cx| project.save_buffer_as(buffer, path, cx))
}
@@ -997,12 +1005,16 @@ impl Item for Editor {
) {
self.workspace = Some((workspace.weak_handle(), workspace.database_id()));
if let Some(workspace) = &workspace.weak_handle().upgrade() {
- cx.subscribe(&workspace, |editor, _, event: &workspace::Event, _cx| {
- if matches!(event, workspace::Event::ModalOpened) {
- editor.mouse_context_menu.take();
- editor.inline_blame_popover.take();
- }
- })
+ cx.subscribe(
+ &workspace,
+ |editor, _, event: &workspace::Event, _cx| match event {
+ workspace::Event::ModalOpened => {
+ editor.mouse_context_menu.take();
+ editor.inline_blame_popover.take();
+ }
+ _ => {}
+ },
+ )
.detach();
}
}
@@ -1118,15 +1118,17 @@ impl ExtensionStore {
extensions_to_unload.len() - reload_count
);
- for extension_id in &extensions_to_load {
- if let Some(extension) = new_index.extensions.get(extension_id) {
- telemetry::event!(
- "Extension Loaded",
- extension_id,
- version = extension.manifest.version
- );
- }
- }
+ let extension_ids = extensions_to_load
+ .iter()
+ .filter_map(|id| {
+ Some((
+ id.clone(),
+ new_index.extensions.get(id)?.manifest.version.clone(),
+ ))
+ })
+ .collect::<Vec<_>>();
+
+ telemetry::event!("Extensions Loaded", id_and_versions = extension_ids);
let themes_to_remove = old_index
.themes
@@ -293,6 +293,7 @@ pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
fn deactivated(&mut self, _window: &mut Window, _: &mut Context<Self>) {}
fn discarded(&self, _project: Entity<Project>, _window: &mut Window, _cx: &mut Context<Self>) {}
+ fn on_removed(&self, _cx: &App) {}
fn workspace_deactivated(&mut self, _window: &mut Window, _: &mut Context<Self>) {}
fn navigate(&mut self, _: Box<dyn Any>, _window: &mut Window, _: &mut Context<Self>) -> bool {
false
@@ -532,6 +533,7 @@ pub trait ItemHandle: 'static + Send {
);
fn deactivated(&self, window: &mut Window, cx: &mut App);
fn discarded(&self, project: Entity<Project>, window: &mut Window, cx: &mut App);
+ fn on_removed(&self, cx: &App);
fn workspace_deactivated(&self, window: &mut Window, cx: &mut App);
fn navigate(&self, data: Box<dyn Any>, window: &mut Window, cx: &mut App) -> bool;
fn item_id(&self) -> EntityId;
@@ -968,6 +970,10 @@ impl<T: Item> ItemHandle for Entity<T> {
self.update(cx, |this, cx| this.deactivated(window, cx));
}
+ fn on_removed(&self, cx: &App) {
+ self.read(cx).on_removed(cx);
+ }
+
fn workspace_deactivated(&self, window: &mut Window, cx: &mut App) {
self.update(cx, |this, cx| this.workspace_deactivated(window, cx));
}
@@ -1829,6 +1829,7 @@ impl Pane {
let mode = self.nav_history.mode();
self.nav_history.set_mode(NavigationMode::ClosingItem);
item.deactivated(window, cx);
+ item.on_removed(cx);
self.nav_history.set_mode(mode);
if self.is_active_preview_item(item.item_id()) {