From 37d77044b8ef8cac2ce5ed5618069889878d00c8 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Wed, 12 Jul 2023 19:15:42 +0200 Subject: [PATCH] net monitor uptime now uses serde --- Cargo.toml | 2 + src/bin/main/mod.rs | 2 +- src/networking/monitoring/uptime.rs | 92 +++++++++++------------------ 3 files changed, 37 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f5df12c..79ff643 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,4 +35,6 @@ openssl-sys = "0.9.90" pyo3 = "0.18.1" regex = "1.9.1" reqwest = { version = "0.11.18", features = ["blocking"] } +serde = { version = "1.0.171", features = ["derive"] } +serde_json = "1.0.102" signal-hook = "0.3.15" diff --git a/src/bin/main/mod.rs b/src/bin/main/mod.rs index 3141a6b..f9e53ad 100644 --- a/src/bin/main/mod.rs +++ b/src/bin/main/mod.rs @@ -94,7 +94,7 @@ pub fn net(cli: &Cli, command: NetCommands) { if repeat > 0 { uptime::continuous_uptime_monitor(success_ratio, urls, repeat * 1000, timeout); } else { - let status = uptime::UptimeStatus::new(success_ratio, &urls, timeout); + let status = uptime::UptimeStatus::new(success_ratio, urls, timeout); println!("{}", status); } } diff --git a/src/networking/monitoring/uptime.rs b/src/networking/monitoring/uptime.rs index 7474fb3..72d7b77 100644 --- a/src/networking/monitoring/uptime.rs +++ b/src/networking/monitoring/uptime.rs @@ -16,20 +16,23 @@ // enable clippy's extra lints, the pedantic version #![warn(clippy::pedantic)] -use std::{fmt, str::FromStr, time::Duration}; +use std::{fmt, time::Duration}; //// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// // we want the log macros in any case #[allow(unused_imports)] use log::{debug, error, info, trace, warn}; -use reqwest::{self, Url}; +use reqwest; use humantime::{format_duration, format_rfc3339}; use std::time::SystemTime; use pyo3::prelude::*; +use serde::{Deserialize, Serialize}; +use serde_json; + use crate::divider; //// TYPES ///////////////////////////////////////////////////////////////////////////////////////// @@ -50,44 +53,43 @@ pub const DEFAULT_CHECK_URLS: &'static [&'static str] = /// /// [`UptimeStatus`] describes the result of an uptime check. #[pyclass] +#[derive(Serialize, Deserialize)] pub struct UptimeStatus { /// true if the [`UptimeStatus`] is considered successful + #[pyo3(get, set)] pub success: bool, /// the percentage of reachable urls out of the total urls + #[pyo3(get, set)] pub success_ratio: u8, /// the percentage of reachable urls out of the total urls that need to be reachable in order /// for this [`UptimeStatus`] to be considered a success. + #[pyo3(get, set)] pub success_ratio_target: u8, /// the number of reachable [`urls`](UptimeStatus::urls) + #[pyo3(get, set)] pub reachable: usize, /// which urls to check in [`check()`](UptimeStatus::check) - pub urls: Vec, + #[pyo3(get, set)] + pub urls: Vec, /// timeout length for requests (in ms) - pub timeout: u64 + #[pyo3(get, set)] + pub timeout: u64, } //// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// /// Main implementation impl UptimeStatus { /// ## create a new `UptimeStatus` and perform it's check - pub fn new(success_ratio_target: u8, url_strs: &Vec, timeout: u64) -> Self { + pub fn new(success_ratio_target: u8, urls: Vec, timeout: u64) -> Self { assert!(success_ratio_target <= 100); let mut status = UptimeStatus { success: false, success_ratio: 0, success_ratio_target, reachable: 0, - urls: Vec::new(), - timeout + urls, + timeout, }; - for s in url_strs { - let url = reqwest::Url::from_str(&s); - if url.is_ok() { - status.urls.push(url.unwrap()); - } else { - warn!("Invalid URL: '{}", s); - } - } status.urls.dedup(); status.check(); @@ -152,8 +154,8 @@ impl UptimeStatus { impl UptimeStatus { /// calls [`new()`](UptimeStatus::new) with python compatible arguments #[new] - pub fn py_new(success_ratio_target: u8, url_strs: Vec, timeout: u64) -> Self { - Self::new(success_ratio_target, &url_strs, timeout) + pub fn py_new(success_ratio_target: u8, urls: Vec, timeout: u64) -> Self { + Self::new(success_ratio_target, urls, timeout) } /// Same as [`check()`](UptimeStatus::check) @@ -168,23 +170,6 @@ impl UptimeStatus { self.calc_success(); } - /// ## get urls for python - /// - /// Since [`UptimeStatus::urls`] has no python equivalent, return the urls as a `list[str]` in - /// Python. - /// - /// Practically, this is also handy for rust implementations that want to access the URLs as - /// [Strings](String). - pub fn urls(&self) -> Vec { - let mut url_strs: Vec = Vec::new(); - - for url in self.urls.clone() { - url_strs.push(url.to_string()); - } - - return url_strs; - } - /// we want to display the [`UptimeStatus`] in python too, so we need `__str__` pub fn __str__(&self) -> String { format!("{}", self) @@ -199,36 +184,22 @@ impl UptimeStatus { //////////////////////////////////////////////////////////////////////////////////////////////////// impl fmt::Debug for UptimeStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut url_strs: Vec<&str> = Vec::new(); + let mut urls: Vec<&str> = Vec::new(); for url in &self.urls { - url_strs.push(url.as_str()); + urls.push(url.as_str()); } - write!( - f, - concat!( - "{{ success: {}, success_ratio: {}%, success_ratio_target: {}%,", - " reachable: {}, urls: {:?}}}" - ), - self.success, self.success_ratio, self.success_ratio_target, self.reachable, url_strs - ) + write!(f, "{}", serde_json::to_string(self).unwrap()) } } //////////////////////////////////////////////////////////////////////////////////////////////////// impl fmt::Display for UptimeStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut url_strs: Vec<&str> = Vec::new(); + let mut urls: Vec<&str> = Vec::new(); for url in &self.urls { - url_strs.push(url.as_str()); + urls.push(url.as_str()); } - write!( - f, - concat!( - "{{\n\tsuccess: {},\n\tsuccess_ratio: {}%,\n\tsuccess_ratio_target: {}%,\n", - "\treachable: {},\n\turls: {:?}\n}}" - ), - self.success, self.success_ratio, self.success_ratio_target, self.reachable, url_strs - ) + write!(f, "{}", serde_json::to_string_pretty(self).unwrap()) } } @@ -240,7 +211,12 @@ impl fmt::Display for UptimeStatus { /// On change of status, an update will be logged at [INFO Level](log::Level::Info), containing /// information on your current status, including timestamps of the last up/down time and durations /// since. -pub fn continuous_uptime_monitor(success_ratio_target: u8, urls: Vec, interval: u64, timeout: u64) { +pub fn continuous_uptime_monitor( + success_ratio_target: u8, + urls: Vec, + interval: u64, + timeout: u64, +) { if urls.len() == 0 { error!("No URLs provided. There is nothing to monitor."); return; @@ -249,7 +225,7 @@ pub fn continuous_uptime_monitor(success_ratio_target: u8, urls: Vec, in let interval = std::time::Duration::from_millis(interval); let mut last_downtime: Option = None; let mut last_uptime: Option = None; - let mut status = UptimeStatus::new(success_ratio_target, &urls, timeout); + let mut status = UptimeStatus::new(success_ratio_target, urls, timeout); let mut last_was_up: bool = false; let mut last_ratio: u8 = status.success_ratio; loop { @@ -295,8 +271,8 @@ pub fn py_continuous_uptime_monitor( success_ratio_target: u8, urls: Vec, interval: u64, - timeout: u64 -) -> PyResult<()>{ + timeout: u64, +) -> PyResult<()> { // execute the function in a different thread let _th = std::thread::spawn(move || { continuous_uptime_monitor(success_ratio_target, urls, interval, timeout);