use std::panic::{AssertUnwindSafe, catch_unwind};
use super::{coverage_class, mcp_bridge, proxy_bridge, receipt_chain, usage_normalizer};
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub(crate) struct DashboardSnapshot {
pub proxy_etpao: f64,
pub mcp_etpao: f64,
pub identity: IdentityView,
pub usage: UsageView,
pub chain: ChainView,
pub coverage: CoverageView,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub(crate) struct IdentityView {
pub total_users: usize,
pub total_tokens: usize,
pub total_saved: usize,
pub acceptance_rate: f64,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub(crate) struct UsageView {
pub total_requests: usize,
pub total_tokens: usize,
pub total_saved: usize,
pub compression_ratio: f64,
pub top_model: Option<String>,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub(crate) struct ChainView {
pub total_entries: usize,
pub accepted: usize,
pub rejected: usize,
pub kernel_hit_rate: f64,
pub phantom_savings_pct: f64,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub(crate) struct CoverageView {
pub proxy_coverage: String,
pub mcp_coverage: String,
pub is_fully_addressable: bool,
}
#[must_use]
pub(crate) fn snapshot() -> DashboardSnapshot {
catch_unwind(AssertUnwindSafe(build_snapshot)).unwrap_or_default()
}
#[must_use]
pub(crate) fn snapshot_json() -> String {
serde_json::to_string(&snapshot()).unwrap_or_else(|_| "{}".to_owned())
}
#[must_use]
pub(crate) fn format_summary() -> String {
let value = snapshot();
format!(
"ETPAO proxy={:.2} mcp={:.2}; requests={}; compression={:.2}; chain={}/{} accepted",
value.proxy_etpao,
value.mcp_etpao,
value.usage.total_requests,
value.usage.compression_ratio,
value.chain.accepted,
value.chain.total_entries,
)
}
fn build_snapshot() -> DashboardSnapshot {
let identity = proxy_bridge::identity_summary();
let proxy_etpao = proxy_bridge::etpao_summary();
let usage = usage_normalizer::session_usage();
let compression = usage_normalizer::compression_overview();
let chain = receipt_chain::chain_summary();
let proxy_coverage = coverage_class::CoverageClass::FullInline;
let mcp_coverage = coverage_class::CoverageClass::ContextControlled;
DashboardSnapshot {
proxy_etpao: proxy_etpao.etpao,
mcp_etpao: mcp_bridge::mcp_etpao(),
identity: IdentityView {
total_users: identity.total_users,
total_tokens: identity.total_tokens,
total_saved: identity.total_savings,
acceptance_rate: proxy_etpao.first_pass_rate,
},
usage: UsageView {
total_requests: usage.total_requests,
total_tokens: usage.total_tokens,
total_saved: usage.total_saved,
compression_ratio: compression.avg_compression_ratio,
top_model: compression.best_model,
},
chain: ChainView {
total_entries: chain.total_entries,
accepted: chain.accepted,
rejected: chain.rejected,
kernel_hit_rate: receipt_chain::kernel_hit_rate(),
phantom_savings_pct: average(chain.total_phantom_savings_pct, chain.total_entries),
},
coverage: CoverageView {
proxy_coverage: coverage_class::coverage_label(proxy_coverage).to_owned(),
mcp_coverage: coverage_class::coverage_label(mcp_coverage).to_owned(),
is_fully_addressable: coverage_class::is_addressable(proxy_coverage)
&& coverage_class::is_addressable(mcp_coverage),
},
}
}
fn average(total: f64, count: usize) -> f64 {
if count == 0 {
0.0
} else {
total / count as f64
}
}
#[cfg(test)]
mod tests {
use std::sync::{Mutex, MutexGuard};
use super::{DashboardSnapshot, format_summary, snapshot, snapshot_json};
use crate::core::context_kernel::mcp_bridge::{self, McpCallData};
use crate::core::context_kernel::proxy_bridge::{self, ProxyRequestData};
static TEST_LOCK: Mutex<()> = Mutex::new(());
fn isolated_test() -> MutexGuard<'static, ()> {
let guard = TEST_LOCK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
proxy_bridge::reset_state();
mcp_bridge::reset_mcp_state();
crate::core::context_kernel::usage_normalizer::reset_usage();
crate::core::context_kernel::receipt_chain::reset_chain();
guard
}
#[test]
fn empty_snapshot() {
let _guard = isolated_test();
let value = snapshot();
assert_eq!(value.proxy_etpao, 0.0);
assert_eq!(value.mcp_etpao, 0.0);
assert_eq!(value.identity.total_tokens, 0);
assert_eq!(value.usage.total_requests, 0);
assert_eq!(value.chain.total_entries, 0);
}
#[test]
fn snapshot_serializes() {
let _guard = isolated_test();
let decoded: DashboardSnapshot = serde_json::from_str(&snapshot_json()).unwrap();
assert_eq!(decoded.proxy_etpao, 0.0);
}
#[test]
fn format_summary_non_empty() {
let _guard = isolated_test();
let summary = format_summary();
assert!(summary.contains("ETPAO"));
assert!(summary.contains("compression"));
}
#[test]
fn snapshot_includes_coverage() {
let _guard = isolated_test();
let coverage = snapshot().coverage;
assert_eq!(coverage.proxy_coverage, "full_inline");
assert_eq!(coverage.mcp_coverage, "context_controlled");
assert!(coverage.is_fully_addressable);
}
#[test]
fn snapshot_after_activity() {
let _guard = isolated_test();
let _ = proxy_bridge::process_proxy_request(&ProxyRequestData {
input_tokens: 80,
output_tokens: 20,
request_count: 1,
..ProxyRequestData::default()
});
mcp_bridge::record_mcp_call(&McpCallData {
input_tokens: 40,
output_tokens: 10,
call_number: 1,
..McpCallData::default()
});
let value = snapshot();
assert!(value.proxy_etpao > 0.0);
assert!(value.mcp_etpao > 0.0);
assert!(value.identity.total_tokens > 0);
}
}