diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/api.rs | 70 | ||||
-rw-r--r-- | src/main.rs | 20 |
2 files changed, 87 insertions, 3 deletions
diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..56ee6f0 --- /dev/null +++ b/src/api.rs @@ -0,0 +1,70 @@ +use crate::{Config, Status, STATUS}; +use serde_json::{json, Value}; +use std::{ops::Deref, sync::Arc}; + +pub async fn make_json_response(config: Arc<Config>) -> Value { + let status = STATUS.read().await; + let status = status.deref(); + let total_err = status + .values() + .map(|s| s.status.is_err() as usize) + .sum::<usize>(); + let total_ok = status + .values() + .map(|s| s.status.is_ok() as usize) + .sum::<usize>(); + + let mut titles_failed = Vec::new(); + let services = config + .services + .iter() + .enumerate() + .map(|(i, s)| { + let total_err = status + .range((i, usize::MIN)..(i, usize::MAX)) + .map(|(_, s)| s.status.is_err() as usize) + .sum::<usize>(); + let total_ok = status + .range((i, usize::MIN)..(i, usize::MAX)) + .map(|(_, s)| s.status.is_ok() as usize) + .sum::<usize>(); + if total_err != 0 { + titles_failed.push(&s.title) + } + json!({ + "status": if total_err == 0 { + "ok" + } else if total_ok == 0 { + "failed" + } else { + "degraded" + }, + "title": &s.title, + }) + }) + .collect::<Vec<_>>(); + + json!({ + "status": if total_err == 0 { + "ok" + } else if total_ok == 0 { + "failed" + } else { + "degraded" + }, + "total_ok": total_ok, + "total_err": total_err, + "services": services, + "failed": titles_failed + }) +} + +impl Status { + pub fn json(&self) -> Value { + json!({ + "ok": self.status.is_ok(), + "message": match &self.status { Ok(m) => m, Err(m) => m }, + "time": self.time.timestamp() + }) + } +} diff --git a/src/main.rs b/src/main.rs index e5cfb31..bd3ff32 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ #![feature(exit_status_error)] +pub mod api; pub mod check; pub mod log; pub mod mail; @@ -6,7 +7,13 @@ pub mod web; use ::log::error; use anyhow::{anyhow, Result}; -use axum::{response::Html, routing::get, Router}; +use api::make_json_response; +use axum::{ + http::HeaderMap, + response::{Html, IntoResponse}, + routing::get, + Json, Router, +}; use check::{check_loop, Check}; use chrono::{DateTime, Utc}; use mail::MailConfig; @@ -72,7 +79,7 @@ async fn run() -> anyhow::Result<()> { "/", get({ let config = config.clone(); - move || async move { + move |headers: HeaderMap| async move { ( [ ( @@ -81,7 +88,14 @@ async fn run() -> anyhow::Result<()> { ), (REFRESH, format!("{}", config.interval)), ], - Html(make_html_page(config.clone()).await), + if headers + .get("accept") + .map_or(false, |s| s == "application/json") + { + Json(make_json_response(config.clone()).await).into_response() + } else { + Html(make_html_page(config.clone()).await).into_response() + }, ) } }), |