net monitor uptime now uses serde

This commit is contained in:
Christoph J. Scherr 2023-07-12 19:15:42 +02:00
parent 8dc4a0aade
commit 37d77044b8
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
3 changed files with 37 additions and 59 deletions

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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<Url>,
#[pyo3(get, set)]
pub urls: Vec<String>,
/// 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<String>, timeout: u64) -> Self {
pub fn new(success_ratio_target: u8, urls: Vec<String>, 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<String>, timeout: u64) -> Self {
Self::new(success_ratio_target, &url_strs, timeout)
pub fn py_new(success_ratio_target: u8, urls: Vec<String>, 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<String> {
let mut url_strs: Vec<String> = 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<String>, interval: u64, timeout: u64) {
pub fn continuous_uptime_monitor(
success_ratio_target: u8,
urls: Vec<String>,
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<String>, in
let interval = std::time::Duration::from_millis(interval);
let mut last_downtime: Option<SystemTime> = None;
let mut last_uptime: Option<SystemTime> = 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<String>,
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);