From 37a4de1a848ab9e2b0e3e0f8174b49f5454a5371 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 10 Jan 2023 15:49:54 -0800 Subject: [PATCH] Add opt-out for metric reporting co-authored-by: kay --- crates/client/src/client.rs | 31 ++++++++++++++++++++++++++----- crates/client/src/telemetry.rs | 19 ++++++++++++++++++- crates/client/src/user.rs | 14 ++++++-------- crates/editor/src/editor.rs | 9 +++++---- crates/settings/src/settings.rs | 16 ++++++++++++++++ crates/zed/src/main.rs | 6 +++++- 6 files changed, 76 insertions(+), 19 deletions(-) diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index aa46d64fcb..213b2cf042 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -25,6 +25,7 @@ use postage::watch; use rand::prelude::*; use rpc::proto::{AnyTypedEnvelope, EntityMessage, EnvelopedMessage, PeerId, RequestMessage}; use serde::Deserialize; +use settings::{Settings, TelemetrySettings}; use std::{ any::TypeId, collections::HashMap, @@ -423,7 +424,9 @@ impl Client { })); } Status::SignedOut | Status::UpgradeRequired => { - self.telemetry.set_authenticated_user_info(None, false); + let telemetry_settings = cx.read(|cx| cx.global::().telemetry()); + self.telemetry + .set_authenticated_user_info(None, false, telemetry_settings); state._reconnect_task.take(); } _ => {} @@ -706,7 +709,13 @@ impl Client { credentials = read_credentials_from_keychain(cx); read_from_keychain = credentials.is_some(); if read_from_keychain { - self.report_event("read credentials from keychain", Default::default()); + cx.read(|cx| { + self.report_event( + "read credentials from keychain", + Default::default(), + cx.global::().telemetry(), + ); + }); } } if credentials.is_none() { @@ -997,6 +1006,8 @@ impl Client { let executor = cx.background(); let telemetry = self.telemetry.clone(); let http = self.http.clone(); + let metrics_enabled = cx.read(|cx| cx.global::().telemetry()); + executor.clone().spawn(async move { // Generate a pair of asymmetric encryption keys. The public key will be used by the // zed server to encrypt the user's access token, so that it can'be intercepted by @@ -1079,7 +1090,11 @@ impl Client { .context("failed to decrypt access token")?; platform.activate(true); - telemetry.report_event("authenticate with browser", Default::default()); + telemetry.report_event( + "authenticate with browser", + Default::default(), + metrics_enabled, + ); Ok(Credentials { user_id: user_id.parse()?, @@ -1287,8 +1302,14 @@ impl Client { self.telemetry.start(); } - pub fn report_event(&self, kind: &str, properties: Value) { - self.telemetry.report_event(kind, properties.clone()); + pub fn report_event( + &self, + kind: &str, + properties: Value, + telemetry_settings: TelemetrySettings, + ) { + self.telemetry + .report_event(kind, properties.clone(), telemetry_settings); } pub fn telemetry_log_file_path(&self) -> Option { diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index ce8b713996..e5d2dad41e 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -10,6 +10,7 @@ use lazy_static::lazy_static; use parking_lot::Mutex; use serde::Serialize; use serde_json::json; +use settings::TelemetrySettings; use std::{ io::Write, mem, @@ -184,11 +185,18 @@ impl Telemetry { .detach(); } + /// This method takes the entire TelemetrySettings struct in order to force client code + /// to pull the struct out of the settings global. Do not remove! pub fn set_authenticated_user_info( self: &Arc, metrics_id: Option, is_staff: bool, + telemetry_settings: TelemetrySettings, ) { + if !telemetry_settings.metrics() { + return; + } + let this = self.clone(); let mut state = self.state.lock(); let device_id = state.device_id.clone(); @@ -221,7 +229,16 @@ impl Telemetry { } } - pub fn report_event(self: &Arc, kind: &str, properties: Value) { + pub fn report_event( + self: &Arc, + kind: &str, + properties: Value, + telemetry_settings: TelemetrySettings, + ) { + if !telemetry_settings.metrics() { + return; + } + let mut state = self.state.lock(); let event = MixpanelEvent { event: kind.to_string(), diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index 4d29669c2f..1201665571 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -5,6 +5,7 @@ use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt}; use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task}; use postage::{sink::Sink, watch}; use rpc::proto::{RequestMessage, UsersResponse}; +use settings::Settings; use std::sync::{Arc, Weak}; use util::TryFutureExt as _; @@ -141,14 +142,11 @@ impl UserStore { let fetch_metrics_id = client.request(proto::GetPrivateUserInfo {}).log_err(); let (user, info) = futures::join!(fetch_user, fetch_metrics_id); - if let Some(info) = info { - client.telemetry.set_authenticated_user_info( - Some(info.metrics_id.clone()), - info.staff, - ); - } else { - client.telemetry.set_authenticated_user_info(None, false); - } + client.telemetry.set_authenticated_user_info( + info.as_ref().map(|info| info.metrics_id.clone()), + info.as_ref().map(|info| info.staff).unwrap_or(false), + cx.read(|cx| cx.global::().telemetry()), + ); current_user_tx.send(user).await.ok(); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f11061cb84..8847c01af7 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6087,10 +6087,11 @@ impl Editor { let extension = Path::new(file.file_name(cx)) .extension() .and_then(|e| e.to_str()); - project - .read(cx) - .client() - .report_event(name, json!({ "File Extension": extension })); + project.read(cx).client().report_event( + name, + json!({ "File Extension": extension }), + cx.global::().telemetry(), + ); } } } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index dd2be6e318..e3e8516508 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -62,6 +62,15 @@ pub struct TelemetrySettings { metrics: Option, } +impl TelemetrySettings { + pub fn metrics(&self) -> bool { + self.metrics.unwrap() + } + pub fn diagnostics(&self) -> bool { + self.diagnostics.unwrap() + } +} + #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] pub struct FeatureFlags { pub experimental_themes: bool, @@ -503,6 +512,13 @@ impl Settings { .unwrap_or_else(|| R::default()) } + pub fn telemetry(&self) -> TelemetrySettings { + TelemetrySettings { + diagnostics: Some(self.telemetry_diagnostics()), + metrics: Some(self.telemetry_metrics()), + } + } + pub fn telemetry_diagnostics(&self) -> bool { self.telemetry_overrides .diagnostics diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 72115022d7..bf86bb9652 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -148,7 +148,11 @@ fn main() { .detach(); client.start_telemetry(); - client.report_event("start app", Default::default()); + client.report_event( + "start app", + Default::default(), + cx.global::().telemetry(), + ); let app_state = Arc::new(AppState { languages,