Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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