Using heartbeat api instead

This commit is contained in:
Marco De Araujo 2025-12-22 10:51:58 -04:00
parent 4cedb17b60
commit d024280878
10 changed files with 319 additions and 40 deletions

103
src/heartbeat/model.rs Normal file
View file

@ -0,0 +1,103 @@
use std::collections::HashMap;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use crate::i18n::t;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HeartbeatEntry {
pub status: u8,
pub time: String,
pub msg: String,
#[serde(default)]
pub ping: Option<u64>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct MonitorHeartbeats {
pub monitor_id: u64,
pub heartbeats: Vec<HeartbeatEntry>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct UptimeData {
pub monitor_id: u64,
pub period_hours: u32,
pub uptime_percentage: f64,
}
impl UptimeData {
pub fn get_perc_formated(&self) -> String {
format!("{:.2}%", self.uptime_percentage * 100.00)
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HeartbeatResponse {
#[serde(rename = "heartbeatList")]
pub heartbeat_list_raw: HashMap<String, Vec<HeartbeatEntry>>,
#[serde(rename = "uptimeList")]
pub uptime_list_raw: HashMap<String, f64>,
#[serde(skip)]
pub monitors: Vec<MonitorHeartbeats>,
#[serde(skip)]
pub uptime_data: Vec<UptimeData>,
}
impl HeartbeatResponse {
pub fn process(&mut self) -> Result<()> {
for (monitor_id_str, heartbeats) in &self.heartbeat_list_raw {
let monitor_id = monitor_id_str
.parse::<u64>()
.with_context(|| format!("{}", t("invalid-monitor-id")))?;
self.monitors.push(MonitorHeartbeats {
monitor_id,
heartbeats: heartbeats.clone(),
});
}
for (key, percentage) in &self.uptime_list_raw {
let parts: Vec<&str> = key.split('_').collect();
if parts.len() != 2 {
return Err(anyhow::anyhow!("Formato invalido (colocar o t) {}", key));
}
let monitor_id = parts[0]
.parse::<u64>()
.with_context(|| format!("{}", t("invalid-monitor-id")))?;
let period_hours = parts[1]
.parse::<u32>()
.with_context(|| format!("{}", t("invalid-period-hours")))?;
self.uptime_data.push(UptimeData {
monitor_id,
period_hours,
uptime_percentage: *percentage,
});
}
self.monitors.sort_by_key(|m| m.monitor_id);
self.uptime_data
.sort_by_key(|u| (u.monitor_id, u.period_hours));
Ok(())
}
pub fn get_uptime(&self, monitor_id: u64, period_hours: u32) -> Option<&UptimeData> {
self.uptime_data
.iter()
.find(|u| u.monitor_id == monitor_id && u.period_hours == period_hours)
}
pub fn get_latest_heartbeat(&self, monitor_id: u64) -> Option<&HeartbeatEntry> {
self.monitors
.iter()
.find(|m| m.monitor_id == monitor_id)
.and_then(|m| m.heartbeats.last())
}
}