Add opt-out for metric reporting
co-authored-by: kay <kay@zed.dev>
This commit is contained in:
parent
866f0e1344
commit
37a4de1a84
6 changed files with 76 additions and 19 deletions
|
@ -25,6 +25,7 @@ use postage::watch;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rpc::proto::{AnyTypedEnvelope, EntityMessage, EnvelopedMessage, PeerId, RequestMessage};
|
use rpc::proto::{AnyTypedEnvelope, EntityMessage, EnvelopedMessage, PeerId, RequestMessage};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use settings::{Settings, TelemetrySettings};
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -423,7 +424,9 @@ impl Client {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Status::SignedOut | Status::UpgradeRequired => {
|
Status::SignedOut | Status::UpgradeRequired => {
|
||||||
self.telemetry.set_authenticated_user_info(None, false);
|
let telemetry_settings = cx.read(|cx| cx.global::<Settings>().telemetry());
|
||||||
|
self.telemetry
|
||||||
|
.set_authenticated_user_info(None, false, telemetry_settings);
|
||||||
state._reconnect_task.take();
|
state._reconnect_task.take();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -706,7 +709,13 @@ impl Client {
|
||||||
credentials = read_credentials_from_keychain(cx);
|
credentials = read_credentials_from_keychain(cx);
|
||||||
read_from_keychain = credentials.is_some();
|
read_from_keychain = credentials.is_some();
|
||||||
if read_from_keychain {
|
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::<Settings>().telemetry(),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if credentials.is_none() {
|
if credentials.is_none() {
|
||||||
|
@ -997,6 +1006,8 @@ impl Client {
|
||||||
let executor = cx.background();
|
let executor = cx.background();
|
||||||
let telemetry = self.telemetry.clone();
|
let telemetry = self.telemetry.clone();
|
||||||
let http = self.http.clone();
|
let http = self.http.clone();
|
||||||
|
let metrics_enabled = cx.read(|cx| cx.global::<Settings>().telemetry());
|
||||||
|
|
||||||
executor.clone().spawn(async move {
|
executor.clone().spawn(async move {
|
||||||
// Generate a pair of asymmetric encryption keys. The public key will be used by the
|
// 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
|
// 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")?;
|
.context("failed to decrypt access token")?;
|
||||||
platform.activate(true);
|
platform.activate(true);
|
||||||
|
|
||||||
telemetry.report_event("authenticate with browser", Default::default());
|
telemetry.report_event(
|
||||||
|
"authenticate with browser",
|
||||||
|
Default::default(),
|
||||||
|
metrics_enabled,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(Credentials {
|
Ok(Credentials {
|
||||||
user_id: user_id.parse()?,
|
user_id: user_id.parse()?,
|
||||||
|
@ -1287,8 +1302,14 @@ impl Client {
|
||||||
self.telemetry.start();
|
self.telemetry.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_event(&self, kind: &str, properties: Value) {
|
pub fn report_event(
|
||||||
self.telemetry.report_event(kind, properties.clone());
|
&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<PathBuf> {
|
pub fn telemetry_log_file_path(&self) -> Option<PathBuf> {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use lazy_static::lazy_static;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use settings::TelemetrySettings;
|
||||||
use std::{
|
use std::{
|
||||||
io::Write,
|
io::Write,
|
||||||
mem,
|
mem,
|
||||||
|
@ -184,11 +185,18 @@ impl Telemetry {
|
||||||
.detach();
|
.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(
|
pub fn set_authenticated_user_info(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
metrics_id: Option<String>,
|
metrics_id: Option<String>,
|
||||||
is_staff: bool,
|
is_staff: bool,
|
||||||
|
telemetry_settings: TelemetrySettings,
|
||||||
) {
|
) {
|
||||||
|
if !telemetry_settings.metrics() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
let mut state = self.state.lock();
|
let mut state = self.state.lock();
|
||||||
let device_id = state.device_id.clone();
|
let device_id = state.device_id.clone();
|
||||||
|
@ -221,7 +229,16 @@ impl Telemetry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_event(self: &Arc<Self>, kind: &str, properties: Value) {
|
pub fn report_event(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
kind: &str,
|
||||||
|
properties: Value,
|
||||||
|
telemetry_settings: TelemetrySettings,
|
||||||
|
) {
|
||||||
|
if !telemetry_settings.metrics() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut state = self.state.lock();
|
let mut state = self.state.lock();
|
||||||
let event = MixpanelEvent {
|
let event = MixpanelEvent {
|
||||||
event: kind.to_string(),
|
event: kind.to_string(),
|
||||||
|
|
|
@ -5,6 +5,7 @@ use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt};
|
||||||
use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
|
use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
|
||||||
use postage::{sink::Sink, watch};
|
use postage::{sink::Sink, watch};
|
||||||
use rpc::proto::{RequestMessage, UsersResponse};
|
use rpc::proto::{RequestMessage, UsersResponse};
|
||||||
|
use settings::Settings;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use util::TryFutureExt as _;
|
use util::TryFutureExt as _;
|
||||||
|
|
||||||
|
@ -141,14 +142,11 @@ impl UserStore {
|
||||||
let fetch_metrics_id =
|
let fetch_metrics_id =
|
||||||
client.request(proto::GetPrivateUserInfo {}).log_err();
|
client.request(proto::GetPrivateUserInfo {}).log_err();
|
||||||
let (user, info) = futures::join!(fetch_user, fetch_metrics_id);
|
let (user, info) = futures::join!(fetch_user, fetch_metrics_id);
|
||||||
if let Some(info) = info {
|
|
||||||
client.telemetry.set_authenticated_user_info(
|
client.telemetry.set_authenticated_user_info(
|
||||||
Some(info.metrics_id.clone()),
|
info.as_ref().map(|info| info.metrics_id.clone()),
|
||||||
info.staff,
|
info.as_ref().map(|info| info.staff).unwrap_or(false),
|
||||||
|
cx.read(|cx| cx.global::<Settings>().telemetry()),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
client.telemetry.set_authenticated_user_info(None, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_user_tx.send(user).await.ok();
|
current_user_tx.send(user).await.ok();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6087,10 +6087,11 @@ impl Editor {
|
||||||
let extension = Path::new(file.file_name(cx))
|
let extension = Path::new(file.file_name(cx))
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|e| e.to_str());
|
.and_then(|e| e.to_str());
|
||||||
project
|
project.read(cx).client().report_event(
|
||||||
.read(cx)
|
name,
|
||||||
.client()
|
json!({ "File Extension": extension }),
|
||||||
.report_event(name, json!({ "File Extension": extension }));
|
cx.global::<Settings>().telemetry(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,15 @@ pub struct TelemetrySettings {
|
||||||
metrics: Option<bool>,
|
metrics: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)]
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct FeatureFlags {
|
pub struct FeatureFlags {
|
||||||
pub experimental_themes: bool,
|
pub experimental_themes: bool,
|
||||||
|
@ -503,6 +512,13 @@ impl Settings {
|
||||||
.unwrap_or_else(|| R::default())
|
.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 {
|
pub fn telemetry_diagnostics(&self) -> bool {
|
||||||
self.telemetry_overrides
|
self.telemetry_overrides
|
||||||
.diagnostics
|
.diagnostics
|
||||||
|
|
|
@ -148,7 +148,11 @@ fn main() {
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
client.start_telemetry();
|
client.start_telemetry();
|
||||||
client.report_event("start app", Default::default());
|
client.report_event(
|
||||||
|
"start app",
|
||||||
|
Default::default(),
|
||||||
|
cx.global::<Settings>().telemetry(),
|
||||||
|
);
|
||||||
|
|
||||||
let app_state = Arc::new(AppState {
|
let app_state = Arc::new(AppState {
|
||||||
languages,
|
languages,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue