Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,10 @@ pub struct VerifyConfig {
pub blocklist: HashSet<String>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct VarlinkConfig {
pub enabled: bool,
}
impl Default for VarlinkConfig {
fn default() -> Self {
VarlinkConfig { enabled: false }
}
}

/// Config struct
/// Each section represents an ini file section
Expand Down
38 changes: 24 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,30 @@ pub async fn stat_collector(

// Run service collectors if there are services listed in config
if config.units.enabled {
if config.varlink.enabled {
join_set.spawn(crate::varlink_units::update_unit_stats(
Arc::clone(&config),
sdc.clone(),
locked_machine_stats.clone(),
crate::varlink_units::METRICS_SOCKET_PATH.to_string(),
));
} else {
join_set.spawn(crate::units::update_unit_stats(
Arc::clone(&config),
sdc.clone(),
locked_machine_stats.clone(),
));
}
let config_clone = Arc::clone(&config);
let sdc_clone = sdc.clone();
let stats_clone = locked_machine_stats.clone();
join_set.spawn(async move {
if config_clone.varlink.enabled {
let socket_path = crate::varlink_units::METRICS_SOCKET_PATH.to_string();
match crate::varlink_units::update_unit_stats(
Arc::clone(&config_clone),
stats_clone.clone(),
socket_path,
)
.await
{
Ok(()) => return Ok(()),
Err(err) => {
warn!(
"Varlink units stats failed, falling back to D-Bus: {:?}",
err
);
}
}
}
crate::units::update_unit_stats(config_clone, sdc_clone, stats_clone).await
});
}

if config.machines.enabled {
Expand Down
30 changes: 23 additions & 7 deletions src/machines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::sync::Arc;

use thiserror::Error;
use tokio::sync::RwLock;
use tracing::{debug, error};
use tracing::{debug, error, warn};

use crate::MachineStats;
use crate::MonitordStats;
Expand Down Expand Up @@ -103,17 +103,33 @@ pub async fn update_machines_stats(

if config.units.enabled {
if config.varlink.enabled {
let config_clone = Arc::clone(&config);
let sdc_clone = sdc.clone();
let stats_clone = locked_machine_stats.clone();
let container_socket_path = format!(
"/proc/{}/root{}",
leader_pid,
crate::varlink_units::METRICS_SOCKET_PATH
);
join_set.spawn(crate::varlink_units::update_unit_stats(
Arc::clone(&config),
sdc.clone(),
locked_machine_stats.clone(),
container_socket_path,
));
join_set.spawn(async move {
match crate::varlink_units::update_unit_stats(
Arc::clone(&config_clone),
stats_clone.clone(),
container_socket_path,
)
.await
{
Ok(()) => Ok(()),
Err(err) => {
warn!(
"Varlink units stats failed, falling back to D-Bus: {:?}",
err
);
crate::units::update_unit_stats(config_clone, sdc_clone, stats_clone)
.await
}
}
});
} else {
join_set.spawn(crate::units::update_unit_stats(
Arc::clone(&config),
Expand Down
66 changes: 35 additions & 31 deletions src/varlink/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,25 @@ impl ListOutput {
self.object.as_deref().unwrap_or("").to_string()
}

/// Returns the string value or default_value if not present
pub fn value_as_string<'a>(&'a self, default_value: &'a str) -> &'a str {
self.value.as_str().unwrap_or(default_value)
/// Returns the string value. Caller must validate value is a string first.
pub fn value_as_string(&self) -> &str {
self.value
.as_str()
.expect("value_as_string called on non-string value; validate metric type first")
}

/// Returns the int value as u64 or default_value if not present
pub fn value_as_int(&self, default_value: u64) -> u64 {
/// Returns the int value. Caller must validate value is an integer first.
pub fn value_as_int(&self) -> i64 {
self.value
.as_i64()
.filter(|v| *v >= 0)
.map(|v| v as u64)
.unwrap_or(default_value)
.expect("value_as_int called on non-integer value; validate metric type first")
}

/// Returns the bool value if present
pub fn value_as_bool(&self) -> Option<bool> {
self.value.as_bool()
/// Returns the bool value. Caller must validate value is a bool first.
pub fn value_as_bool(&self) -> bool {
self.value
.as_bool()
.expect("value_as_bool called on non-boolean value; validate metric type first")
}

/// Returns the fields map if present
Expand Down Expand Up @@ -296,67 +298,68 @@ mod tests {
fields: None,
};

assert_eq!(output.value_as_string("unknown"), "active");
assert_eq!(output.value_as_string(), "active");
}

#[test]
fn test_value_as_string_without_value() {
fn test_value_as_string_empty_string() {
let output = ListOutput {
name: "test.metric".to_string(),
value: serde_json::Value::Null,
value: serde_json::json!(""),
object: None,
fields: None,
};

assert_eq!(output.value_as_string("unknown"), "unknown");
assert_eq!(output.value_as_string(), "");
}

#[test]
fn test_value_as_string_empty_string() {
fn test_value_as_int_with_value() {
let output = ListOutput {
name: "test.metric".to_string(),
value: serde_json::json!(""),
value: serde_json::json!(42),
object: None,
fields: None,
};

assert_eq!(output.value_as_string("default"), "");
assert_eq!(output.value_as_int(), 42);
}

#[test]
fn test_value_as_int_with_value() {
#[should_panic(expected = "value_as_int called on non-integer value")]
fn test_value_as_int_without_value() {
let output = ListOutput {
name: "test.metric".to_string(),
value: serde_json::json!(42),
value: serde_json::Value::Null,
object: None,
fields: None,
};

assert_eq!(output.value_as_int(0), 42);
output.value_as_int();
}

#[test]
fn test_value_as_int_without_value() {
fn test_value_as_int_zero() {
let output = ListOutput {
name: "test.metric".to_string(),
value: serde_json::Value::Null,
value: serde_json::json!(0),
object: None,
fields: None,
};

assert_eq!(output.value_as_int(0), 0);
assert_eq!(output.value_as_int(), 0);
}

#[test]
fn test_value_as_int_zero() {
fn test_value_as_int_negative() {
let output = ListOutput {
name: "test.metric".to_string(),
value: serde_json::json!(0),
value: serde_json::json!(-5),
object: None,
fields: None,
};

assert_eq!(output.value_as_int(0), 0);
assert_eq!(output.value_as_int(), -5);
}

#[test]
Expand All @@ -368,7 +371,7 @@ mod tests {
fields: None,
};

assert_eq!(output.value_as_int(0), 9999999999);
assert_eq!(output.value_as_int(), 9999999999);
}

#[test]
Expand All @@ -380,7 +383,7 @@ mod tests {
fields: None,
};

assert_eq!(output.value_as_bool(), Some(true));
assert_eq!(output.value_as_bool(), true);
}

#[test]
Expand All @@ -392,10 +395,11 @@ mod tests {
fields: None,
};

assert_eq!(output.value_as_bool(), Some(false));
assert_eq!(output.value_as_bool(), false);
}

#[test]
#[should_panic(expected = "value_as_bool called on non-boolean value")]
fn test_value_as_bool_none() {
let output = ListOutput {
name: "test.metric".to_string(),
Expand All @@ -404,6 +408,6 @@ mod tests {
fields: None,
};

assert_eq!(output.value_as_bool(), None);
output.value_as_bool();
}
}
Loading
Loading