83 lines
3.1 KiB
Rust
83 lines
3.1 KiB
Rust
use crate::config::{analytics_id, analytics_api_key};
|
|
use chrono::Datelike;
|
|
use chrono::Timelike;
|
|
use reqwest::header::{ACCEPT, CONTENT_TYPE};
|
|
use serde_json::{json, Value};
|
|
use std::{
|
|
env,
|
|
time::{SystemTime, UNIX_EPOCH},
|
|
};
|
|
|
|
pub fn track(
|
|
event_name: String,
|
|
description: String,
|
|
ws_addr_string: &str,
|
|
event_properties: Value,
|
|
) {
|
|
println!("{}", description);
|
|
|
|
let firebase_app_id = analytics_id(ws_addr_string);
|
|
let firebase_api_key = analytics_api_key(ws_addr_string);
|
|
if firebase_app_id.is_empty() {
|
|
return;
|
|
}
|
|
let local_now = chrono::offset::Local::now();
|
|
|
|
// For tracking events, we use the Firebase Measurement Protocol
|
|
// Firebase is mostly designed for mobile and web apps, but for our use case of a CLI,
|
|
// we can use the Measurement Protocol to track events by POST to a URL.
|
|
// The only thing that may be unexpected is that the URL we use includes a firebase key
|
|
|
|
// Firebase format for properties for Mesurement protocol:
|
|
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=firebase#payload
|
|
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=firebase#payload_query_parameters
|
|
let mut properties = json!({
|
|
"time": SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(),
|
|
// app_instance_id is the standard key Firebase uses this key to track the same user across sessions
|
|
// It is a bit redundant, but I wanted to keep the recommended format Firebase uses to minimize surprises
|
|
// I still left the distinct_id key as well for backwards compatibility
|
|
"app_instance_id": event_properties["prover_id"],
|
|
"distinct_id": event_properties["prover_id"],
|
|
"prover_type": "volunteer",
|
|
"client_type": "cli",
|
|
"operating_system": env::consts::OS,
|
|
"time_zone": iana_time_zone::get_timezone().unwrap(),
|
|
"local_hour": local_now.hour(),
|
|
"local_weekday_number_from_monday": local_now.weekday().number_from_monday(),
|
|
"ws_addr_string": ws_addr_string,
|
|
});
|
|
for (k, v) in event_properties.as_object().unwrap() {
|
|
properties[k] = v.clone();
|
|
}
|
|
|
|
// Firebase format for events
|
|
let body = json!({
|
|
"app_instance_id": event_properties["prover_id"],
|
|
"events": [{
|
|
"name": event_name,
|
|
"params": properties
|
|
}],
|
|
});
|
|
|
|
tokio::spawn(async move {
|
|
let client = reqwest::Client::new();
|
|
|
|
let _ = client
|
|
//URL is the google analytics endpoint for firebase: https://stackoverflow.com/questions/50355752/firebase-analytics-from-remote-rest-api
|
|
.post(format!(
|
|
"https://www.google-analytics.com/mp/collect?firebase_app_id={}&api_secret={}",
|
|
firebase_app_id,
|
|
firebase_api_key
|
|
))
|
|
.body(format!("[{}]", body))
|
|
.header(ACCEPT, "text/plain")
|
|
.header(CONTENT_TYPE, "application/json")
|
|
.send()
|
|
.await
|
|
.unwrap()
|
|
.text()
|
|
.await
|
|
.unwrap();
|
|
});
|
|
}
|