aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api.rs70
-rw-r--r--src/main.rs20
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()
+ },
)
}
}),