healthchecks-rs/hcctl/src/main.rs

131 lines
3.4 KiB
Rust

#[macro_use]
extern crate prettytable;
use std::env::var;
use std::time::SystemTime;
use chrono::prelude::{DateTime, Datelike, Timelike};
use chrono::Duration;
use clap::{crate_version, Clap};
use prettytable::{format, Table};
use healthchecks::manage;
#[derive(Debug)]
struct Settings {
token: String,
ua: Option<String>,
}
/// Command-line tool for interacting with a https://healthchecks.io account
#[derive(Clap)]
#[clap(version = crate_version!())]
struct Opts {
#[clap(subcommand)]
subcommand: SubCommand,
}
#[derive(Clap)]
enum SubCommand {
List(List),
Pings(Pings),
}
/// Lists the checks in your account with their last ping
#[derive(Clap)]
struct List {}
/// Get the last 10 pings for the given check ID
#[derive(Clap)]
struct Pings {
/// ID of the check whose pings are being fetched
check_id: String,
}
fn main() -> anyhow::Result<()> {
let ua = match var("HEALTHCHECKS_USERAGENT") {
Ok(f) => Some(f),
Err(_) => None,
};
let settings = Settings {
token: var("HEALTHCHECKS_TOKEN").expect("HEALTHCHECKS_TOKEN must be set to run monitor"),
ua,
};
let opts = Opts::parse();
match opts.subcommand {
SubCommand::List(_) => {
list(settings)?;
}
SubCommand::Pings(p) => {
pings(settings, &p.check_id)?;
}
}
Ok(())
}
fn pings(settings: Settings, check_id: &str) -> anyhow::Result<()> {
let api = manage::get_config(settings.token, settings.ua)?;
let mut pings = api.list_logged_pings(check_id)?;
let mut table = Table::new();
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.set_titles(row!["Number", "Time", "Type", "Duration"]);
pings.truncate(10);
for ping in pings {
let utc_time = DateTime::parse_from_rfc3339(&ping.date)?.naive_utc();
let date = utc_time.date();
let time = utc_time.time();
let time_str = format!(
"{}/{} {}:{}",
date.day(),
date.month(),
time.hour(),
time.minute(),
);
let duration_str = if let Some(duration) = ping.duration {
format!("{0:.3} sec", duration)
} else {
"".to_owned()
};
table.add_row(row![
format!("#{}", ping.n),
time_str,
ping.type_field,
duration_str
]);
}
table.printstd();
Ok(())
}
fn list(settings: Settings) -> anyhow::Result<()> {
let api = manage::get_config(settings.token, settings.ua)?;
let checks = api.get_checks()?;
let mut table = Table::new();
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.set_titles(row!["ID", "Name", "Last Ping"]);
let now = SystemTime::now();
for check in checks {
let date = if let Some(ref date_str) = check.last_ping {
let date = DateTime::parse_from_rfc3339(&date_str)?;
let duration = Duration::from_std(now.duration_since(SystemTime::from(date))?)?;
format!(
"{} hour(s) and {} minute(s) ago",
duration.num_hours(),
duration.num_minutes()
)
} else {
"-".to_owned()
};
let id = check.id().unwrap_or_else(|| "-".to_owned());
table.add_row(row![id, check.name, date]);
}
table.printstd();
Ok(())
}