From fd7a133d001fa2c50484192276d6ec35ed841e09 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Sun, 15 Jun 2025 17:00:34 -0400 Subject: [PATCH] Include .NET project identification in telemetry (#32769) With Windows support on the horizon this year, we'll want to know how much .NET dev happens in Zed, so we can know how to prioritize bug fixes or enhancements to the dev experience in this framework. Release Notes: - N/A --- Cargo.lock | 1 + crates/client/Cargo.toml | 1 + crates/client/src/telemetry.rs | 42 +++++++++++++++++++--------------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25b86632c8..1caf667130 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2834,6 +2834,7 @@ dependencies = [ "paths", "postage", "rand 0.8.5", + "regex", "release_channel", "rpc", "rustls-pki-types", diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 0516670d7e..9902813880 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -39,6 +39,7 @@ paths.workspace = true parking_lot.workspace = true postage.workspace = true rand.workspace = true +regex.workspace = true release_channel.workspace = true rpc = { workspace = true, features = ["gpui"] } schemars.workspace = true diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 6510cf6e3c..3c2f623940 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -8,10 +8,11 @@ use futures::{Future, FutureExt, StreamExt}; use gpui::{App, AppContext as _, BackgroundExecutor, Task}; use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request}; use parking_lot::Mutex; +use regex::Regex; use release_channel::ReleaseChannel; use settings::{Settings, SettingsStore}; use sha2::{Digest, Sha256}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::fs::File; use std::io::Write; use std::sync::LazyLock; @@ -45,7 +46,7 @@ struct TelemetryState { first_event_date_time: Option, event_coalescer: EventCoalescer, max_queue_size: usize, - worktree_id_map: WorktreeIdMap, + project_marker_patterns: ProjectMarkerPatterns, os_name: String, app_version: String, @@ -53,7 +54,7 @@ struct TelemetryState { } #[derive(Debug)] -struct WorktreeIdMap(HashMap); +struct ProjectMarkerPatterns(Vec<(Regex, ProjectCache)>); #[derive(Debug)] struct ProjectCache { @@ -194,20 +195,27 @@ impl Telemetry { first_event_date_time: None, event_coalescer: EventCoalescer::new(clock.clone()), max_queue_size: MAX_QUEUE_LEN, - worktree_id_map: WorktreeIdMap(HashMap::from_iter([ + project_marker_patterns: ProjectMarkerPatterns(vec![ ( - "pnpm-lock.yaml".to_string(), + Regex::new(r"^pnpm-lock\.yaml$").unwrap(), ProjectCache::new("pnpm".to_string()), ), ( - "yarn.lock".to_string(), + Regex::new(r"^yarn\.lock$").unwrap(), ProjectCache::new("yarn".to_string()), ), ( - "package.json".to_string(), + Regex::new(r"^package\.json$").unwrap(), ProjectCache::new("node".to_string()), ), - ])), + ( + Regex::new( + r"^(global\.json|Directory\.Build\.props|.*\.(csproj|fsproj|vbproj|sln))$", + ) + .unwrap(), + ProjectCache::new("dotnet".to_string()), + ), + ]), os_version: None, os_name: os_name(), @@ -379,14 +387,11 @@ impl Telemetry { let project_type_names: Vec = { let mut state = self.state.lock(); state - .worktree_id_map + .project_marker_patterns .0 .iter_mut() - .filter_map(|(project_file_name, project_type_telemetry)| { - if project_type_telemetry - .worktree_ids_reported - .contains(&worktree_id) - { + .filter_map(|(pattern, project_cache)| { + if project_cache.worktree_ids_reported.contains(&worktree_id) { return None; } @@ -394,7 +399,7 @@ impl Telemetry { path.as_ref() .file_name() .and_then(|name| name.to_str()) - .map(|name_str| name_str == project_file_name) + .map(|name_str| pattern.is_match(name_str)) .unwrap_or(false) }); @@ -402,11 +407,9 @@ impl Telemetry { return None; } - project_type_telemetry - .worktree_ids_reported - .insert(worktree_id); + project_cache.worktree_ids_reported.insert(worktree_id); - Some(project_type_telemetry.name.clone()) + Some(project_cache.name.clone()) }) .collect() }; @@ -578,6 +581,7 @@ mod tests { use clock::FakeSystemClock; use gpui::TestAppContext; use http_client::FakeHttpClient; + use std::collections::HashMap; use telemetry_events::FlexibleEvent; #[gpui::test]