Skip to content

Commit

Permalink
Merge pull request #284 from hubblo-org/uggla-bump_clap4
Browse files Browse the repository at this point in the history
Uggla bump clap4
  • Loading branch information
bpetit authored Mar 27, 2023
2 parents ba5b2a8 + 444b3c6 commit 0d32d12
Show file tree
Hide file tree
Showing 12 changed files with 735 additions and 598 deletions.
849 changes: 495 additions & 354 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ homepage = "https://hubblo-org.github.io/scaphandre-documentation"
[dependencies]
loggerv = "0.7.2"
log = "0.4"
clap = "2.33.3"
regex = "1"
# clap string feature is required to allow dynamic values otherwise it ended up with a lifetime pb.
# https://docs.rs/clap/4.0.19/clap/builder/struct.Str.html
clap = { version = "4.0.18", features = ["cargo", "string"] }
regex = "1.7.0"
riemann_client = { version = "0.9.0", optional = true }
hostname = "0.3.1"
protobuf = "2.20.0"
protobuf = "2.28.0"
serde = { version = "1.0", features = ["derive"], optional = true }
serde_json = { version = "1.0", optional = true }
ordered-float = "2.0"
warp10 = { version = "1.0.0", optional = true }
rand = { version = "0.7.3" }
#time = { version = "0.3.11", features = ["std"] }
#time blocked because used by chrono and warp10
time = "0.2.25"
colored = "2.0.0"
chrono = "0.4.19"
Expand All @@ -34,6 +38,7 @@ tokio = { version = "1.26.0", features = ["full"], optional = true}
sysinfo = { version = "0.28.3"}

[target.'cfg(target_os="linux")'.dependencies]
#procfs = "0.13.2"
procfs = { version = "0.12.0" }

[target.'cfg(target_os="windows")'.dependencies]
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM rust:1.59 as planner
FROM rust:1.68 as planner
WORKDIR app

RUN cargo install cargo-chef
Expand All @@ -7,15 +7,15 @@ COPY . .
# Analyze dependencies
RUN cargo chef prepare --recipe-path recipe.json

FROM rust:1.59 as cacher
FROM rust:1.68 as cacher
WORKDIR app
RUN cargo install cargo-chef
COPY --from=planner /app/recipe.json recipe.json

# Cache dependencies
RUN cargo chef cook --release --recipe-path recipe.json

FROM rust:1.59 as builder
FROM rust:1.68 as builder
WORKDIR app
COPY . .

