From b1cbcc6d264f5dc7f49fef983ef167b330028e06 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Wed, 15 Dec 2021 14:42:42 -0500 Subject: [PATCH] feat: implement telemetry helpers --- src/frontend/telemetry.rs | 114 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/frontend/telemetry.rs diff --git a/src/frontend/telemetry.rs b/src/frontend/telemetry.rs new file mode 100644 index 000000000..92d05f763 --- /dev/null +++ b/src/frontend/telemetry.rs @@ -0,0 +1,114 @@ +use segment::{HttpClient, Client, message::{Track, User, Message}}; +use mac_address::get_mac_address; +use clarity_repl::clarity::util::hash::{bytes_to_hex, Hash160}; + +use crate::publish::Network; + +pub enum DeveloperUsageEvent { + NewProject(DeveloperUsageDigest), + PokeExecuted(DeveloperUsageDigest), + CheckExecuted(DeveloperUsageDigest), + TestSuiteExecuted(DeveloperUsageDigest, bool, u32), + DevnetExecuted(DeveloperUsageDigest), + ContractPublished(DeveloperUsageDigest, Network), + UnknownCommand(DeveloperUsageDigest, String) +} + +pub struct DeveloperUsageDigest { + pub project_id: String, + pub team_id: String, +} + +impl DeveloperUsageDigest { + + pub fn new(project_id: &str, team_id: &Vec) -> Self { + let hashed_project_id = Hash160::from_data(project_id.as_bytes()); + let hashed_team_id = Hash160::from_data(team_id.join(",").as_bytes()); + Self { + project_id: format!("0x{}", bytes_to_hex(&hashed_project_id.to_bytes().to_vec())), + team_id: format!("0x{}", bytes_to_hex(&hashed_team_id.to_bytes().to_vec())), + } + } +} + + +pub fn telemetry_report_event(event: DeveloperUsageEvent) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .max_blocking_threads(32) + .build() + .unwrap(); + + rt.block_on(send_event(event)); +} + +async fn send_event(event: DeveloperUsageEvent) { + let segment_api_key = ""; + + let clarinet_version = option_env!("CARGO_PKG_VERSION").expect("Unable to detect version").to_string(); + let ci_mode = option_env!("CLARINET_MODE_CI").unwrap_or("0").to_string(); + + let (event_name, properties) = match event { + DeveloperUsageEvent::NewProject(digest) => ("NewProject", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + })), + DeveloperUsageEvent::TestSuiteExecuted(digest, success, count) => ("TestSuiteExecuted", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + "success": success, + "count": count, + })), + DeveloperUsageEvent::DevnetExecuted(digest) => ("DevnetExecuted", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + })), + DeveloperUsageEvent::ContractPublished(digest, network) => ("ContractPublished", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + "network": format!("{:?}", network), + })), + DeveloperUsageEvent::CheckExecuted(digest) => ("CheckExecuted", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + })), + DeveloperUsageEvent::PokeExecuted(digest) => ("PokeExecuted", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + })), + DeveloperUsageEvent::UnknownCommand(digest, command) => ("UnknownCommand", json!({ + "project_id": digest.project_id, + "team_id": digest.team_id, + "clarinet_version": clarinet_version, + "ci_mode": ci_mode, + })), + }; + + let user_id = match get_mac_address() { + Ok(Some(ma)) => Hash160::from_data(&ma.bytes()), + Ok(None) => Hash160::from_data(&[0]), + Err(e) => return + }; + + let client = HttpClient::default(); + + let _ = client.send(segment_api_key.to_string(), Message::from(Track { + user: User::UserId { user_id: format!("0x{}", bytes_to_hex(&user_id.to_bytes().to_vec())) }, + event: event_name.into(), + properties: properties, + ..Default::default() + })).await; +} \ No newline at end of file