intiial import of new code
This commit is contained in:
		
							
								
								
									
										44
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										44
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1,5 +1,7 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
|  | ||||
| [[package]] | ||||
| name = "ansi_term" | ||||
| version = "0.11.0" | ||||
| @ -445,27 +447,6 @@ dependencies = [ | ||||
|  "winapi", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "peshming" | ||||
| version = "0.4.1" | ||||
| dependencies = [ | ||||
|  "anyhow", | ||||
|  "async-anyhow-logger", | ||||
|  "chrono", | ||||
|  "clap", | ||||
|  "fern", | ||||
|  "futures", | ||||
|  "futures-util", | ||||
|  "hyper", | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "prometheus", | ||||
|  "serde", | ||||
|  "tokio", | ||||
|  "tokio-icmp-echo", | ||||
|  "toml", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "pin-project" | ||||
| version = "1.0.7" | ||||
| @ -604,6 +585,27 @@ dependencies = [ | ||||
|  "bitflags", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rexaping" | ||||
| version = "0.4.1" | ||||
| dependencies = [ | ||||
|  "anyhow", | ||||
|  "async-anyhow-logger", | ||||
|  "chrono", | ||||
|  "clap", | ||||
|  "fern", | ||||
|  "futures", | ||||
|  "futures-util", | ||||
|  "hyper", | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "prometheus", | ||||
|  "serde", | ||||
|  "tokio", | ||||
|  "tokio-icmp-echo", | ||||
|  "toml", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "scopeguard" | ||||
| version = "1.1.0" | ||||
|  | ||||
							
								
								
									
										12
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Cargo.toml
									
									
									
									
									
								
							| @ -1,12 +1,12 @@ | ||||
| [package] | ||||
| name = "peshming" | ||||
| version = "0.4.1" | ||||
| name = "rexaping" | ||||
| version = "0.5.0" | ||||
| license = "AGPL-3.0-only" | ||||
| authors = ["Jan Christian Grünhage <jan.christian@gruenhage.xyz>"] | ||||
| repository = "https://git.jcg.re/jcgruenhage/peshming" | ||||
| authors = ["Marek Isalski <marek@faelix.net>", "Jan Christian Grünhage <jan.christian@gruenhage.xyz>"] | ||||
| repository = "https://gitea.faelix.net/FAELIX/rexaping" | ||||
| keywords = ["ping", "icmp", "prometheus"] | ||||
| edition = "2018" | ||||
| description = "Pings configured hosts in a configurable intervals and exposes metrics for prometheus." | ||||
| edition = "2021" | ||||
| description = "Pings configured hosts in a configurable intervals and labels, and exposes metrics for prometheus." | ||||
|  | ||||
| [dependencies] | ||||
| prometheus = "0.12" | ||||
|  | ||||
							
								
								
									
										19
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.md
									
									
									
									
									
								
							| @ -1,21 +1,22 @@ | ||||
| ## peshming | ||||
| ## rexaping | ||||
| It's a prometheus exporter pinging hosts in the background. | ||||
| It's been inspired by [meshping](https://bitbucket.org/Svedrin/meshping), | ||||
| but instead of managing targets using a redis db this is using a simple config file. | ||||
| In addition, this tool allows to set a ping frequency per target. | ||||
| It's been forked from [peshming](https://git.jcg.re/jcgruenhage/peshming), | ||||
| but only allowing targets to specify an interval, the config file can enrich | ||||
| the Prometheus metrics with additional labels. | ||||
|  | ||||
| The name peshming is intended as a placeholder until | ||||
| someone comes up with something better. | ||||
| The name rexaping is a play on exaping, a tool with the same purpose | ||||
| originally written in Python for Exa Networks. | ||||
|  | ||||
| ### Usage: | ||||
| ``` | ||||
| $ peshming --help | ||||
| peshming 0.2.3 | ||||
| $ rexaping --help | ||||
| rexaping 0.2.3 | ||||
| Marek Isalski <marek@faelix.net> | ||||
| Jan Christian Grünhage <jan.christian@gruenhage.xyz> | ||||
| Pings configured hosts in a configurable intervals and exposes metrics for prometheus. | ||||
|  | ||||
| USAGE: | ||||
|     peshming [FLAGS] <config> | ||||
|     rexaping [FLAGS] <config> | ||||
|  | ||||
| FLAGS: | ||||
|     -h, --help       Prints help information | ||||
|  | ||||
| @ -7,5 +7,5 @@ listener = "[::]:9898" | ||||
| # will ping the primary and secondary IP of cloudflare's 1.1.1.1 DNS service | ||||
| # every 500ms, or twice per second. | ||||
| [hosts] | ||||
| "1.1.1.1" = 500 | ||||
| "1.0.0.1" = 500 | ||||
| "1.1.1.1" = { interval = "500", device = "one.one.one.one", interface="eth1111" } | ||||
| "1.0.0.1" = { interval = "500", device = "one.one.one.one", interface="eth1001" } | ||||
|  | ||||
| @ -3,6 +3,7 @@ | ||||
|  *                                                                              * | ||||
|  *   Copyright (C) 2019-2020 Jan Christian Grünhage                             * | ||||
|  *   Copyright (C) 2020 Famedly GmbH                                            * | ||||
|  *   Copyright (C) 2021-2022 Faelix Limited                                     * | ||||
|  *                                                                              * | ||||
|  *   This program is free software: you can redistribute it and/or modify       * | ||||
|  *   it under the terms of the GNU Affero General Public License as             * | ||||
| @ -26,7 +27,7 @@ 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>, | ||||
|     pub(crate) hosts: HashMap<std::net::IpAddr, HashMap<String, String>>, | ||||
| } | ||||
|  | ||||
| fn setup_clap() -> clap::ArgMatches<'static> { | ||||
|  | ||||
| @ -3,6 +3,7 @@ | ||||
|  *                                                                              * | ||||
|  *   Copyright (C) 2019-2020 Jan Christian Grünhage                             * | ||||
|  *   Copyright (C) 2020 Famedly GmbH                                            * | ||||
|  *   Copyright (C) 2021-2022 Faelix Limited                                     * | ||||
|  *                                                                              * | ||||
|  *   This program is free software: you can redistribute it and/or modify       * | ||||
|  *   it under the terms of the GNU Affero General Public License as             * | ||||
|  | ||||
| @ -3,6 +3,7 @@ | ||||
|  *                                                                              * | ||||
|  *   Copyright (C) 2019-2020 Jan Christian Grünhage                             * | ||||
|  *   Copyright (C) 2020 Famedly GmbH                                            * | ||||
|  *   Copyright (C) 2021-2022 Faelix Limited                                     * | ||||
|  *                                                                              * | ||||
|  *   This program is free software: you can redistribute it and/or modify       * | ||||
|  *   it under the terms of the GNU Affero General Public License as             * | ||||
|  | ||||
							
								
								
									
										58
									
								
								src/ping.rs
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/ping.rs
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ | ||||
|  *                                                                              * | ||||
|  *   Copyright (C) 2019-2020 Jan Christian Grünhage                             * | ||||
|  *   Copyright (C) 2020 Famedly GmbH                                            * | ||||
|  *   Copyright (C) 2021-2022 Faelix Limited                                     * | ||||
|  *                                                                              * | ||||
|  *   This program is free software: you can redistribute it and/or modify       * | ||||
|  *   it under the terms of the GNU Affero General Public License as             * | ||||
| @ -21,39 +22,54 @@ use crate::config::Config; | ||||
| use anyhow::{Context, Result}; | ||||
| use async_anyhow_logger::catch; | ||||
| use lazy_static::lazy_static; | ||||
| use log::{info, trace}; | ||||
| use log::{trace}; | ||||
| use prometheus::*; | ||||
| use std::net::IpAddr; | ||||
| use std::time::Duration; | ||||
| use tokio_icmp_echo::{PingFuture, Pinger}; | ||||
| use std::collections::HashMap; | ||||
|  | ||||
| lazy_static! { | ||||
|     static ref PING_HISTOGRAM: HistogramVec = register_histogram_vec!( | ||||
|         "ping_rtt_milliseconds", | ||||
|         "The ping round trip time in milliseconds", | ||||
|         &["target"], | ||||
|         &["target", "device", "interface", "expected", "team", "priority"], | ||||
|         vec![ | ||||
|             0.5, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 50.0, 75.0, 100.0, 150.0, 200.0, 250.0, 300.0, | ||||
|             350.0, 400.0, 450.0, 500.0, 550.0, 600.0, 650.0, 700.0, 750.0, 800.0, 900.0, 1000.0, | ||||
|             1250.0, 1500.0, 1750.0, 2000.0 | ||||
|             0.125, 0.25, 0.5, 1.0, 1.5, 2.0, 2.5, 5.0, 7.5, 10.0, 15.0, 20.0, 25.0, 30.0, | ||||
|             35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 90.0, 100.0, | ||||
|             125.0, 150.0, 175.0, 200.0, 250.0, 300.0, 400.0, 500.0, 750.0, 1000.0, 2000.0, 4000.0 | ||||
|         ] | ||||
|     ) | ||||
|     .unwrap(); | ||||
| } | ||||
|  | ||||
| lazy_static! { | ||||
|     static ref PING_COUNTER: IntCounterVec = | ||||
|         register_int_counter_vec!("ping_replies", "Number of ICMP ping responses received", &["target"]).unwrap(); | ||||
| } | ||||
|  | ||||
| pub(crate) async fn start_pinging_hosts(config: &Config) -> Result<()> { | ||||
|     let pinger = Pinger::new().await.context("Couldn't create pinger")?; | ||||
|     let mut handles = vec![]; | ||||
|     for (host, interval) in config.hosts.clone() { | ||||
|         info!("Spawn ping task for {}", host); | ||||
|         handles.push(tokio::spawn(ping_host(pinger.clone(), host, interval))); | ||||
|     let mut interval; | ||||
|  | ||||
|     for (target, hostdata) in config.hosts.clone() { | ||||
|         let hd_interval = hostdata.get("interval"); | ||||
|         match hd_interval { | ||||
|             Some(ival) => { | ||||
|                 interval = ival.parse()?; | ||||
|             }, | ||||
|             _ => interval = 1000, | ||||
|         } | ||||
|  | ||||
|         handles.push(tokio::spawn(ping_host(pinger.clone(), target, interval, hostdata))); | ||||
|     } | ||||
|     let (result, _, _) = futures::future::select_all(handles).await; | ||||
|     result??; | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| async fn ping_host(pinger: Pinger, host: IpAddr, interval: u64) -> Result<()> { | ||||
| async fn ping_host(pinger: Pinger, host: IpAddr, interval: u64, hostdata: HashMap<String, String>) -> Result<()> { | ||||
|     let mut pingchain = pinger.chain(host).timeout(Duration::from_secs(3)); | ||||
|     let mut interval = tokio::time::interval(Duration::from_millis(interval)); | ||||
|     let host_string = host.to_string(); | ||||
| @ -62,23 +78,41 @@ async fn ping_host(pinger: Pinger, host: IpAddr, interval: u64) -> Result<()> { | ||||
|         tokio::spawn(catch(handle_ping_result( | ||||
|             pingchain.send(), | ||||
|             host_string.clone(), | ||||
|             hostdata.clone(), | ||||
|         ))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| async fn handle_ping_result(result: PingFuture, host: String) -> Result<()> { | ||||
| async fn handle_ping_result(result: PingFuture, host: String, hostdata: HashMap<String, String>) -> Result<()> { | ||||
|     let pong = result.await.context(format!("Couldn't ping {}", &host))?; | ||||
|  | ||||
|     let empty = "".to_string(); | ||||
|     let device = hostdata.get("device").unwrap_or(&empty); | ||||
|     let interface = hostdata.get("interface").unwrap_or(&empty); | ||||
|     let team = hostdata.get("team").unwrap_or(&empty); | ||||
|  | ||||
|     let up = "up".to_string(); | ||||
|     let expected = hostdata.get("expected").unwrap_or(&up); | ||||
|  | ||||
|     let notice = "notice".to_string(); | ||||
|     let severity = hostdata.get("severity").unwrap_or(¬ice); | ||||
|  | ||||
|     match pong { | ||||
|         Some(time) => { | ||||
|             let ms = time.as_millis(); | ||||
|             trace!("Received pong from {} after {} ms", &host, &ms); | ||||
|             PING_HISTOGRAM | ||||
|                 .with_label_values(&[&host]) | ||||
|                 .with_label_values(&[&host, device, interface, expected, team, severity]) | ||||
|                 .observe(ms as f64); | ||||
|             //PING_COUNTER | ||||
|             //    .with_label_values(&[&host]) | ||||
|             //    .collect(); | ||||
|         } | ||||
|         None => { | ||||
|             trace!("Received no response from {} within timeout", &host); | ||||
|             PING_HISTOGRAM.with_label_values(&[&host]).observe(3000.0); | ||||
|             PING_HISTOGRAM | ||||
|                 .with_label_values(&[&host, device, interface, expected, team, severity]) | ||||
|                 .observe(4000.0); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user