generated from PlexSheep/baserepo
monitoring struct
This commit is contained in:
parent
354db00312
commit
791b04f71f
|
@ -15,9 +15,7 @@
|
|||
#![warn(clippy::pedantic)]
|
||||
|
||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
use libpt;
|
||||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
use clap_num::number_range;
|
||||
|
||||
|
@ -56,21 +54,12 @@ pub struct Cli {
|
|||
pub verbose: Verbosity,
|
||||
|
||||
/// choose a subcommand
|
||||
///
|
||||
///
|
||||
#[command(subcommand)]
|
||||
pub command: Commands,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#[derive(Debug, Clone, Args)]
|
||||
pub struct NetDiscoverArgs {
|
||||
#[clap(short)]
|
||||
test: bool,
|
||||
}
|
||||
|
||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// # Top level commands
|
||||
/// # defines the top level commands
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
#[non_exhaustive]
|
||||
pub enum Commands {
|
||||
|
@ -82,12 +71,13 @@ pub enum Commands {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// defines the networking commands
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
#[non_exhaustive]
|
||||
pub enum NetCommands {
|
||||
/// monitor your network
|
||||
Monitor {
|
||||
/// repeat every N milliseconds, 0 means no repeat
|
||||
/// repeat every N seconds, 0 means no repeat
|
||||
#[clap(short, long, default_value_t = 0, name = "N")]
|
||||
repeat: u64,
|
||||
|
||||
|
|
|
@ -85,13 +85,14 @@ fn net(cli: &Cli, command: NetCommands) {
|
|||
let _verbose = cli.verbose.log_level().is_some();
|
||||
if repeat > 0 {
|
||||
loop {
|
||||
let status: uptime::UptimeStatus = uptime::check_status(&urls, success_ratio);
|
||||
println!("{}", uptime::display_uptime_status(&status));
|
||||
std::thread::sleep(std::time::Duration::from_millis(repeat))
|
||||
let status = uptime::UptimeStatus::new(success_ratio, &urls);
|
||||
println!("{}", status);
|
||||
std::thread::sleep(std::time::Duration::from_secs(repeat));
|
||||
|
||||
}
|
||||
} else {
|
||||
let status: uptime::UptimeStatus = uptime::check_status(&urls, success_ratio);
|
||||
println!("{}", uptime::display_uptime_status(&status));
|
||||
let status = uptime::UptimeStatus::new(success_ratio, &urls);
|
||||
println!("{}", status);
|
||||
}
|
||||
}
|
||||
NetCommands::Discover {} => {}
|
||||
|
|
|
@ -14,24 +14,21 @@
|
|||
// enable clippy's extra lints, the pedantic version
|
||||
#![warn(clippy::pedantic)]
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::{fmt, str::FromStr};
|
||||
|
||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
// we want the log macros in any case
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use reqwest;
|
||||
use reqwest::{self, Url};
|
||||
|
||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||
pub type UptimeStatus = (bool, usize, usize);
|
||||
|
||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||
/// urls used for checking by default
|
||||
pub const DEFAULT_CHECK_URLS: &'static [&'static str] = &[
|
||||
"https://www.cscherr.de",
|
||||
"https://www.cloudflare.com"
|
||||
];
|
||||
pub const DEFAULT_CHECK_URLS: &'static [&'static str] =
|
||||
&["https://www.cscherr.de", "https://www.cloudflare.com"];
|
||||
|
||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -40,79 +37,128 @@ pub const DEFAULT_CHECK_URLS: &'static [&'static str] = &[
|
|||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// ## Describes an uptime status
|
||||
///
|
||||
/// [`UptimeStatus`] describes the result of an uptime check.
|
||||
pub struct UptimeStatus {
|
||||
/// true if the [`UptimeStatus`] is considered successful
|
||||
success: bool,
|
||||
/// the percentage of reachable urls out of the total urls
|
||||
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.
|
||||
success_ratio_target: u8,
|
||||
/// the number of reachable [`urls`]
|
||||
reachable: usize,
|
||||
/// which urls to check in [`check()`]
|
||||
urls: Vec<Url>,
|
||||
}
|
||||
|
||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
/// ## check uptime status
|
||||
///
|
||||
/// This function checks the current network status.
|
||||
///
|
||||
/// ### Parameters
|
||||
/// additional_urls
|
||||
///
|
||||
/// ### Returns
|
||||
/// The function returns a tuple of the format
|
||||
///
|
||||
/// `(status: [bool], reachable: [usize], checked: [usize])`
|
||||
///
|
||||
/// #### `status`
|
||||
/// Will be `true` if the check is considered a success.
|
||||
pub fn check_status(urls_strs: &Vec<String>, percentage_for_success: u8) -> UptimeStatus {
|
||||
if percentage_for_success > 100 {
|
||||
panic!("percentage_for_success is over 100: {percentage_for_success}")
|
||||
}
|
||||
let status: bool;
|
||||
let mut reachable: usize = 0;
|
||||
let total: usize = urls_strs.len();
|
||||
|
||||
info!("checking with the following URLs: {:?}", urls_strs);
|
||||
|
||||
let mut urls: Vec<reqwest::Url> = Vec::new();
|
||||
for s in urls_strs {
|
||||
let url = reqwest::Url::from_str(&s);
|
||||
if url.is_ok() {
|
||||
urls.push(url.unwrap());
|
||||
} else {
|
||||
warn!("Invalid URL: '{}", s);
|
||||
impl UptimeStatus {
|
||||
/// ## create a new `UptimeStatus` and perform it's check
|
||||
pub fn new(success_ratio_target: u8, urls_str: &Vec<String>) -> Self {
|
||||
let mut status = UptimeStatus {
|
||||
success: false,
|
||||
success_ratio: 0,
|
||||
success_ratio_target,
|
||||
reachable: 0,
|
||||
urls: Vec::new(),
|
||||
};
|
||||
for s in urls_str {
|
||||
let url = reqwest::Url::from_str(&s);
|
||||
if url.is_ok() {
|
||||
status.urls.push(url.unwrap());
|
||||
} else {
|
||||
warn!("Invalid URL: '{}", s);
|
||||
}
|
||||
}
|
||||
}
|
||||
// make urls not mutable
|
||||
let urls = urls;
|
||||
|
||||
for url in urls {
|
||||
let response = reqwest::blocking::get(url);
|
||||
if response.is_ok() {
|
||||
reachable += 1
|
||||
status.check();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/// ## check for success with the given urls
|
||||
///
|
||||
/// Makes the actual https requests and updates the success fields.
|
||||
pub fn check(&mut self) {
|
||||
self.reachable = 0;
|
||||
self.urls.iter().for_each(|url| {
|
||||
let response = reqwest::blocking::get(url.clone());
|
||||
if response.is_ok() {
|
||||
self.reachable += 1
|
||||
}
|
||||
});
|
||||
self.calc_success();
|
||||
}
|
||||
|
||||
/// ## calculate the success based on the `reachable` and `total`
|
||||
///
|
||||
/// Calculates the ratio of [`reachable`](UptimeStatus::reachable) /
|
||||
/// [`total`](UptimeStatus::total).
|
||||
///
|
||||
/// Calculates a [`success_ratio`](UptimeStatus::success_ratio) (as [u8]) from that,
|
||||
/// by multiplying with 100, then flooring.
|
||||
///
|
||||
/// If the [`success_ratio`](UptimeStatus::success_ratio) is greater than or equal to the
|
||||
/// [`success_ratio_target`](UptimeStatus::success_ratio_target), the [`UptimeStatus`] will be
|
||||
/// considered a success.
|
||||
///
|
||||
/// In the special case that no URLs to check for have been provided, the check will be
|
||||
/// considered a success, but the [`success_ratio`](UptimeStatus::success_ratio) will be `0`.
|
||||
///
|
||||
/// Note: does not check for networking, use [`check()`] for that.
|
||||
pub fn calc_success(&mut self) {
|
||||
// if no urls need to be checked, success without checking
|
||||
if self.urls.len() == 0 {
|
||||
self.success = true;
|
||||
self.success_ratio = 0;
|
||||
return;
|
||||
}
|
||||
let ratio: f32 = (self.reachable as f32) / (self.urls.len() as f32) * 100f32;
|
||||
debug!("calculated success_ratio: {}", ratio);
|
||||
self.success_ratio = ratio.floor() as u8;
|
||||
self.success = self.success_ratio >= self.success_ratio_target;
|
||||
}
|
||||
|
||||
// evaluate the status
|
||||
if total != 0 {
|
||||
info!("reachability ratio: {}", ((reachable as f32) / total as f32) * 100f32);
|
||||
status = ((reachable as f32) / total as f32) * 100f32 >= percentage_for_success as f32;
|
||||
} else {
|
||||
// no reachable domains at all!
|
||||
info!("no valid services given");
|
||||
status = true;
|
||||
}
|
||||
|
||||
return (status, reachable, total);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// ## display UptimeStatus
|
||||
///
|
||||
/// returns a fancy string that shows the UptimeStatus, so you can print it to the user.
|
||||
pub fn display_uptime_status(status: &UptimeStatus) -> String {
|
||||
format!(
|
||||
r"{{
|
||||
success: {},
|
||||
reachable: {},
|
||||
checked: {}
|
||||
}}",
|
||||
status.0, status.1, status.2
|
||||
)
|
||||
impl fmt::Debug for UptimeStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{{
|
||||
success: {},
|
||||
success_ratio: {}%,
|
||||
success_ratio_target: {}%,
|
||||
reachable: {},
|
||||
urls: {:?}\n}}",
|
||||
self.success, self.success_ratio, self.success_ratio_target, self.reachable, self.urls
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
impl fmt::Display for UptimeStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut url_strs: Vec<&str> = Vec::new();
|
||||
for url in &self.urls {
|
||||
url_strs.push(url.as_str());
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{{
|
||||
success: {},
|
||||
success_ratio: {}%,
|
||||
success_ratio_target: {}%,
|
||||
reachable: {},
|
||||
urls: {:?}\n}}",
|
||||
self.success, self.success_ratio, self.success_ratio_target, self.reachable, url_strs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Reference in New Issue