aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..0136f94
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,87 @@
+pub mod check;
+pub mod web;
+pub mod mail;
+
+use anyhow::{anyhow, Result};
+use axum::{routing::get, Router};
+use check::check_loop;
+use log::error;
+use serde::Deserialize;
+use std::{
+ collections::BTreeMap,
+ net::SocketAddr,
+ sync::Arc,
+ time::{Duration, SystemTime},
+};
+use tokio::{fs::read_to_string, sync::RwLock};
+use web::send_html_page;
+
+#[tokio::main]
+async fn main() {
+ env_logger::init_from_env("LOG");
+ if let Err(e) = run().await {
+ error!("{e:?}")
+ }
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Config {
+ title: String,
+ bind: SocketAddr,
+ interval: u64,
+ services: Vec<Service>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Service {
+ title: String,
+ checks: Vec<Check>,
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Check {
+ Systemd(String),
+ Http { title: Option<String>, url: String },
+ Shell { title: String, command: String },
+}
+
+#[derive(Debug, Clone)]
+pub struct Success {
+ pub latency: Option<Duration>,
+ pub updated: SystemTime,
+}
+impl Default for Success {
+ fn default() -> Self {
+ Self {
+ latency: None,
+ updated: SystemTime::now(),
+ }
+ }
+}
+
+static STATUS: RwLock<BTreeMap<(usize, usize), Result<Success>>> =
+ RwLock::const_new(BTreeMap::new());
+
+async fn run() -> anyhow::Result<()> {
+ let config = std::env::args()
+ .nth(1)
+ .ok_or(anyhow!("expected config path as first argument"))?;
+ let config = read_to_string(config).await?;
+ let config = Arc::<Config>::new(serde_yaml::from_str(&config)?);
+
+ for i in 0..config.services.len() {
+ tokio::task::spawn(check_loop(config.clone(), i));
+ }
+
+ let app = Router::new().route(
+ "/",
+ get({
+ let config = config.clone();
+ move || send_html_page(config.clone())
+ }),
+ );
+ let listener = tokio::net::TcpListener::bind(config.bind).await?;
+ axum::serve(listener, app).await?;
+ Ok(())
+}