Merge pull request #1680 from zed-industries/telemetry-tweaks

Max Brunsfeld created

Telemetry tweaks

Change summary

crates/client/src/client.rs                 |  2 
crates/client/src/telemetry.rs              | 44 ++++++++++++++++------
crates/client/src/test.rs                   |  1 
crates/client/src/user.rs                   |  9 ++++
crates/collab/src/rpc.rs                    | 11 +++++
crates/contacts_panel/src/contacts_panel.rs | 10 -----
crates/rpc/proto/zed.proto                  |  1 
7 files changed, 52 insertions(+), 26 deletions(-)

Detailed changes

crates/client/src/client.rs 🔗

@@ -351,7 +351,7 @@ impl Client {
                 }));
             }
             Status::SignedOut | Status::UpgradeRequired => {
-                self.telemetry.set_metrics_id(None);
+                self.telemetry.set_authenticated_user_info(None, false);
                 state._reconnect_task.take();
             }
             _ => {}

crates/client/src/telemetry.rs 🔗

@@ -9,6 +9,7 @@ use isahc::Request;
 use lazy_static::lazy_static;
 use parking_lot::Mutex;
 use serde::Serialize;
+use serde_json::json;
 use std::{
     io::Write,
     mem,
@@ -52,12 +53,6 @@ lazy_static! {
 struct AmplitudeEventBatch {
     api_key: &'static str,
     events: Vec<AmplitudeEvent>,
-    options: AmplitudeEventBatchOptions,
-}
-
-#[derive(Serialize)]
-struct AmplitudeEventBatchOptions {
-    min_id_length: usize,
 }
 
 #[derive(Serialize)]
@@ -73,6 +68,7 @@ struct AmplitudeEvent {
     os_name: &'static str,
     os_version: Option<Arc<str>>,
     app_version: Option<Arc<str>>,
+    platform: &'static str,
     event_id: usize,
     session_id: u128,
     time: u128,
@@ -176,11 +172,32 @@ impl Telemetry {
             .detach();
     }
 
-    pub fn set_metrics_id(&self, metrics_id: Option<String>) {
+    pub fn set_authenticated_user_info(
+        self: &Arc<Self>,
+        metrics_id: Option<String>,
+        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<Self>, kind: &str, properties: Value) {
+        self.report_event_with_user_properties(kind, properties, Default::default());
+    }
+
+    fn report_event_with_user_properties(
+        self: &Arc<Self>,
+        kind: &str,
+        properties: Value,
+        user_properties: Value,
+    ) {
         if AMPLITUDE_API_KEY.is_none() {
             return;
         }
@@ -198,10 +215,15 @@ impl Telemetry {
             } else {
                 None
             },
-            user_properties: 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(),
             event_id: post_inc(&mut state.next_event_id),
@@ -245,11 +267,7 @@ impl Telemetry {
                             }
                         }
 
-                        let batch = AmplitudeEventBatch {
-                            api_key,
-                            events,
-                            options: AmplitudeEventBatchOptions { min_id_length: 1 },
-                        };
+                        let batch = AmplitudeEventBatch { api_key, events };
                         json_bytes.clear();
                         serde_json::to_writer(&mut json_bytes, &batch)?;
                         let request =

crates/client/src/test.rs 🔗

@@ -157,6 +157,7 @@ impl FakeServer {
                         .receipt(),
                     GetPrivateUserInfoResponse {
                         metrics_id: "the-metrics-id".into(),
+                        staff: false,
                     },
                 )
                 .await;

crates/client/src/user.rs 🔗

@@ -148,7 +148,14 @@ impl UserStore {
                                 let fetch_metrics_id =
                                     client.request(proto::GetPrivateUserInfo {}).log_err();
                                 let (user, info) = futures::join!(fetch_user, fetch_metrics_id);
-                                client.telemetry.set_metrics_id(info.map(|i| i.metrics_id));
+                                if let Some(info) = info {
+                                    client.telemetry.set_authenticated_user_info(
+                                        Some(info.metrics_id),
+                                        info.staff,
+                                    );
+                                } else {
+                                    client.telemetry.set_authenticated_user_info(None, false);
+                                }
                                 client.telemetry.report_event("sign in", Default::default());
                                 current_user_tx.send(user).await.ok();
                             }

crates/collab/src/rpc.rs 🔗

@@ -1738,7 +1738,16 @@ impl Server {
             .await
             .user_id_for_connection(request.sender_id)?;
         let metrics_id = self.app_state.db.get_user_metrics_id(user_id).await?;
-        response.send(proto::GetPrivateUserInfoResponse { metrics_id })?;
+        let user = self
+            .app_state
+            .db
+            .get_user_by_id(user_id)
+            .await?
+            .ok_or_else(|| anyhow!("user not found"))?;
+        response.send(proto::GetPrivateUserInfoResponse {
+            metrics_id,
+            staff: user.admin,
+        })?;
         Ok(())
     }
 

crates/contacts_panel/src/contacts_panel.rs 🔗

@@ -1221,16 +1221,6 @@ mod tests {
         let project_store = cx.add_model(|_| ProjectStore::new(project::Db::open_fake()));
         let server = FakeServer::for_client(current_user_id, &client, cx).await;
 
-        let request = server.receive::<proto::GetPrivateUserInfo>().await.unwrap();
-        server
-            .respond(
-                request.receipt(),
-                proto::GetPrivateUserInfoResponse {
-                    metrics_id: "the-metrics-id".into(),
-                },
-            )
-            .await;
-
         let fs = FakeFs::new(cx.background());
         fs.insert_tree("/private_dir", json!({ "one.rs": "" }))
             .await;

crates/rpc/proto/zed.proto 🔗

@@ -755,6 +755,7 @@ message GetPrivateUserInfo {}
 
 message GetPrivateUserInfoResponse {
     string metrics_id = 1;
+    bool staff = 2;
 }
 
 // Entities