Skip to content

Commit 8e6e2ae

Browse files
committed
feat(datadog): add tokio as optional dependency
Signed-off-by: Jérémie Drouet <[email protected]>
1 parent 7747f75 commit 8e6e2ae

File tree

4 files changed

+57
-29
lines changed

4 files changed

+57
-29
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ readme = "README.md"
1313

1414
[features]
1515
default = ["datadog"]
16-
datadog = ["datadog-client"]
16+
datadog = ["datadog-client", "tokio"]
1717

1818
[dependencies]
1919
loggerv = "0.7.2"
@@ -30,6 +30,7 @@ serde = { version = "1.0", features = ["derive"] }
3030
serde_json = "1.0"
3131

3232
datadog-client = { version = "0.1", optional = true }
33+
tokio = { version = "1", features = ["full"], optional = true }
3334

3435
[profile.release]
3536
lto = true

src/exporters/datadog.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use datadog_client::metrics::{Point, Serie, Type};
55
use std::collections::HashMap;
66
use std::thread;
77
use std::time::{Duration, Instant};
8+
use tokio::runtime::Runtime;
89

910
fn merge<A>(first: Vec<A>, second: Vec<A>) -> Vec<A> {
1011
second.into_iter().fold(first, |mut res, item| {
@@ -32,7 +33,10 @@ pub struct DatadogExporter {
3233
impl Exporter for DatadogExporter {
3334
/// Lanches runner()
3435
fn run(&mut self, parameters: ArgMatches) {
35-
self.runner(&parameters);
36+
let rt = Runtime::new().unwrap();
37+
rt.block_on(async move {
38+
self.runner(&parameters).await;
39+
});
3640
}
3741

3842
/// Returns options needed for that exporter, as a HashMap
@@ -87,7 +91,7 @@ impl DatadogExporter {
8791
Client::new(config)
8892
}
8993

90-
fn runner(&mut self, parameters: &ArgMatches) {
94+
async fn runner(&mut self, parameters: &ArgMatches<'_>) {
9195
if let Some(timeout) = parameters.value_of("timeout") {
9296
let now = Instant::now();
9397
let timeout = timeout
@@ -110,18 +114,22 @@ impl DatadogExporter {
110114
info!("Measurement step is: {}s", step_duration);
111115

112116
while now.elapsed().as_secs() <= timeout {
113-
self.iterate(parameters);
117+
self.iterate(parameters).await;
114118
thread::sleep(Duration::new(step_duration, step_duration_nano));
115119
}
116120
} else {
117-
self.iterate(parameters);
121+
self.iterate(parameters).await;
118122
}
119123
}
120124

121-
fn iterate(&mut self, parameters: &ArgMatches) {
125+
async fn iterate(&mut self, parameters: &ArgMatches<'_>) {
122126
self.topology.refresh();
123-
let _series = self.collect_series();
124-
let _client = Self::build_client(parameters);
127+
let series = self.collect_series();
128+
let client = Self::build_client(parameters);
129+
match client.post_metrics(&series).await {
130+
Ok(_) => log::debug!("metrics sent"),
131+
Err(_) => log::warn!("unable to send metrics"),
132+
};
125133
}
126134

127135
fn create_consumption_serie(&self) -> Serie {

src/lib.rs

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ pub mod exporters;
55
pub mod sensors;
66
use clap::ArgMatches;
77
use exporters::{
8-
json::JSONExporter, prometheus::PrometheusExporter, qemu::QemuExporter,
9-
riemann::RiemannExporter, stdout::StdoutExporter, Exporter, ExporterOption,
8+
datadog::DatadogExporter, json::JSONExporter, prometheus::PrometheusExporter,
9+
qemu::QemuExporter, riemann::RiemannExporter, stdout::StdoutExporter, Exporter, ExporterOption,
1010
};
1111
use sensors::{powercap_rapl::PowercapRAPLSensor, Sensor};
1212
use std::collections::HashMap;
@@ -52,32 +52,44 @@ fn get_sensor(matches: &ArgMatches) -> Box<dyn Sensor> {
5252
pub fn run(matches: ArgMatches) {
5353
loggerv::init_with_verbosity(matches.occurrences_of("v")).unwrap();
5454

55-
let sensor_boxed = get_sensor(&matches);
56-
let exporter_parameters;
57-
5855
if let Some(stdout_exporter_parameters) = matches.subcommand_matches("stdout") {
59-
exporter_parameters = stdout_exporter_parameters.clone();
60-
let mut exporter = StdoutExporter::new(sensor_boxed);
56+
let exporter_parameters = stdout_exporter_parameters.clone();
57+
let mut exporter = StdoutExporter::new(get_sensor(&matches));
6158
exporter.run(exporter_parameters);
62-
} else if let Some(json_exporter_parameters) = matches.subcommand_matches("json") {
63-
exporter_parameters = json_exporter_parameters.clone();
64-
let mut exporter = JSONExporter::new(sensor_boxed);
59+
return;
60+
}
61+
if let Some(json_exporter_parameters) = matches.subcommand_matches("json") {
62+
let exporter_parameters = json_exporter_parameters.clone();
63+
let mut exporter = JSONExporter::new(get_sensor(&matches));
6564
exporter.run(exporter_parameters);
66-
} else if let Some(riemann_exporter_parameters) = matches.subcommand_matches("riemann") {
67-
exporter_parameters = riemann_exporter_parameters.clone();
68-
let mut exporter = RiemannExporter::new(sensor_boxed);
65+
return;
66+
}
67+
if let Some(riemann_exporter_parameters) = matches.subcommand_matches("riemann") {
68+
let exporter_parameters = riemann_exporter_parameters.clone();
69+
let mut exporter = RiemannExporter::new(get_sensor(&matches));
6970
exporter.run(exporter_parameters);
70-
} else if let Some(prometheus_exporter_parameters) = matches.subcommand_matches("prometheus") {
71-
exporter_parameters = prometheus_exporter_parameters.clone();
72-
let mut exporter = PrometheusExporter::new(sensor_boxed);
71+
return;
72+
}
73+
if let Some(prometheus_exporter_parameters) = matches.subcommand_matches("prometheus") {
74+
let exporter_parameters = prometheus_exporter_parameters.clone();
75+
let mut exporter = PrometheusExporter::new(get_sensor(&matches));
7376
exporter.run(exporter_parameters);
74-
} else if let Some(qemu_exporter_parameters) = matches.subcommand_matches("qemu") {
75-
exporter_parameters = qemu_exporter_parameters.clone();
76-
let mut exporter = QemuExporter::new(sensor_boxed);
77+
return;
78+
}
79+
if let Some(qemu_exporter_parameters) = matches.subcommand_matches("qemu") {
80+
let exporter_parameters = qemu_exporter_parameters.clone();
81+
let mut exporter = QemuExporter::new(get_sensor(&matches));
7782
exporter.run(exporter_parameters);
78-
} else {
79-
error!("Couldn't determine which exporter has been chosen.");
83+
return;
8084
}
85+
#[cfg(feature = "datadog")]
86+
if let Some(datadog_exporter_parameters) = matches.subcommand_matches("datadog") {
87+
let exporter_parameters = datadog_exporter_parameters.clone();
88+
let mut exporter = DatadogExporter::new(get_sensor(&matches));
89+
exporter.run(exporter_parameters);
90+
return;
91+
}
92+
error!("Couldn't determine which exporter has been chosen.");
8193
}
8294

8395
/// Returns options needed for each exporter as a HashMap.
@@ -104,6 +116,11 @@ pub fn get_exporters_options() -> HashMap<String, HashMap<String, ExporterOption
104116
String::from("qemu"),
105117
exporters::qemu::QemuExporter::get_options(),
106118
);
119+
#[cfg(feature = "datadog")]
120+
options.insert(
121+
String::from("datadog"),
122+
exporters::datadog::DatadogExporter::get_options(),
123+
);
107124
options
108125
}
109126

src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ fn main() {
6363
"prometheus" => "Prometheus exporter exposes power consumption metrics on an http endpoint (/metrics is default) in prometheus accepted format",
6464
"riemann" => "Riemann exporter sends power consumption metrics to a Riemann server",
6565
"qemu" => "Qemu exporter watches all Qemu/KVM virtual machines running on the host and exposes metrics of each of them in a dedicated folder",
66+
#[cfg(feature = "datadog")]
67+
"datadog" => "Datadog exporter sends power consumption metrics to Datadog",
6668
_ => "Unknown exporter",
6769
}
6870
);

0 commit comments

Comments
 (0)