lean_ctx/core/
verification_observability.rs1use serde::Serialize;
2use std::sync::atomic::{AtomicU64, Ordering};
3use std::time::SystemTime;
4
5static SLO_EVALS: AtomicU64 = AtomicU64::new(0);
6
7#[derive(Debug, Clone, Serialize)]
8pub struct VerificationObservabilityV1 {
9 pub schema_version: u32,
10 pub created_at: String,
11 pub role: String,
12 pub profile: String,
13 pub budgets: crate::core::budget_tracker::BudgetSnapshot,
14 pub slo: crate::core::slo::SloSnapshot,
15 pub verification: crate::core::output_verification::VerificationSnapshot,
16 pub proof: crate::core::context_proof::ProofStatsSnapshot,
17 pub pipeline: crate::core::pipeline::PipelineStats,
18 pub counters: CountersSnapshot,
19}
20
21#[derive(Debug, Clone, Serialize)]
22pub struct CountersSnapshot {
23 pub slo_evals: u64,
24}
25
26pub fn record_slo_eval() {
27 SLO_EVALS.fetch_add(1, Ordering::Relaxed);
28}
29
30pub fn snapshot_v1() -> VerificationObservabilityV1 {
31 let created_at = chrono::Utc::now().to_rfc3339();
32 let role = crate::core::roles::active_role_name();
33 let profile = crate::core::profiles::active_profile_name();
34
35 let budgets = crate::core::budget_tracker::BudgetTracker::global().check();
36 let slo = crate::core::slo::evaluate_quiet();
37 let verification = crate::core::output_verification::stats_snapshot();
38 let proof = crate::core::context_proof::proof_stats_snapshot();
39 let pipeline = crate::core::pipeline::PipelineStats::load();
40
41 VerificationObservabilityV1 {
42 schema_version: crate::core::contracts::VERIFICATION_OBSERVABILITY_V1_SCHEMA_VERSION,
43 created_at,
44 role,
45 profile,
46 budgets,
47 slo,
48 verification,
49 proof,
50 pipeline,
51 counters: CountersSnapshot {
52 slo_evals: SLO_EVALS.load(Ordering::Relaxed),
53 },
54 }
55}
56
57pub fn format_compact(v: &VerificationObservabilityV1) -> String {
58 let proof_last = v
59 .proof
60 .last_written_at
61 .clone()
62 .unwrap_or_else(|| "-".to_string());
63 format!(
64 "{}\n{}\n{}\nProof: written={} last={proof_last}",
65 v.verification.format_compact(),
66 v.slo.format_compact(),
67 v.budgets.format_compact(),
68 v.proof.written
69 )
70}
71
72#[allow(dead_code)]
74fn _unix_ms_now() -> u128 {
75 SystemTime::now()
76 .duration_since(SystemTime::UNIX_EPOCH)
77 .map_or(0, |d| d.as_millis())
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn snapshot_has_schema_version() {
86 let s = snapshot_v1();
87 assert_eq!(s.schema_version, 1);
88 assert!(s.created_at.contains('T'));
89 let compact = format_compact(&s);
90 assert!(compact.contains("Verification:"));
91 assert!(compact.contains("Proof: written="));
92 }
93}