From 495fd151f5794d2d225bd918c687a3f465eeebcb Mon Sep 17 00:00:00 2001 From: Joseph T Lyons Date: Mon, 31 Oct 2022 19:18:03 -0400 Subject: [PATCH 1/6] Revert Amplitude's "app" name back to "platform" This was unintentional. We only want to rename the Mixpanel telemetry "platform" field to "app." We want to keep it as "platform" on Amplitude because we want to keep using Amplitude for a bit, and the event fields should be the same. --- crates/client/src/amplitude_telemetry.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/client/src/amplitude_telemetry.rs b/crates/client/src/amplitude_telemetry.rs index 4883124d28a79fbefc0243b160766d7767634f61..de17ae6e8d69e20de0053cb4a8967739572ca236 100644 --- a/crates/client/src/amplitude_telemetry.rs +++ b/crates/client/src/amplitude_telemetry.rs @@ -70,8 +70,7 @@ struct AmplitudeEvent { os_name: &'static str, os_version: Option>, app_version: Option>, - #[serde(rename = "App")] - app: &'static str, + platform: &'static str, release_channel: Option<&'static str>, event_id: usize, session_id: u128, @@ -221,7 +220,7 @@ impl AmplitudeTelemetry { user_id: state.metrics_id.clone(), device_id: state.device_id.clone(), os_name: state.os_name, - app: "Zed", + platform: "Zed", os_version: state.os_version.clone(), app_version: state.app_version.clone(), release_channel: state.release_channel, From 61f31bf0101b39136c15f01739f2defecd4f1045 Mon Sep 17 00:00:00 2001 From: Joseph T Lyons Date: Mon, 31 Oct 2022 19:18:35 -0400 Subject: [PATCH 2/6] Fill in missing "app" field names on Mixpanel events --- crates/client/src/telemetry.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 01adeccb50218d48d0dbb4836b6c15c41b12ba9a..1a0238cd0f9ee8242b79e3581d2520770c0d1346 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -32,6 +32,7 @@ pub struct Telemetry { struct TelemetryState { metrics_id: Option>, device_id: Option>, + app: &'static str, app_version: Option>, release_channel: Option<&'static str>, os_version: Option>, @@ -119,6 +120,7 @@ impl Telemetry { state: Mutex::new(TelemetryState { os_version: platform.os_version().ok().map(|v| v.to_string().into()), os_name: platform.os_name().into(), + app: "Zed", app_version: platform.app_version().ok().map(|v| v.to_string().into()), release_channel, device_id: None, @@ -239,7 +241,7 @@ impl Telemetry { release_channel: state.release_channel, app_version: state.app_version.clone(), signed_in: state.metrics_id.is_some(), - app: "Zed", + app: state.app, }, }; state.queue.push(event); From e5f096513827686561fa3b44853028bdfbb6112d Mon Sep 17 00:00:00 2001 From: Joseph T Lyons Date: Tue, 1 Nov 2022 20:36:18 -0400 Subject: [PATCH 3/6] Differentiate between first time app starts and subsequent ones --- crates/client/src/telemetry.rs | 24 +++++++++++++++++------- crates/zed/src/main.rs | 1 - 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 1a0238cd0f9ee8242b79e3581d2520770c0d1346..3aff42d3358b8dd9a8bf4ad1ba08d736ac00f449 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -157,13 +157,16 @@ impl Telemetry { self.executor .spawn( async move { - let device_id = if let Ok(Some(device_id)) = db.read_kvp("device_id") { - device_id - } else { - let device_id = Uuid::new_v4().to_string(); - db.write_kvp("device_id", &device_id)?; - device_id - }; + let (device_id, is_first_time_start) = + if let Ok(Some(device_id)) = db.read_kvp("device_id") { + (device_id, false) + } else { + let device_id = Uuid::new_v4().to_string(); + db.write_kvp("device_id", &device_id)?; + (device_id, true) + }; + + this.report_start_app(is_first_time_start); let device_id: Arc = device_id.into(); let mut state = this.state.lock(); @@ -260,6 +263,13 @@ impl Telemetry { } } + pub fn report_start_app(self: &Arc, is_first_time_start: bool) { + self.report_event( + "Start App", + json!({ "is_first_time_start": is_first_time_start }), + ) + } + fn flush(self: &Arc) { let mut state = self.state.lock(); let mut events = mem::take(&mut state.queue); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 74a38599ece2fc139328c893a2af1ec4927f5487..168152eface517825b26c17a687d77b82448f798 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -150,7 +150,6 @@ fn main() { let project_store = cx.add_model(|_| ProjectStore::new()); let db = cx.background().block(db); client.start_telemetry(db.clone()); - client.report_event("start app", Default::default()); let app_state = Arc::new(AppState { languages, From dc657a647e2c09c661a7437ad62b26f6b75895d2 Mon Sep 17 00:00:00 2001 From: Joseph T Lyons Date: Tue, 1 Nov 2022 20:49:49 -0400 Subject: [PATCH 4/6] Remove Amplitude event tracking --- .github/workflows/ci.yml | 1 - .github/workflows/release_actions.yml | 12 - crates/client/src/amplitude_telemetry.rs | 281 ---------------------- crates/client/src/client.rs | 11 - crates/client/src/user.rs | 10 - crates/zed/build.rs | 3 - script/amplitude_release/main.py | 30 --- script/amplitude_release/requirements.txt | 1 - 8 files changed, 349 deletions(-) delete mode 100644 crates/client/src/amplitude_telemetry.rs delete mode 100644 script/amplitude_release/main.py delete mode 100644 script/amplitude_release/requirements.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4eb4acc59fa3a5bc90a2ee2d823071ff8f7cfa5d..1dff0c84e927dd277d68d0b3f6e9750ba0fa4bec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,6 @@ jobs: MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }} APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }} - ZED_AMPLITUDE_API_KEY: ${{ secrets.ZED_AMPLITUDE_API_KEY }} ZED_MIXPANEL_TOKEN: ${{ secrets.ZED_MIXPANEL_TOKEN }} steps: - name: Install Rust diff --git a/.github/workflows/release_actions.yml b/.github/workflows/release_actions.yml index 7328ea3fd16b3a9de4b550ae06b55ff15d92dda7..8ee8e4121c4d628d3a88b50776e8b1a7fa65a989 100644 --- a/.github/workflows/release_actions.yml +++ b/.github/workflows/release_actions.yml @@ -20,15 +20,3 @@ jobs: ### Changelog ${{ github.event.release.body }} - ``` - amplitude_release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: "3.10.5" - architecture: "x64" - cache: "pip" - - run: pip install -r script/amplitude_release/requirements.txt - - run: python script/amplitude_release/main.py ${{ github.event.release.tag_name }} ${{ secrets.ZED_AMPLITUDE_API_KEY }} ${{ secrets.ZED_AMPLITUDE_SECRET_KEY }} diff --git a/crates/client/src/amplitude_telemetry.rs b/crates/client/src/amplitude_telemetry.rs deleted file mode 100644 index de17ae6e8d69e20de0053cb4a8967739572ca236..0000000000000000000000000000000000000000 --- a/crates/client/src/amplitude_telemetry.rs +++ /dev/null @@ -1,281 +0,0 @@ -use crate::http::HttpClient; -use db::Db; -use gpui::{ - executor::Background, - serde_json::{self, value::Map, Value}, - AppContext, Task, -}; -use isahc::Request; -use lazy_static::lazy_static; -use parking_lot::Mutex; -use serde::Serialize; -use serde_json::json; -use settings::ReleaseChannel; -use std::{ - io::Write, - mem, - path::PathBuf, - sync::Arc, - time::{Duration, SystemTime, UNIX_EPOCH}, -}; -use tempfile::NamedTempFile; -use util::{post_inc, ResultExt, TryFutureExt}; -use uuid::Uuid; - -pub struct AmplitudeTelemetry { - http_client: Arc, - executor: Arc, - session_id: u128, - state: Mutex, -} - -#[derive(Default)] -struct AmplitudeTelemetryState { - metrics_id: Option>, - device_id: Option>, - app_version: Option>, - release_channel: Option<&'static str>, - os_version: Option>, - os_name: &'static str, - queue: Vec, - next_event_id: usize, - flush_task: Option>, - log_file: Option, -} - -const AMPLITUDE_EVENTS_URL: &'static str = "https://api2.amplitude.com/batch"; - -lazy_static! { - static ref AMPLITUDE_API_KEY: Option = std::env::var("ZED_AMPLITUDE_API_KEY") - .ok() - .or_else(|| option_env!("ZED_AMPLITUDE_API_KEY").map(|key| key.to_string())); -} - -#[derive(Serialize)] -struct AmplitudeEventBatch { - api_key: &'static str, - events: Vec, -} - -#[derive(Serialize)] -struct AmplitudeEvent { - #[serde(skip_serializing_if = "Option::is_none")] - user_id: Option>, - device_id: Option>, - event_type: String, - #[serde(skip_serializing_if = "Option::is_none")] - event_properties: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - user_properties: Option>, - os_name: &'static str, - os_version: Option>, - app_version: Option>, - platform: &'static str, - release_channel: Option<&'static str>, - event_id: usize, - session_id: u128, - time: u128, -} - -#[cfg(debug_assertions)] -const MAX_QUEUE_LEN: usize = 1; - -#[cfg(not(debug_assertions))] -const MAX_QUEUE_LEN: usize = 10; - -#[cfg(debug_assertions)] -const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); - -#[cfg(not(debug_assertions))] -const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); - -impl AmplitudeTelemetry { - pub fn new(client: Arc, cx: &AppContext) -> Arc { - let platform = cx.platform(); - let release_channel = if cx.has_global::() { - Some(cx.global::().name()) - } else { - None - }; - let this = Arc::new(Self { - http_client: client, - executor: cx.background().clone(), - session_id: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis(), - state: Mutex::new(AmplitudeTelemetryState { - os_version: platform.os_version().ok().map(|v| v.to_string().into()), - os_name: platform.os_name().into(), - app_version: platform.app_version().ok().map(|v| v.to_string().into()), - release_channel, - device_id: None, - queue: Default::default(), - flush_task: Default::default(), - next_event_id: 0, - log_file: None, - metrics_id: None, - }), - }); - - if AMPLITUDE_API_KEY.is_some() { - this.executor - .spawn({ - let this = this.clone(); - async move { - if let Some(tempfile) = NamedTempFile::new().log_err() { - this.state.lock().log_file = Some(tempfile); - } - } - }) - .detach(); - } - - this - } - - pub fn log_file_path(&self) -> Option { - Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) - } - - pub fn start(self: &Arc, db: Db) { - let this = self.clone(); - self.executor - .spawn( - async move { - let device_id = if let Ok(Some(device_id)) = db.read_kvp("device_id") { - device_id - } else { - let device_id = Uuid::new_v4().to_string(); - db.write_kvp("device_id", &device_id)?; - device_id - }; - - let device_id = Some(Arc::from(device_id)); - let mut state = this.state.lock(); - state.device_id = device_id.clone(); - for event in &mut state.queue { - event.device_id = device_id.clone(); - } - if !state.queue.is_empty() { - drop(state); - this.flush(); - } - - anyhow::Ok(()) - } - .log_err(), - ) - .detach(); - } - - pub fn set_authenticated_user_info( - self: &Arc, - metrics_id: Option, - is_staff: bool, - ) { - let is_signed_in = metrics_id.is_some(); - self.state.lock().metrics_id = metrics_id.map(|s| s.into()); - if is_signed_in { - self.report_event_with_user_properties( - "$identify", - Default::default(), - json!({ "$set": { "staff": is_staff } }), - ) - } - } - - pub fn report_event(self: &Arc, kind: &str, properties: Value) { - self.report_event_with_user_properties(kind, properties, Default::default()); - } - - fn report_event_with_user_properties( - self: &Arc, - kind: &str, - properties: Value, - user_properties: Value, - ) { - if AMPLITUDE_API_KEY.is_none() { - return; - } - - let mut state = self.state.lock(); - let event = AmplitudeEvent { - event_type: kind.to_string(), - time: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis(), - session_id: self.session_id, - event_properties: if let Value::Object(properties) = properties { - Some(properties) - } else { - None - }, - user_properties: if let Value::Object(user_properties) = user_properties { - Some(user_properties) - } else { - None - }, - user_id: state.metrics_id.clone(), - device_id: state.device_id.clone(), - os_name: state.os_name, - platform: "Zed", - os_version: state.os_version.clone(), - app_version: state.app_version.clone(), - release_channel: state.release_channel, - event_id: post_inc(&mut state.next_event_id), - }; - state.queue.push(event); - if state.device_id.is_some() { - if state.queue.len() >= MAX_QUEUE_LEN { - drop(state); - self.flush(); - } else { - let this = self.clone(); - let executor = self.executor.clone(); - state.flush_task = Some(self.executor.spawn(async move { - executor.timer(DEBOUNCE_INTERVAL).await; - this.flush(); - })); - } - } - } - - fn flush(self: &Arc) { - let mut state = self.state.lock(); - let events = mem::take(&mut state.queue); - state.flush_task.take(); - drop(state); - - if let Some(api_key) = AMPLITUDE_API_KEY.as_ref() { - let this = self.clone(); - self.executor - .spawn( - async move { - let mut json_bytes = Vec::new(); - - if let Some(file) = &mut this.state.lock().log_file { - let file = file.as_file_mut(); - for event in &events { - json_bytes.clear(); - serde_json::to_writer(&mut json_bytes, event)?; - file.write_all(&json_bytes)?; - file.write(b"\n")?; - } - } - - let batch = AmplitudeEventBatch { api_key, events }; - json_bytes.clear(); - serde_json::to_writer(&mut json_bytes, &batch)?; - let request = - Request::post(AMPLITUDE_EVENTS_URL).body(json_bytes.into())?; - this.http_client.send(request).await?; - Ok(()) - } - .log_err(), - ) - .detach(); - } - } -} diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index c4a3167f83e2aefb9276454b8cf27777960c94b2..c55d5f16811fcd9b3f2d2e21950ec9542139b8bd 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -1,13 +1,11 @@ #[cfg(any(test, feature = "test-support"))] pub mod test; -pub mod amplitude_telemetry; pub mod channel; pub mod http; pub mod telemetry; pub mod user; -use amplitude_telemetry::AmplitudeTelemetry; use anyhow::{anyhow, Context, Result}; use async_recursion::async_recursion; use async_tungstenite::tungstenite::{ @@ -85,7 +83,6 @@ pub struct Client { peer: Arc, http: Arc, telemetry: Arc, - amplitude_telemetry: Arc, state: RwLock, #[allow(clippy::type_complexity)] @@ -265,7 +262,6 @@ impl Client { id: 0, peer: Peer::new(), telemetry: Telemetry::new(http.clone(), cx), - amplitude_telemetry: AmplitudeTelemetry::new(http.clone(), cx), http, state: Default::default(), @@ -378,8 +374,6 @@ impl Client { } Status::SignedOut | Status::UpgradeRequired => { self.telemetry.set_authenticated_user_info(None, false); - self.amplitude_telemetry - .set_authenticated_user_info(None, false); state._reconnect_task.take(); } _ => {} @@ -1029,7 +1023,6 @@ impl Client { let platform = cx.platform(); let executor = cx.background(); let telemetry = self.telemetry.clone(); - let amplitude_telemetry = self.amplitude_telemetry.clone(); let http = self.http.clone(); executor.clone().spawn(async move { // Generate a pair of asymmetric encryption keys. The public key will be used by the @@ -1114,7 +1107,6 @@ impl Client { platform.activate(true); telemetry.report_event("authenticate with browser", Default::default()); - amplitude_telemetry.report_event("authenticate with browser", Default::default()); Ok(Credentials { user_id: user_id.parse()?, @@ -1227,16 +1219,13 @@ impl Client { pub fn start_telemetry(&self, db: Db) { self.telemetry.start(db.clone()); - self.amplitude_telemetry.start(db); } pub fn report_event(&self, kind: &str, properties: Value) { self.telemetry.report_event(kind, properties.clone()); - self.amplitude_telemetry.report_event(kind, properties); } pub fn telemetry_log_file_path(&self) -> Option { - self.amplitude_telemetry.log_file_path(); self.telemetry.log_file_path() } } diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index d06a6682c5e0fb2589d19fa23909e0988794b9bc..11b9ef6117f09e34e4c4addf5142fbc31058dd79 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -146,21 +146,11 @@ impl UserStore { Some(info.metrics_id.clone()), info.staff, ); - client.amplitude_telemetry.set_authenticated_user_info( - Some(info.metrics_id), - info.staff, - ); } else { client.telemetry.set_authenticated_user_info(None, false); - client - .amplitude_telemetry - .set_authenticated_user_info(None, false); } client.telemetry.report_event("sign in", Default::default()); - client - .amplitude_telemetry - .report_event("sign in", Default::default()); current_user_tx.send(user).await.ok(); } } diff --git a/crates/zed/build.rs b/crates/zed/build.rs index 1f30e7ded2bc055d2f0185c0e459da583dcfb6e1..8622842c440619ecbbcc40518f483e1577859b6c 100644 --- a/crates/zed/build.rs +++ b/crates/zed/build.rs @@ -4,9 +4,6 @@ fn main() { if let Ok(value) = std::env::var("ZED_MIXPANEL_TOKEN") { println!("cargo:rustc-env=ZED_MIXPANEL_TOKEN={value}"); } - if let Ok(value) = std::env::var("ZED_AMPLITUDE_API_KEY") { - println!("cargo:rustc-env=ZED_AMPLITUDE_API_KEY={value}"); - } if let Ok(value) = std::env::var("ZED_PREVIEW_CHANNEL") { println!("cargo:rustc-env=ZED_PREVIEW_CHANNEL={value}"); } diff --git a/script/amplitude_release/main.py b/script/amplitude_release/main.py deleted file mode 100644 index 160e40b66c7c9e56380b9b18ac7cc6faaa9906ea..0000000000000000000000000000000000000000 --- a/script/amplitude_release/main.py +++ /dev/null @@ -1,30 +0,0 @@ -import datetime -import sys - -from amplitude_python_sdk.v2.clients.releases_client import ReleasesAPIClient -from amplitude_python_sdk.v2.models.releases import Release - - -def main(): - version = sys.argv[1] - version = version.removeprefix("v") - - api_key = sys.argv[2] - secret_key = sys.argv[3] - - current_datetime = datetime.datetime.now(datetime.timezone.utc) - current_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S") - - release = Release( - title=version, - version=version, - release_start=current_datetime, - created_by="GitHub Release Workflow", - chart_visibility=True - ) - - ReleasesAPIClient(api_key=api_key, secret_key=secret_key).create(release) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/script/amplitude_release/requirements.txt b/script/amplitude_release/requirements.txt deleted file mode 100644 index 7ed3ea65157f04eea2e2d9625eaf5147f7dddb9f..0000000000000000000000000000000000000000 --- a/script/amplitude_release/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -amplitude-python-sdk==0.2.0 \ No newline at end of file From aafc3a9584af1efcd3f4d42dbb74fb834c94856c Mon Sep 17 00:00:00 2001 From: Joseph T Lyons Date: Tue, 1 Nov 2022 23:19:55 -0400 Subject: [PATCH 5/6] Make event name casing consistent with other event names --- crates/client/src/telemetry.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 3aff42d3358b8dd9a8bf4ad1ba08d736ac00f449..b470dde0048e26a2de38d14eef8d871d8c5575cb 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -265,8 +265,8 @@ impl Telemetry { pub fn report_start_app(self: &Arc, is_first_time_start: bool) { self.report_event( - "Start App", - json!({ "is_first_time_start": is_first_time_start }), + "start app", + json!({ "First Time Open": is_first_time_start }), ) } From d8685baa476be3cbf811c438944e80f666f99034 Mon Sep 17 00:00:00 2001 From: Joseph T Lyons Date: Wed, 2 Nov 2022 12:22:46 -0400 Subject: [PATCH 6/6] Revert "Differentiate between first time app starts and subsequent ones" --- crates/client/src/telemetry.rs | 24 +++++++----------------- crates/zed/src/main.rs | 1 + 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index b470dde0048e26a2de38d14eef8d871d8c5575cb..1a0238cd0f9ee8242b79e3581d2520770c0d1346 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -157,16 +157,13 @@ impl Telemetry { self.executor .spawn( async move { - let (device_id, is_first_time_start) = - if let Ok(Some(device_id)) = db.read_kvp("device_id") { - (device_id, false) - } else { - let device_id = Uuid::new_v4().to_string(); - db.write_kvp("device_id", &device_id)?; - (device_id, true) - }; - - this.report_start_app(is_first_time_start); + let device_id = if let Ok(Some(device_id)) = db.read_kvp("device_id") { + device_id + } else { + let device_id = Uuid::new_v4().to_string(); + db.write_kvp("device_id", &device_id)?; + device_id + }; let device_id: Arc = device_id.into(); let mut state = this.state.lock(); @@ -263,13 +260,6 @@ impl Telemetry { } } - pub fn report_start_app(self: &Arc, is_first_time_start: bool) { - self.report_event( - "start app", - json!({ "First Time Open": is_first_time_start }), - ) - } - fn flush(self: &Arc) { let mut state = self.state.lock(); let mut events = mem::take(&mut state.queue); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 168152eface517825b26c17a687d77b82448f798..74a38599ece2fc139328c893a2af1ec4927f5487 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -150,6 +150,7 @@ fn main() { let project_store = cx.add_model(|_| ProjectStore::new()); let db = cx.background().block(db); client.start_telemetry(db.clone()); + client.report_event("start app", Default::default()); let app_state = Arc::new(AppState { languages,