towerops-agent/src/health.rs
Graham McIntire d00e3782c3
Remove unused health server methods
- Removed update_config_fetch_time() and record_error()
- These methods were not integrated with the scheduler
- Fixes cargo clippy dead_code warnings
2026-01-15 08:06:29 -06:00

118 lines
3.6 KiB
Rust

use crate::buffer::Storage;
use crate::metrics::Timestamp;
use log::{error, info};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
use std::thread;
use tiny_http::{Response, Server};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
pub status: String,
pub version: String,
pub uptime_seconds: u64,
pub config_last_fetch: Option<String>,
pub metrics_pending: usize,
pub last_error: Option<String>,
}
pub struct HealthServer {
start_time: Timestamp,
storage: Storage,
last_error: Arc<Mutex<Option<String>>>,
config_last_fetch: Arc<Mutex<Option<Timestamp>>>,
}
impl HealthServer {
pub fn new(storage: Storage) -> Self {
Self {
start_time: Timestamp::now(),
storage,
last_error: Arc::new(Mutex::new(None)),
config_last_fetch: Arc::new(Mutex::new(None)),
}
}
pub fn start(self, port: u16) {
thread::spawn(move || {
let addr = format!("0.0.0.0:{}", port);
info!("Starting health endpoint on {}", addr);
let server = match Server::http(&addr) {
Ok(s) => s,
Err(e) => {
error!("Failed to start health server: {}", e);
return;
}
};
for request in server.incoming_requests() {
let path = request.url();
if path == "/health" {
let status = self.get_health_status();
let json = match serde_json::to_string(&status) {
Ok(j) => j,
Err(e) => {
error!("Failed to serialize health status: {}", e);
let _ = request.respond(
Response::from_string("Internal error").with_status_code(500),
);
continue;
}
};
let response = Response::from_string(json)
.with_header(
tiny_http::Header::from_bytes(
&b"Content-Type"[..],
&b"application/json"[..],
)
.unwrap(),
)
.with_status_code(200);
let _ = request.respond(response);
} else {
let _ =
request.respond(Response::from_string("Not found").with_status_code(404));
}
}
});
}
fn get_health_status(&self) -> HealthStatus {
let uptime = self.start_time.elapsed_secs() as u64;
// Get pending metrics count
let metrics_pending = self
.storage
.get_pending_metrics(1000)
.map(|m| m.len())
.unwrap_or(0);
// Get last config fetch time
let config_last_fetch = self
.config_last_fetch
.lock()
.ok()
.and_then(|guard| *guard)
.map(|ts| ts.to_rfc3339());
// Get last error
let last_error = self
.last_error
.lock()
.ok()
.and_then(|guard| (*guard).clone());
HealthStatus {
status: "healthy".to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
uptime_seconds: uptime,
config_last_fetch,
metrics_pending,
last_error,
}
}
}