use serde::Serialize;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::SystemTime;
static SLO_EVALS: AtomicU64 = AtomicU64::new(0);
#[derive(Debug, Clone, Serialize)]
pub struct VerificationObservabilityV1 {
pub schema_version: u32,
pub created_at: String,
pub role: String,
pub profile: String,
pub budgets: crate::core::budget_tracker::BudgetSnapshot,
pub slo: crate::core::slo::SloSnapshot,
pub verification: crate::core::output_verification::VerificationSnapshot,
pub proof: crate::core::context_proof::ProofStatsSnapshot,
pub pipeline: crate::core::pipeline::PipelineStats,
pub counters: CountersSnapshot,
}
#[derive(Debug, Clone, Serialize)]
pub struct CountersSnapshot {
pub slo_evals: u64,
}
pub fn record_slo_eval() {
SLO_EVALS.fetch_add(1, Ordering::Relaxed);
}
pub fn snapshot_v1() -> VerificationObservabilityV1 {
let created_at = chrono::Utc::now().to_rfc3339();
let role = crate::core::roles::active_role_name();
let profile = crate::core::profiles::active_profile_name();
let budgets = crate::core::budget_tracker::BudgetTracker::global().check();
let slo = crate::core::slo::evaluate_quiet();
let verification = crate::core::output_verification::stats_snapshot();
let proof = crate::core::context_proof::proof_stats_snapshot();
let pipeline = crate::core::pipeline::PipelineStats::load();
VerificationObservabilityV1 {
schema_version: crate::core::contracts::VERIFICATION_OBSERVABILITY_V1_SCHEMA_VERSION,
created_at,
role,
profile,
budgets,
slo,
verification,
proof,
pipeline,
counters: CountersSnapshot {
slo_evals: SLO_EVALS.load(Ordering::Relaxed),
},
}
}
pub fn format_compact(v: &VerificationObservabilityV1) -> String {
let proof_last = v
.proof
.last_written_at
.clone()
.unwrap_or_else(|| "-".to_string());
format!(
"{}\n{}\n{}\nProof: written={} last={proof_last}",
v.verification.format_compact(),
v.slo.format_compact(),
v.budgets.format_compact(),
v.proof.written
)
}
#[allow(dead_code)]
fn _unix_ms_now() -> u128 {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_or(0, |d| d.as_millis())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn snapshot_has_schema_version() {
let s = snapshot_v1();
assert_eq!(s.schema_version, 1);
assert!(s.created_at.contains('T'));
let compact = format_compact(&s);
assert!(compact.contains("Verification:"));
assert!(compact.contains("Proof: written="));
}
}