use crate::{config::*, updater::update_status}; use chrono::prelude::*; use serde::{Serialize, Serializer}; #[derive(Clone, Debug)] pub enum EndpointStatus { OK, WARN, ERROR, MAINTENANCE, UNKNOWN, } /// Custom serialization implementation, since its rendered form will be as a /// CSS class. The default serialization keeps things uppercase, which is /// discouraged as CSS class names. impl Serialize for EndpointStatus { fn serialize(&self, s: S) -> Result where S: Serializer, { s.serialize_str(match *self { EndpointStatus::OK => "ok", EndpointStatus::WARN => "warn", EndpointStatus::ERROR => "error", EndpointStatus::MAINTENANCE => "maintenance", EndpointStatus::UNKNOWN => "unknown", }) } } impl Into for EndpointStatus { fn into(self) -> String { match self { EndpointStatus::OK => String::from("ok"), EndpointStatus::WARN => String::from("warn"), EndpointStatus::ERROR => String::from("error"), EndpointStatus::MAINTENANCE => String::from("maintenance"), EndpointStatus::UNKNOWN => String::from("unknown"), } } } /// This holds the results of pinging a single endpoint. RTT exists iff there /// aren't any errors. #[derive(Clone, Serialize, Debug)] pub struct Endpoint { pub status: EndpointStatus, pub location: String, pub label: String, pub rtt: Option, pub errors: Vec, } /// Various helper functions for generating resulting statuses impl Endpoint { pub fn ok(location: String, label: String, rtt: String) -> Self { Endpoint { status: EndpointStatus::OK, location, label, rtt: Some(rtt), errors: vec![], } } pub fn warn(location: String, label: String, rtt: String, errors: Vec) -> Self { Endpoint { status: EndpointStatus::WARN, location, label, rtt: Some(rtt), errors, } } pub fn error(location: String, label: String, errors: Vec) -> Self { Endpoint { status: EndpointStatus::ERROR, location, label, rtt: None, errors, } } pub fn maintenance(location: String, label: String, errors: Vec) -> Self { Endpoint { status: EndpointStatus::MAINTENANCE, location, label, rtt: None, errors, } } pub fn unknown(location: String, label: String, errors: Vec) -> Self { Endpoint { status: EndpointStatus::UNKNOWN, location, label, rtt: None, errors, } } } #[derive(Serialize, Debug)] pub struct StatusGroup { pub label: String, pub endpoints: Vec, } #[derive(Serialize, Debug)] pub struct QueryResults { pub timestamp: DateTime, pub timestamp_str: String, pub refresh_time: u64, pub config: Config, pub groups: Vec, } impl QueryResults { pub fn new(config: Config) -> Self { let time = Utc::now(); QueryResults { timestamp: time, timestamp_str: Self::format_timestamp(time), refresh_time: config.refresh_time, config: config.clone(), groups: update_status(&config), } } pub fn update(&mut self, updated_groups: Vec) { self.update_timestamp(); self.groups = updated_groups; } #[inline] fn update_timestamp(&mut self) { let current_time = Utc::now(); self.timestamp = current_time; self.timestamp_str = Self::format_timestamp(current_time); } fn format_timestamp(timestamp: DateTime) -> String { timestamp.format("%Y-%m-%d %H:%M:%S").to_string() } }