Skip to main content

hypercall/observability/metrics_collector/
events.rs

1use hypercall_types::observability::AuthFailureReason;
2use metrics::{counter, gauge};
3use tracing::info;
4
5// ===== Event-driven metrics (called from other modules) =====
6
7/// Bounded set of liquidation reasons to prevent metric cardinality explosion.
8#[derive(Debug, Clone, Copy)]
9pub enum LiquidationReason {
10    MarginInsufficient,
11    PortfolioRisk,
12    ManualTrigger,
13    Other,
14}
15
16impl LiquidationReason {
17    pub fn as_str(&self) -> &'static str {
18        match self {
19            Self::MarginInsufficient => "margin_insufficient",
20            Self::PortfolioRisk => "portfolio_risk",
21            Self::ManualTrigger => "manual_trigger",
22            Self::Other => "other",
23        }
24    }
25}
26
27/// Record a liquidation event.
28pub fn record_liquidation(wallet: &str, reason: LiquidationReason, shortfall: f64) {
29    counter!("ht_liquidations_total", "reason" => reason.as_str()).increment(1);
30    gauge!("ht_last_liquidation_shortfall_usd").set(shortfall);
31    info!(
32        "Liquidation recorded: wallet={}, reason={}, shortfall=${:.2}",
33        wallet,
34        reason.as_str(),
35        shortfall
36    );
37}
38
39/// Record an authentication failure.
40pub fn record_auth_failure(reason: AuthFailureReason) {
41    counter!("ht_auth_failures_total", "reason" => reason.as_str()).increment(1);
42}
43
44/// Record a settlement event.
45pub fn record_settlement(underlying: &str, success: bool) {
46    let status = if success { "success" } else { "failed" };
47    counter!("ht_settlements_total", "underlying" => underlying.to_string(), "status" => status)
48        .increment(1);
49}