Expand Down
107 changes: 54 additions & 53 deletions src/exporters/json.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::exporters::*;
use crate::sensors::Sensor;
use clap::Arg;
use clap::{parser::ValueSource, value_parser, Arg};
use colored::*;
use regex::Regex;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -28,84 +28,88 @@ impl Exporter for JSONExporter {

/// Returns options needed for that exporter, as a HashMap
fn get_options() -> Vec<clap::Arg<'static, 'static>> {
fn get_options() -> Vec<clap::Arg> {
let mut options = Vec::new();
let arg = Arg::with_name("timeout")
let arg = Arg::new("timeout")
.help("Maximum time spent measuring, in seconds.")
.long("timeout")
.short("t")
.short('t')
.required(false)
.takes_value(true);
.value_parser(value_parser!(u64))
.action(clap::ArgAction::Set);
options.push(arg);

let arg = Arg::with_name("step_duration")
let arg = Arg::new("step_duration")
.default_value("2")
.help("Set measurement step duration in second.")
.long("step")
.short("s")
.short('s')
.required(false)
.takes_value(true);
.value_parser(value_parser!(u64))
.action(clap::ArgAction::Set);
options.push(arg);

let arg = Arg::with_name("step_duration_nano")
let arg = Arg::new("step_duration_nano")
.default_value("0")
.help("Set measurement step duration in nano second.")
.long("step_nano")
.short("n")
.short('n')
.required(false)
.takes_value(true);
.value_parser(value_parser!(u32))
.action(clap::ArgAction::Set);
options.push(arg);

let arg = Arg::with_name("file_path")
let arg = Arg::new("file_path")
.default_value("")
.help("Destination file for the report.")
.long("file")
.short("f")
.short('f')
.required(false)
.takes_value(true);
.action(clap::ArgAction::Set);
options.push(arg);

let arg = Arg::with_name("max_top_consumers")
let arg = Arg::new("max_top_consumers")
.default_value("10")
.help("Maximum number of processes to watch.")
.long("max-top-consumers")
.short("m")
.short('m')
.required(false)
.takes_value(true);
.value_parser(value_parser!(u16))
.action(clap::ArgAction::Set);
options.push(arg);

#[cfg(feature = "containers")]
{
let arg = Arg::with_name("containers")
let arg = Arg::new("containers")
.help("Monitor and apply labels for processes running as containers")
.short("c")
.short('c')
.long("containers")
.required(false)
.takes_value(false);
.action(clap::ArgAction::Set);
options.push(arg);
}

let arg = Arg::with_name("regex_filter")
let arg = Arg::new("regex_filter")
.help("Filter processes based on regular expressions (e.g: 'scaph\\w\\wd.e').")
.long("regex")
.short("r")
.short('r')
.required(false)
.takes_value(true);
.action(clap::ArgAction::Set);
options.push(arg);

let arg = Arg::with_name("resources")
let arg = Arg::new("resources")
.help("Monitor and include CPU/RAM/Disk usage per process.")
.long("resources")
.required(false);
options.push(arg);

#[cfg(feature = "containers")]
{
let arg = Arg::with_name("container_regex")
let arg = Arg::new("container_regex")
.help("Filter process by container name based on regular expressions (e.g: 'scaph\\w\\wd.e'). Works only with --containers enabled.")
.long("container-regex")
.required(false)
.takes_value(true);
.action(clap::ArgAction::Set);
options.push(arg);
}

Expand All @@ -117,7 +121,6 @@ impl Exporter for JSONExporter {
// .required(false)
// .takes_value(false);
//options.push(arg);

options
}
}
Expand Down Expand Up @@ -211,54 +214,53 @@ impl JSONExporter {
let mut metric_generator = MetricGenerator::new(
topology,
utils::get_hostname(),
parameters.is_present("qemu"),
parameters.is_present("containers"),
parameters.get_flag("qemu"),
parameters.get_flag("containers"),
);

// We have a default value of 2s so it is safe to unwrap the option
// Panic if a non numerical value is passed
let step_duration: u64 = parameters
.value_of("step_duration")
.unwrap()
.parse()
let step_duration: u64 = *parameters
.get_one("step_duration")
.expect("Wrong step_duration value, should be a number of seconds");
let step_duration_nano: u32 = parameters
.value_of("step_duration_nano")
.unwrap()
.parse()
let step_duration_nano: u32 = *parameters
.get_one("step_duration_nano")
.expect("Wrong step_duration_nano value, should be a number of nano seconds");

self.regex = if !parameters.is_present("regex_filter")
|| parameters.value_of("regex_filter").unwrap().is_empty()
self.regex = if !parameters.get_flag("regex_filter")
|| parameters
.get_one::<String>("regex_filter")
.unwrap()
.is_empty()
{
None
} else {
Some(
Regex::new(parameters.value_of("regex_filter").unwrap())
Regex::new(parameters.get_one::<String>("regex_filter").unwrap())
.expect("Wrong regex_filter, regexp is invalid"),
)
};

if parameters.occurrences_of("regex_filter") == 1
&& parameters.occurrences_of("max_top_consumers") == 1
if parameters.value_source("regex_filter") == Some(ValueSource::CommandLine)
&& parameters.value_source("max_top_consumers") == Some(ValueSource::CommandLine)
{
let warning =
String::from("Warning: (--max-top-consumers) and (-r / --regex) used at the same time. (--max-top-consumers) disabled");
eprintln!("{}", warning.bright_yellow());
}

#[cfg(feature = "containers")]
if !parameters.is_present("containers") && parameters.is_present("container_regex") {
if !parameters.get_flag("containers") && parameters.get_flag("container_regex") {
let warning =
String::from("Warning: --container-regex is used but --containers is not enabled. Regex search won't work.");
eprintln!("{}", warning.bright_yellow());
}

info!("Measurement step is: {}s", step_duration);
if let Some(timeout) = parameters.value_of("timeout") {
if let Some(timeout) = parameters.get_one::<u64>("timeout") {
let now = Instant::now();

let timeout_secs: u64 = timeout.parse().unwrap();
let timeout_secs: u64 = *timeout;
while now.elapsed().as_secs() <= timeout_secs {
self.iterate(&parameters, &mut metric_generator);
thread::sleep(Duration::new(step_duration, step_duration_nano));
Expand Down Expand Up @@ -384,8 +386,8 @@ impl JSONExporter {

let consumers: Vec<(IProcess, f64)>;
let max_top = parameters
.value_of("max_top_consumers")
.unwrap_or("10")
.get_one::<String>("max_top_consumers")
.unwrap_or(&String::from("10"))
.parse::<u16>()
.unwrap();
if let Some(regex_filter) = &self.regex {
Expand All @@ -394,11 +396,11 @@ impl JSONExporter {
.topology
.proc_tracker
.get_filtered_processes(regex_filter);
} else if parameters.is_present("container_regex") {
} else if parameters.get_flag("container_regex") {
#[cfg(feature = "containers")]
{
consumers = metric_generator.get_processes_filtered_by_container_name(
&Regex::new(parameters.value_of("container_regex").unwrap())
&Regex::new(parameters.get_one::<String>("container_regex").unwrap())
.expect("Wrong container_regex expression. Regexp is invalid."),
);
}
Expand Down Expand Up @@ -431,7 +433,7 @@ impl JSONExporter {
consumption: format!("{}", metric.metric_value).parse::<f32>().unwrap(),
resources_usage: None,
timestamp: metric.timestamp.as_secs_f64(),
container: match parameters.is_present("containers") {
container: match parameters.get_flag("containers") {
true => metric.attributes.get("container_id").map(|container_id| {
Container {
id: String::from(container_id),
Expand Down Expand Up @@ -461,8 +463,7 @@ impl JSONExporter {
})
.collect::<Vec<_>>();

if parameters.is_present("resources") {
info!("ADDING RESOURCES");
if parameters.get_flag("resources") {
for c in top_consumers.iter_mut() {
let mut res = ResourcesUsage {
cpu_usage: String::from("0"),
Expand Down Expand Up @@ -561,7 +562,7 @@ impl JSONExporter {
sockets: all_sockets,
};

let file_path = parameters.value_of("file_path").unwrap();
let file_path = parameters.get_one::<String>("file_path").unwrap();
// Print json
if file_path.is_empty() {
let json: String =
Expand Down
2 changes: 1 addition & 1 deletion src/exporters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub trait Exporter {
/// Entry point for all Exporters
fn run(&mut self, parameters: ArgMatches);
/// Get the options passed via the command line
fn get_options() -> Vec<clap::Arg<'static, 'static>>;
fn get_options() -> Vec<clap::Arg>;
}

/// MetricGenerator is an exporter helper structure to collect Scaphandre metrics.
Expand Down
Loading

0 comments on commit 0d32d12

Please sign in to comment.