generated from PlexSheep/baserepo
net monitor uptime now uses serde
This commit is contained in:
parent
8dc4a0aade
commit
37d77044b8
|
@ -35,4 +35,6 @@ openssl-sys = "0.9.90"
|
||||||
pyo3 = "0.18.1"
|
pyo3 = "0.18.1"
|
||||||
regex = "1.9.1"
|
regex = "1.9.1"
|
||||||
reqwest = { version = "0.11.18", features = ["blocking"] }
|
reqwest = { version = "0.11.18", features = ["blocking"] }
|
||||||
|
serde = { version = "1.0.171", features = ["derive"] }
|
||||||
|
serde_json = "1.0.102"
|
||||||
signal-hook = "0.3.15"
|
signal-hook = "0.3.15"
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub fn net(cli: &Cli, command: NetCommands) {
|
||||||
if repeat > 0 {
|
if repeat > 0 {
|
||||||
uptime::continuous_uptime_monitor(success_ratio, urls, repeat * 1000, timeout);
|
uptime::continuous_uptime_monitor(success_ratio, urls, repeat * 1000, timeout);
|
||||||
} else {
|
} else {
|
||||||
let status = uptime::UptimeStatus::new(success_ratio, &urls, timeout);
|
let status = uptime::UptimeStatus::new(success_ratio, urls, timeout);
|
||||||
println!("{}", status);
|
println!("{}", status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,23 @@
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
use std::{fmt, str::FromStr, time::Duration};
|
use std::{fmt, time::Duration};
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want the log macros in any case
|
// we want the log macros in any case
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
use reqwest::{self, Url};
|
use reqwest;
|
||||||
|
|
||||||
use humantime::{format_duration, format_rfc3339};
|
use humantime::{format_duration, format_rfc3339};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
use crate::divider;
|
use crate::divider;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -50,44 +53,43 @@ pub const DEFAULT_CHECK_URLS: &'static [&'static str] =
|
||||||
///
|
///
|
||||||
/// [`UptimeStatus`] describes the result of an uptime check.
|
/// [`UptimeStatus`] describes the result of an uptime check.
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct UptimeStatus {
|
pub struct UptimeStatus {
|
||||||
/// true if the [`UptimeStatus`] is considered successful
|
/// true if the [`UptimeStatus`] is considered successful
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
/// the percentage of reachable urls out of the total urls
|
/// the percentage of reachable urls out of the total urls
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub success_ratio: u8,
|
pub success_ratio: u8,
|
||||||
/// the percentage of reachable urls out of the total urls that need to be reachable in order
|
/// 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.
|
/// for this [`UptimeStatus`] to be considered a success.
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub success_ratio_target: u8,
|
pub success_ratio_target: u8,
|
||||||
/// the number of reachable [`urls`](UptimeStatus::urls)
|
/// the number of reachable [`urls`](UptimeStatus::urls)
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub reachable: usize,
|
pub reachable: usize,
|
||||||
/// which urls to check in [`check()`](UptimeStatus::check)
|
/// 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)
|
/// timeout length for requests (in ms)
|
||||||
pub timeout: u64
|
#[pyo3(get, set)]
|
||||||
|
pub timeout: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Main implementation
|
/// Main implementation
|
||||||
impl UptimeStatus {
|
impl UptimeStatus {
|
||||||
/// ## create a new `UptimeStatus` and perform it's check
|
/// ## 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);
|
assert!(success_ratio_target <= 100);
|
||||||
let mut status = UptimeStatus {
|
let mut status = UptimeStatus {
|
||||||
success: false,
|
success: false,
|
||||||
success_ratio: 0,
|
success_ratio: 0,
|
||||||
success_ratio_target,
|
success_ratio_target,
|
||||||
reachable: 0,
|
reachable: 0,
|
||||||
urls: Vec::new(),
|
urls,
|
||||||
timeout
|
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.urls.dedup();
|
||||||
|
|
||||||
status.check();
|
status.check();
|
||||||
|
@ -152,8 +154,8 @@ impl UptimeStatus {
|
||||||
impl UptimeStatus {
|
impl UptimeStatus {
|
||||||
/// calls [`new()`](UptimeStatus::new) with python compatible arguments
|
/// calls [`new()`](UptimeStatus::new) with python compatible arguments
|
||||||
#[new]
|
#[new]
|
||||||
pub fn py_new(success_ratio_target: u8, url_strs: Vec<String>, timeout: u64) -> Self {
|
pub fn py_new(success_ratio_target: u8, urls: Vec<String>, timeout: u64) -> Self {
|
||||||
Self::new(success_ratio_target, &url_strs, timeout)
|
Self::new(success_ratio_target, urls, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as [`check()`](UptimeStatus::check)
|
/// Same as [`check()`](UptimeStatus::check)
|
||||||
|
@ -168,23 +170,6 @@ impl UptimeStatus {
|
||||||
self.calc_success();
|
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__`
|
/// we want to display the [`UptimeStatus`] in python too, so we need `__str__`
|
||||||
pub fn __str__(&self) -> String {
|
pub fn __str__(&self) -> String {
|
||||||
format!("{}", self)
|
format!("{}", self)
|
||||||
|
@ -199,36 +184,22 @@ impl UptimeStatus {
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl fmt::Debug for UptimeStatus {
|
impl fmt::Debug for UptimeStatus {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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 {
|
for url in &self.urls {
|
||||||
url_strs.push(url.as_str());
|
urls.push(url.as_str());
|
||||||
}
|
}
|
||||||
write!(
|
write!(f, "{}", serde_json::to_string(self).unwrap())
|
||||||
f,
|
|
||||||
concat!(
|
|
||||||
"{{ success: {}, success_ratio: {}%, success_ratio_target: {}%,",
|
|
||||||
" reachable: {}, urls: {:?}}}"
|
|
||||||
),
|
|
||||||
self.success, self.success_ratio, self.success_ratio_target, self.reachable, url_strs
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl fmt::Display for UptimeStatus {
|
impl fmt::Display for UptimeStatus {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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 {
|
for url in &self.urls {
|
||||||
url_strs.push(url.as_str());
|
urls.push(url.as_str());
|
||||||
}
|
}
|
||||||
write!(
|
write!(f, "{}", serde_json::to_string_pretty(self).unwrap())
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
/// 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
|
/// information on your current status, including timestamps of the last up/down time and durations
|
||||||
/// since.
|
/// 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 {
|
if urls.len() == 0 {
|
||||||
error!("No URLs provided. There is nothing to monitor.");
|
error!("No URLs provided. There is nothing to monitor.");
|
||||||
return;
|
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 interval = std::time::Duration::from_millis(interval);
|
||||||
let mut last_downtime: Option<SystemTime> = None;
|
let mut last_downtime: Option<SystemTime> = None;
|
||||||
let mut last_uptime: 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_was_up: bool = false;
|
||||||
let mut last_ratio: u8 = status.success_ratio;
|
let mut last_ratio: u8 = status.success_ratio;
|
||||||
loop {
|
loop {
|
||||||
|
@ -295,8 +271,8 @@ pub fn py_continuous_uptime_monitor(
|
||||||
success_ratio_target: u8,
|
success_ratio_target: u8,
|
||||||
urls: Vec<String>,
|
urls: Vec<String>,
|
||||||
interval: u64,
|
interval: u64,
|
||||||
timeout: u64
|
timeout: u64,
|
||||||
) -> PyResult<()>{
|
) -> PyResult<()> {
|
||||||
// execute the function in a different thread
|
// execute the function in a different thread
|
||||||
let _th = std::thread::spawn(move || {
|
let _th = std::thread::spawn(move || {
|
||||||
continuous_uptime_monitor(success_ratio_target, urls, interval, timeout);
|
continuous_uptime_monitor(success_ratio_target, urls, interval, timeout);
|
||||||
|
|
Reference in New Issue