From 7b9bd8b42883f82b090718175b8316296ef18236 Mon Sep 17 00:00:00 2001 From: main Date: Thu, 19 Mar 2026 10:15:18 -0400 Subject: Initial Fidget Spinner MVP --- crates/fidget-spinner-cli/src/mcp/telemetry.rs | 103 +++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 crates/fidget-spinner-cli/src/mcp/telemetry.rs (limited to 'crates/fidget-spinner-cli/src/mcp/telemetry.rs') diff --git a/crates/fidget-spinner-cli/src/mcp/telemetry.rs b/crates/fidget-spinner-cli/src/mcp/telemetry.rs new file mode 100644 index 0000000..7206f76 --- /dev/null +++ b/crates/fidget-spinner-cli/src/mcp/telemetry.rs @@ -0,0 +1,103 @@ +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; + +use crate::mcp::fault::FaultRecord; + +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct OperationTelemetry { + pub requests: u64, + pub successes: u64, + pub errors: u64, + pub retries: u64, + pub last_latency_ms: Option, +} + +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct ServerTelemetry { + pub requests: u64, + pub successes: u64, + pub errors: u64, + pub retries: u64, + pub worker_restarts: u64, + pub host_rollouts: u64, + pub last_fault: Option, + pub operations: BTreeMap, +} + +impl ServerTelemetry { + pub fn record_request(&mut self, operation: &str) { + self.requests += 1; + self.operations + .entry(operation.to_owned()) + .or_default() + .requests += 1; + } + + pub fn record_success(&mut self, operation: &str, latency_ms: u128) { + self.successes += 1; + let entry = self.operations.entry(operation.to_owned()).or_default(); + entry.successes += 1; + entry.last_latency_ms = Some(latency_ms); + } + + pub fn record_retry(&mut self, operation: &str) { + self.retries += 1; + self.operations + .entry(operation.to_owned()) + .or_default() + .retries += 1; + } + + pub fn record_error(&mut self, operation: &str, fault: FaultRecord, latency_ms: u128) { + self.errors += 1; + self.last_fault = Some(fault.clone()); + let entry = self.operations.entry(operation.to_owned()).or_default(); + entry.errors += 1; + entry.last_latency_ms = Some(latency_ms); + } + + pub fn record_worker_restart(&mut self) { + self.worker_restarts += 1; + } + + pub fn record_rollout(&mut self) { + self.host_rollouts += 1; + } +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct InitializationHealth { + pub ready: bool, + pub seed_captured: bool, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct WorkerHealth { + pub worker_generation: u64, + pub alive: bool, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct BinaryHealth { + pub current_executable: String, + pub launch_path_stable: bool, + pub rollout_pending: bool, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct BindingHealth { + pub bound: bool, + pub requested_path: Option, + pub project_root: Option, + pub state_root: Option, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub(crate) struct HealthSnapshot { + pub initialization: InitializationHealth, + pub binding: BindingHealth, + pub worker: WorkerHealth, + pub binary: BinaryHealth, + pub last_fault: Option, +} -- cgit v1.2.3