|
|
|
/********************************************************************************
|
|
|
|
* Prometheus exporter for monitoring network connectivity using icmp pings *
|
|
|
|
* *
|
|
|
|
* Copyright (C) 2019-2020 Jan Christian Grünhage *
|
|
|
|
* Copyright (C) 2020 Famedly GmbH *
|
|
|
|
* *
|
|
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU Affero General Public License as *
|
|
|
|
* published by the Free Software Foundation, either version 3 of the *
|
|
|
|
* License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU Affero General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU Affero General Public License *
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
|
|
********************************************************************************/
|
|
|
|
use anyhow::{Context, Result};
|
|
|
|
use clap::{clap_app, crate_authors, crate_description, crate_name, crate_version};
|
|
|
|
use log::info;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
|
|
pub(crate) struct Config {
|
|
|
|
pub(crate) listener: std::net::SocketAddr,
|
|
|
|
pub(crate) hosts: HashMap<std::net::IpAddr, u64>,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_clap() -> clap::ArgMatches<'static> {
|
|
|
|
clap_app!(myapp =>
|
|
|
|
(name: crate_name!())
|
|
|
|
(version: crate_version!())
|
|
|
|
(author: crate_authors!())
|
|
|
|
(about: crate_description!())
|
|
|
|
(@arg config: +required "Set config file")
|
|
|
|
(@arg v: -v --verbose ... "Be verbose (you can add this up to 4 times for more logs).
|
|
|
|
By default, only errors are logged, so no output is a good thing.")
|
|
|
|
)
|
|
|
|
.get_matches()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_fern(level: u64) {
|
|
|
|
let level = match level {
|
|
|
|
0 => log::LevelFilter::Error,
|
|
|
|
1 => log::LevelFilter::Warn,
|
|
|
|
2 => log::LevelFilter::Info,
|
|
|
|
3 => log::LevelFilter::Debug,
|
|
|
|
_ => log::LevelFilter::Trace,
|
|
|
|
};
|
|
|
|
match fern::Dispatch::new()
|
|
|
|
.format(|out, message, record| {
|
|
|
|
out.finish(format_args!(
|
|
|
|
"[{}][{}] {}",
|
|
|
|
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
|
|
|
|
record.level(),
|
|
|
|
message
|
|
|
|
))
|
|
|
|
})
|
|
|
|
.level(level)
|
|
|
|
.chain(std::io::stdout())
|
|
|
|
.apply()
|
|
|
|
{
|
|
|
|
Err(_) => {
|
|
|
|
eprintln!("error setting up logging!");
|
|
|
|
}
|
|
|
|
_ => info!("logging set up properly"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_config(path: &str) -> Result<Config> {
|
|
|
|
let config_file_content = std::fs::read_to_string(path).context("Couldn't read config file")?;
|
|
|
|
Ok(toml::from_str(&config_file_content).context("Couldn't parse config file")?)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn setup_app() -> Result<Config> {
|
|
|
|
let clap = setup_clap();
|
|
|
|
setup_fern(clap.occurrences_of("v"));
|
|
|
|
let config_path = clap
|
|
|
|
.value_of("config")
|
|
|
|
.context("Got no config file. clap should've catched this")?;
|
|
|
|
Ok(read_config(config_path).context("Couldn't read config file!")?)
|
|
|
|
}
|