use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct PluginMetricsSection {
#[serde(default)]
pub prometheus: bool,
#[serde(default)]
pub broker_topic_prefix: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timeout_seconds: Option<u64>,
}
impl PluginMetricsSection {
pub fn validate(&self) -> Result<(), String> {
if self.prometheus && self.broker_topic_prefix.is_empty() {
return Err("broker_topic_prefix cannot be empty when prometheus = true".into());
}
if self.broker_topic_prefix.contains(' ') {
return Err("broker_topic_prefix cannot contain spaces".into());
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn validate_accepts_minimal() {
let s = PluginMetricsSection {
prometheus: true,
broker_topic_prefix: "plugin.email".into(),
timeout_seconds: None,
};
assert!(s.validate().is_ok());
}
#[test]
fn validate_rejects_prometheus_without_topic() {
let s = PluginMetricsSection {
prometheus: true,
broker_topic_prefix: String::new(),
timeout_seconds: None,
};
assert!(s.validate().is_err());
}
#[test]
fn validate_accepts_prometheus_off_without_topic() {
let s = PluginMetricsSection::default();
assert!(s.validate().is_ok());
}
#[test]
fn deserializes_minimal_toml() {
let toml = r#"
prometheus = true
broker_topic_prefix = "plugin.email"
"#;
let s: PluginMetricsSection = toml::from_str(toml).expect("parse");
assert!(s.prometheus);
assert_eq!(s.broker_topic_prefix, "plugin.email");
}
}