From a16e326b24d361126071dddd6411d710535495d3 Mon Sep 17 00:00:00 2001 From: Uggla Date: Fri, 10 Jun 2022 01:01:39 +0200 Subject: [PATCH 1/2] feat: Refactor riemann exporters - Refactor to use MetricGenerator. --- src/exporters/riemann.rs | 87 +++++++++++++--------------------------- 1 file changed, 27 insertions(+), 60 deletions(-) diff --git a/src/exporters/riemann.rs b/src/exporters/riemann.rs index d8cdb76b..7d81a1bb 100644 --- a/src/exporters/riemann.rs +++ b/src/exporters/riemann.rs @@ -10,7 +10,6 @@ use clap::Arg; use riemann_client::proto::Attribute; use riemann_client::proto::Event; use riemann_client::Client; -use std::collections::HashMap; use std::convert::TryFrom; use std::thread; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -138,9 +137,8 @@ impl Exporter for RiemannExporter { println!("Press CTRL-C to stop scaphandre"); println!("Measurement step is: {}s", dispatch_duration); - let topology = self.sensor.get_topology().unwrap(); let mut metric_generator = MetricGenerator::new( - topology, + self.sensor.get_topology().unwrap(), hostname, parameters.is_present("qemu"), parameters.is_present("containers"), @@ -164,66 +162,27 @@ impl Exporter for RiemannExporter { metric_generator.topology.refresh(); info!("{}: Refresh data", Utc::now().format("%Y-%m-%dT%H:%M:%S")); - // Here we need a specific behavior for process metrics, so we call each gen function - // and then implement that specific behavior (we don't use gen_all_metrics). - metric_generator.gen_self_metrics(); - metric_generator.gen_host_metrics(); - metric_generator.gen_socket_metrics(); + metric_generator.gen_all_metrics(); - let mut data = vec![]; - let processes_tracker = &metric_generator.topology.proc_tracker; - - for pid in processes_tracker.get_alive_pids() { - let exe = processes_tracker.get_process_name(pid); - let cmdline = processes_tracker.get_process_cmdline(pid); - - let mut attributes = HashMap::new(); - attributes.insert("pid".to_string(), pid.to_string()); - - attributes.insert("exe".to_string(), exe.clone()); - - if let Some(cmdline_str) = cmdline { - attributes.insert("cmdline".to_string(), cmdline_str.replace('\"', "\\\"")); - - if parameters.is_present("qemu") { - if let Some(vmname) = utils::filter_qemu_cmdline(&cmdline_str) { - attributes.insert("vmname".to_string(), vmname); - } - } - } - - // Here we define a metric name with pid + exe string suffix as riemann needs - // to differentiate services/metrics - let metric_name = format!( - "{}_{}_{}", - "scaph_process_power_consumption_microwatts", pid, exe - ); - if let Some(power) = metric_generator - .topology - .get_process_power_consumption_microwatts(pid) - { - data.push(Metric { - name: metric_name, - metric_type: String::from("gauge"), - ttl: 60.0, - hostname: get_hostname(), - timestamp: power.timestamp, - state: String::from("ok"), - tags: vec!["scaphandre".to_string()], - attributes, - description: String::from("Power consumption due to the process, measured on at the topology level, in microwatts"), - metric_value: MetricValueType::Text(power.value), - }); - } - } // Send all data info!("{}: Send data", Utc::now().format("%Y-%m-%dT%H:%M:%S")); - for metric in metric_generator.pop_metrics() { - rclient.send_metric(&metric); - } - for metric in data { - rclient.send_metric(&metric); - } + metric_generator + .pop_metrics() + .iter_mut() + .map(|mut metric| { + // Here we define a metric name with pid + exe string suffix as riemann needs + // to differentiate services/metrics + if metric.name == "scaph_process_power_consumption_microwatts" { + metric.name = format!( + "{}_{}_{}", + "scaph_process_power_consumption_microwatts", + metric.attributes.get("pid").unwrap(), + metric.attributes.get("exe").unwrap() + ) + } + metric + }) + .for_each(|metric| rclient.send_metric(metric)); thread::sleep(Duration::new(dispatch_duration, 0)); } @@ -267,6 +226,13 @@ impl Exporter for RiemannExporter { .takes_value(false); options.push(arg); + let arg = Arg::with_name("containers") + .help("Monitor and apply labels for processes running as containers") + .long("containers") + .required(false) + .takes_value(false); + options.push(arg); + let arg = Arg::with_name("mtls") .help("Connect to a Riemann server using mTLS. Parameters address, ca, cert and key must be defined.") .long("mtls") @@ -319,3 +285,4 @@ impl Exporter for RiemannExporter { // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// From 0df79136d35c589e01b22c04b8c3fb7c1a5b0f75 Mon Sep 17 00:00:00 2001 From: Uggla Date: Sun, 17 Jul 2022 19:08:11 +0200 Subject: [PATCH 2/2] fix: Clippy warning - Fix clippy warning from rust 1.62. --- src/exporters/prometheus.rs | 11 ++++++----- src/exporters/stdout.rs | 7 +++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/exporters/prometheus.rs b/src/exporters/prometheus.rs index 5651e70f..0eab8823 100644 --- a/src/exporters/prometheus.rs +++ b/src/exporters/prometheus.rs @@ -11,6 +11,7 @@ use clap::{Arg, ArgMatches}; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server}; use std::convert::Infallible; +use std::fmt::Write; use std::{ collections::HashMap, net::{IpAddr, SocketAddr}, @@ -194,12 +195,12 @@ fn format_metric(key: &str, value: &str, labels: Option<&HashMap if let Some(labels) = labels { result.push('{'); for (k, v) in labels.iter() { - result.push_str(&format!("{}=\"{}\",", k, v.replace('\"', "_"))); + write!(result, "{}=\"{}\",", k, v.replace('\"', "_")).unwrap(); } result.remove(result.len() - 1); result.push('}'); } - result.push_str(&format!(" {}\n", value)); + writeln!(result, " {}", value).unwrap(); result } @@ -211,8 +212,8 @@ fn push_metric( metric_name: String, metric_line: String, ) -> String { - body.push_str(&format!("# HELP {} {}", metric_name, help)); - body.push_str(&format!("\n# TYPE {} {}\n", metric_name, metric_type)); + write!(body, "# HELP {} {}", metric_name, help).unwrap(); + writeln!(body, "\n# TYPE {} {}", metric_name, metric_type).unwrap(); body.push_str(&metric_line); body } @@ -272,7 +273,7 @@ async fn show_metrics( ); } } else { - body.push_str(&format!("Scaphandre's prometheus exporter here. Metrics available on /{}", suffix, suffix)); + write!(body,"Scaphandre's prometheus exporter here. Metrics available on /{}", suffix, suffix).unwrap(); } Ok(Response::new(body.into())) } diff --git a/src/exporters/stdout.rs b/src/exporters/stdout.rs index 85be82a3..72e72ea0 100644 --- a/src/exporters/stdout.rs +++ b/src/exporters/stdout.rs @@ -4,6 +4,7 @@ use crate::exporters::*; use crate::sensors::Sensor; use colored::*; use regex::Regex; +use std::fmt::Write; use std::thread; use std::time::{Duration, Instant}; @@ -211,7 +212,8 @@ impl StdoutExporter { } false }) { - to_print.push_str(&format!( + write!( + to_print, "{} W\t", current_domain .metric_value @@ -219,7 +221,8 @@ impl StdoutExporter { .parse::() .unwrap() / 1000000.0 - )); + ) + .unwrap() } else { to_print.push_str("---"); }