Remove code sending zed events to mixpanel

Joseph Lyons created

Change summary

.github/workflows/ci.yml                 |   1 
.github/workflows/release_actions.yml    |  16 --
crates/client/src/client.rs              |  18 --
crates/client/src/telemetry.rs           | 202 -------------------------
crates/zed/build.rs                      |   3 
crates/zed/src/main.rs                   |   5 
script/mixpanel_release/main.py          |  30 ---
script/mixpanel_release/requirements.txt |   1 
8 files changed, 4 insertions(+), 272 deletions(-)

Detailed changes

.github/workflows/ci.yml 🔗

@@ -93,7 +93,6 @@ jobs:
       MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
       APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
       APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
-      ZED_MIXPANEL_TOKEN: ${{ secrets.ZED_MIXPANEL_TOKEN }}
     steps:
       - name: Install Rust
         run: |

.github/workflows/release_actions.yml 🔗

@@ -21,19 +21,3 @@ jobs:
 
           ${{ github.event.release.body }}
           ```
-  mixpanel_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/mixpanel_release/requirements.txt
-      - run: >
-          python script/mixpanel_release/main.py
-          ${{ github.event.release.tag_name }}
-          ${{ secrets.MIXPANEL_PROJECT_ID }}
-          ${{ secrets.MIXPANEL_SERVICE_ACCOUNT_USERNAME }}
-          ${{ secrets.MIXPANEL_SERVICE_ACCOUNT_SECRET }}

crates/client/src/client.rs 🔗

@@ -776,15 +776,6 @@ impl Client {
         if credentials.is_none() && try_keychain {
             credentials = read_credentials_from_keychain(cx);
             read_from_keychain = credentials.is_some();
-            if read_from_keychain {
-                cx.read(|cx| {
-                    self.telemetry().report_mixpanel_event(
-                        "read credentials from keychain",
-                        Default::default(),
-                        *settings::get::<TelemetrySettings>(cx),
-                    );
-                });
-            }
         }
         if credentials.is_none() {
             let mut status_rx = self.status();
@@ -1072,11 +1063,8 @@ impl Client {
     ) -> Task<Result<Credentials>> {
         let platform = cx.platform();
         let executor = cx.background();
-        let telemetry = self.telemetry.clone();
         let http = self.http.clone();
 
-        let telemetry_settings = cx.read(|cx| *settings::get::<TelemetrySettings>(cx));
-
         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
@@ -1159,12 +1147,6 @@ impl Client {
                 .context("failed to decrypt access token")?;
             platform.activate(true);
 
-            telemetry.report_mixpanel_event(
-                "authenticate with browser",
-                Default::default(),
-                telemetry_settings,
-            );
-
             Ok(Credentials {
                 user_id: user_id.parse()?,
                 access_token,

crates/client/src/telemetry.rs 🔗

@@ -1,14 +1,9 @@
 use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
 use db::kvp::KEY_VALUE_STORE;
-use gpui::{
-    executor::Background,
-    serde_json::{self, value::Map, Value},
-    AppContext, Task,
-};
+use gpui::{executor::Background, serde_json, AppContext, Task};
 use lazy_static::lazy_static;
 use parking_lot::Mutex;
 use serde::Serialize;
-use serde_json::json;
 use std::{
     env,
     io::Write,
@@ -19,7 +14,7 @@ use std::{
 };
 use tempfile::NamedTempFile;
 use util::http::HttpClient;
-use util::{channel::ReleaseChannel, post_inc, ResultExt, TryFutureExt};
+use util::{channel::ReleaseChannel, TryFutureExt};
 use uuid::Uuid;
 
 pub struct Telemetry {
@@ -37,23 +32,15 @@ struct TelemetryState {
     os_name: &'static str,
     os_version: Option<Arc<str>>,
     architecture: &'static str,
-    mixpanel_events_queue: Vec<MixpanelEvent>,
     clickhouse_events_queue: Vec<ClickhouseEventWrapper>,
-    next_mixpanel_event_id: usize,
-    flush_mixpanel_events_task: Option<Task<()>>,
     flush_clickhouse_events_task: Option<Task<()>>,
     log_file: Option<NamedTempFile>,
     is_staff: Option<bool>,
 }
 
-const MIXPANEL_EVENTS_URL: &'static str = "https://api.mixpanel.com/track";
-const MIXPANEL_ENGAGE_URL: &'static str = "https://api.mixpanel.com/engage#profile-set";
 const CLICKHOUSE_EVENTS_URL_PATH: &'static str = "/api/events";
 
 lazy_static! {
-    static ref MIXPANEL_TOKEN: Option<String> = std::env::var("ZED_MIXPANEL_TOKEN")
-        .ok()
-        .or_else(|| option_env!("ZED_MIXPANEL_TOKEN").map(|key| key.to_string()));
     static ref CLICKHOUSE_EVENTS_URL: String =
         format!("{}{}", *ZED_SERVER_URL, CLICKHOUSE_EVENTS_URL_PATH);
 }
@@ -95,47 +82,6 @@ pub enum ClickhouseEvent {
     },
 }
 
-#[derive(Serialize, Debug)]
-struct MixpanelEvent {
-    event: String,
-    properties: MixpanelEventProperties,
-}
-
-#[derive(Serialize, Debug)]
-struct MixpanelEventProperties {
-    // Mixpanel required fields
-    #[serde(skip_serializing_if = "str::is_empty")]
-    token: &'static str,
-    time: u128,
-    #[serde(rename = "distinct_id")]
-    installation_id: Option<Arc<str>>,
-    #[serde(rename = "$insert_id")]
-    insert_id: usize,
-    // Custom fields
-    #[serde(skip_serializing_if = "Option::is_none", flatten)]
-    event_properties: Option<Map<String, Value>>,
-    #[serde(rename = "OS Name")]
-    os_name: &'static str,
-    #[serde(rename = "OS Version")]
-    os_version: Option<Arc<str>>,
-    #[serde(rename = "Release Channel")]
-    release_channel: Option<&'static str>,
-    #[serde(rename = "App Version")]
-    app_version: Option<Arc<str>>,
-    #[serde(rename = "Signed In")]
-    signed_in: bool,
-}
-
-#[derive(Serialize)]
-struct MixpanelEngageRequest {
-    #[serde(rename = "$token")]
-    token: &'static str,
-    #[serde(rename = "$distinct_id")]
-    installation_id: Arc<str>,
-    #[serde(rename = "$set")]
-    set: Value,
-}
-
 #[cfg(debug_assertions)]
 const MAX_QUEUE_LEN: usize = 1;
 
@@ -168,29 +114,13 @@ impl Telemetry {
                 release_channel,
                 installation_id: None,
                 metrics_id: None,
-                mixpanel_events_queue: Default::default(),
                 clickhouse_events_queue: Default::default(),
-                flush_mixpanel_events_task: Default::default(),
                 flush_clickhouse_events_task: Default::default(),
-                next_mixpanel_event_id: 0,
                 log_file: None,
                 is_staff: None,
             }),
         });
 
-        if MIXPANEL_TOKEN.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
     }
 
@@ -218,20 +148,9 @@ impl Telemetry {
                     let mut state = this.state.lock();
                     state.installation_id = Some(installation_id.clone());
 
-                    for event in &mut state.mixpanel_events_queue {
-                        event
-                            .properties
-                            .installation_id
-                            .get_or_insert_with(|| installation_id.clone());
-                    }
-
-                    let has_mixpanel_events = !state.mixpanel_events_queue.is_empty();
                     let has_clickhouse_events = !state.clickhouse_events_queue.is_empty();
-                    drop(state);
 
-                    if has_mixpanel_events {
-                        this.flush_mixpanel_events();
-                    }
+                    drop(state);
 
                     if has_clickhouse_events {
                         this.flush_clickhouse_events();
@@ -256,37 +175,11 @@ impl Telemetry {
             return;
         }
 
-        let this = self.clone();
         let mut state = self.state.lock();
-        let installation_id = state.installation_id.clone();
         let metrics_id: Option<Arc<str>> = metrics_id.map(|id| id.into());
         state.metrics_id = metrics_id.clone();
         state.is_staff = Some(is_staff);
         drop(state);
-
-        if let Some((token, installation_id)) = MIXPANEL_TOKEN.as_ref().zip(installation_id) {
-            self.executor
-                .spawn(
-                    async move {
-                        let json_bytes = serde_json::to_vec(&[MixpanelEngageRequest {
-                            token,
-                            installation_id,
-                            set: json!({
-                                "Staff": is_staff,
-                                "ID": metrics_id,
-                                "App": true
-                            }),
-                        }])?;
-
-                        this.http_client
-                            .post_json(MIXPANEL_ENGAGE_URL, json_bytes.into())
-                            .await?;
-                        anyhow::Ok(())
-                    }
-                    .log_err(),
-                )
-                .detach();
-        }
     }
 
     pub fn report_clickhouse_event(
@@ -310,7 +203,7 @@ impl Telemetry {
         });
 
         if state.installation_id.is_some() {
-            if state.mixpanel_events_queue.len() >= MAX_QUEUE_LEN {
+            if state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN {
                 drop(state);
                 self.flush_clickhouse_events();
             } else {
@@ -324,55 +217,6 @@ impl Telemetry {
         }
     }
 
-    pub fn report_mixpanel_event(
-        self: &Arc<Self>,
-        kind: &str,
-        properties: Value,
-        telemetry_settings: TelemetrySettings,
-    ) {
-        if !telemetry_settings.metrics {
-            return;
-        }
-
-        let mut state = self.state.lock();
-        let event = MixpanelEvent {
-            event: kind.into(),
-            properties: MixpanelEventProperties {
-                token: "",
-                time: SystemTime::now()
-                    .duration_since(UNIX_EPOCH)
-                    .unwrap()
-                    .as_millis(),
-                installation_id: state.installation_id.clone(),
-                insert_id: post_inc(&mut state.next_mixpanel_event_id),
-                event_properties: if let Value::Object(properties) = properties {
-                    Some(properties)
-                } else {
-                    None
-                },
-                os_name: state.os_name,
-                os_version: state.os_version.clone(),
-                release_channel: state.release_channel,
-                app_version: state.app_version.clone(),
-                signed_in: state.metrics_id.is_some(),
-            },
-        };
-        state.mixpanel_events_queue.push(event);
-        if state.installation_id.is_some() {
-            if state.mixpanel_events_queue.len() >= MAX_QUEUE_LEN {
-                drop(state);
-                self.flush_mixpanel_events();
-            } else {
-                let this = self.clone();
-                let executor = self.executor.clone();
-                state.flush_mixpanel_events_task = Some(self.executor.spawn(async move {
-                    executor.timer(DEBOUNCE_INTERVAL).await;
-                    this.flush_mixpanel_events();
-                }));
-            }
-        }
-    }
-
     pub fn metrics_id(self: &Arc<Self>) -> Option<Arc<str>> {
         self.state.lock().metrics_id.clone()
     }
@@ -385,44 +229,6 @@ impl Telemetry {
         self.state.lock().is_staff
     }
 
-    fn flush_mixpanel_events(self: &Arc<Self>) {
-        let mut state = self.state.lock();
-        let mut events = mem::take(&mut state.mixpanel_events_queue);
-        state.flush_mixpanel_events_task.take();
-        drop(state);
-
-        if let Some(token) = MIXPANEL_TOKEN.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 &mut events {
-                                json_bytes.clear();
-                                serde_json::to_writer(&mut json_bytes, event)?;
-                                file.write_all(&json_bytes)?;
-                                file.write(b"\n")?;
-
-                                event.properties.token = token;
-                            }
-                        }
-
-                        json_bytes.clear();
-                        serde_json::to_writer(&mut json_bytes, &events)?;
-                        this.http_client
-                            .post_json(MIXPANEL_EVENTS_URL, json_bytes.into())
-                            .await?;
-                        anyhow::Ok(())
-                    }
-                    .log_err(),
-                )
-                .detach();
-        }
-    }
-
     fn flush_clickhouse_events(self: &Arc<Self>) {
         let mut state = self.state.lock();
         let mut events = mem::take(&mut state.clickhouse_events_queue);

crates/zed/build.rs 🔗

@@ -1,9 +1,6 @@
 fn main() {
     println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.15.7");
 
-    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_PREVIEW_CHANNEL") {
         println!("cargo:rustc-env=ZED_PREVIEW_CHANNEL={value}");
     }

crates/zed/src/main.rs 🔗

@@ -171,11 +171,6 @@ fn main() {
         .detach();
 
         client.telemetry().start();
-        client.telemetry().report_mixpanel_event(
-            "start app",
-            Default::default(),
-            *settings::get::<TelemetrySettings>(cx),
-        );
 
         let app_state = Arc::new(AppState {
             languages,

script/mixpanel_release/main.py 🔗

@@ -1,30 +0,0 @@
-import datetime
-import sys
-import requests
-
-def main():
-    version = sys.argv[1]
-    version = version.removeprefix("v")
-    project_id = sys.argv[2]
-    account_username = sys.argv[3]
-    account_secret = sys.argv[4]
-    
-    current_datetime = datetime.datetime.now(datetime.timezone.utc) 
-    current_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
-    
-    url = f"https://mixpanel.com/api/app/projects/{project_id}/annotations"
-    
-    payload = {
-        "date": current_datetime,
-        "description": version
-    }
-    
-    response = requests.post(
-        url, 
-        auth=(account_username, account_secret), 
-        json=payload
-    )
-
-
-if __name__ == "__main__":
-    main()