Skip to main content

hypercall_admin/monitoring/
rpi.rs

1use axum::{
2    extract::{Query, State},
3    response::IntoResponse,
4};
5use hypercall_runtime_api::rpi_monitor::{self, RpiMonitorEvent, RpiMonitorFilter};
6use hypercall_runtime_api::sonic_json::SonicJson;
7use serde::{Deserialize, Serialize};
8
9use crate::state::AdminState;
10
11#[derive(Debug, Deserialize, utoipa::IntoParams, utoipa::ToSchema)]
12pub struct RpiMonitoringQuery {
13    #[serde(default = "default_rpi_monitoring_limit")]
14    pub limit: usize,
15    pub outcome: Option<String>,
16    pub symbol: Option<String>,
17    pub wallet: Option<String>,
18    pub rfq_id: Option<String>,
19    pub request_id: Option<String>,
20}
21
22fn default_rpi_monitoring_limit() -> usize {
23    100
24}
25
26#[derive(Debug, Serialize, utoipa::ToSchema)]
27pub struct RpiMonitoringBuildInfo {
28    pub version: String,
29    pub commit: String,
30    pub git_ref: String,
31    pub build_time: String,
32}
33
34#[derive(Debug, Serialize, utoipa::ToSchema)]
35pub struct RpiMonitoringResponse {
36    pub count: usize,
37    pub events: Vec<RpiMonitorEvent>,
38    pub build_info: RpiMonitoringBuildInfo,
39}
40
41/// GET /monitoring/rpi - Recent RPI routing decisions and outcomes.
42#[utoipa::path(
43    get,
44    path = "/monitoring/rpi",
45    params(RpiMonitoringQuery),
46    responses(
47        (status = 200, description = "Recent RPI routing events", body = RpiMonitoringResponse),
48        (status = 401, description = "Invalid or missing X-Admin-Key header")
49    ),
50    tag = "Monitoring",
51    security(("admin_key" = []))
52)]
53pub async fn rpi_monitoring(
54    State(state): State<AdminState>,
55    Query(params): Query<RpiMonitoringQuery>,
56) -> impl IntoResponse {
57    let limit = params.limit.clamp(1, 500);
58    let filter = RpiMonitorFilter {
59        outcome: params.outcome,
60        symbol: params.symbol,
61        wallet: params.wallet,
62        rfq_id: params.rfq_id,
63        request_id: params.request_id,
64    };
65    let events = rpi_monitor::recent(&filter, limit);
66    SonicJson(RpiMonitoringResponse {
67        count: events.len(),
68        events,
69        build_info: RpiMonitoringBuildInfo {
70            version: state.build_info.version.clone(),
71            commit: state.build_info.commit.clone(),
72            git_ref: state.build_info.git_ref.clone(),
73            build_time: state.build_info.build_time.clone(),
74        },
75    })
76}