use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EventKind {
Startup,
RunSuccess,
RunCancelled,
RunHardStop,
RunFailed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TelemetryConfig {
pub enabled: bool,
pub install_id: String,
}
impl Default for TelemetryConfig {
fn default() -> Self {
Self {
enabled: false,
install_id: String::new(),
}
}
}
impl TelemetryConfig {
pub fn path(state_dir: &std::path::Path) -> PathBuf {
state_dir.join("telemetry.toml")
}
pub fn load(state_dir: &std::path::Path) -> Self {
let p = Self::path(state_dir);
if !p.exists() {
return Self::default();
}
std::fs::read_to_string(&p)
.ok()
.and_then(|s| toml::from_str(&s).ok())
.unwrap_or_default()
}
pub fn save(&self, state_dir: &std::path::Path) -> anyhow::Result<()> {
std::fs::create_dir_all(state_dir).ok();
let p = Self::path(state_dir);
std::fs::write(p, toml::to_string_pretty(self)?)?;
Ok(())
}
}
pub fn event(_state_dir: &std::path::Path, _kind: EventKind, _success: Option<bool>) {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_disabled() {
let cfg = TelemetryConfig::default();
assert!(!cfg.enabled);
assert!(cfg.install_id.is_empty());
}
#[test]
fn round_trip_through_tempdir() {
let dir = tempfile::tempdir().unwrap();
let cfg = TelemetryConfig {
enabled: false,
install_id: "abcdef".into(),
};
cfg.save(dir.path()).unwrap();
let back = TelemetryConfig::load(dir.path());
assert_eq!(back.install_id, "abcdef");
assert!(!back.enabled);
}
#[test]
fn event_is_noop_when_disabled() {
let dir = tempfile::tempdir().unwrap();
event(dir.path(), EventKind::Startup, None);
event(dir.path(), EventKind::RunSuccess, Some(true));
}
}