saluki_components/config/
mrf.rs

1//! Multi-region failover configuration.
2
3use agent_data_plane_config::domains::multi_region_failover;
4
5/// Multi-region failover configuration shared by signal-specific pipelines.
6#[derive(Clone, Debug, Eq, PartialEq)]
7pub struct MrfConfiguration {
8    enabled: bool,
9    failover_metrics: bool,
10    metric_allowlist: Vec<String>,
11    api_key: Option<String>,
12    metrics_endpoint: Option<String>,
13}
14
15impl MrfConfiguration {
16    /// Creates a new `MrfConfiguration` from the resolved multi-region failover configuration.
17    pub fn from_configuration(mrf: &multi_region_failover::Domain) -> Self {
18        Self {
19            enabled: mrf.enabled,
20            failover_metrics: mrf.failover_metrics,
21            metric_allowlist: mrf.metric_allowlist.clone(),
22            api_key: mrf.api_key.clone(),
23            metrics_endpoint: mrf.metrics_endpoint_url(),
24        }
25    }
26
27    /// Returns whether multi-region failover is enabled for this process.
28    pub const fn is_enabled(&self) -> bool {
29        self.enabled
30    }
31
32    /// Returns whether metrics forwarding to the failover region is requested by configuration.
33    pub const fn is_metrics_forwarding_requested(&self) -> bool {
34        self.enabled && self.failover_metrics
35    }
36
37    /// Updates whether metrics forwarding to the failover region is enabled.
38    pub(crate) const fn set_failover_metrics(&mut self, failover_metrics: bool) {
39        self.failover_metrics = failover_metrics;
40    }
41
42    /// Updates the metric allowlist.
43    pub(crate) fn set_metric_allowlist(&mut self, metric_allowlist: Vec<String>) {
44        self.metric_allowlist = metric_allowlist;
45    }
46
47    /// Returns the metric allowlist.
48    pub fn metric_allowlist(&self) -> &[String] {
49        &self.metric_allowlist
50    }
51
52    /// Returns the failover-region API key.
53    pub fn api_key(&self) -> Option<&str> {
54        self.api_key.as_deref()
55    }
56
57    /// Returns the failover-region metrics endpoint URL.
58    pub fn metrics_endpoint_url(&self) -> Option<&str> {
59        self.metrics_endpoint.as_deref()
60    }
61
62    /// Returns the endpoint and API key override for the failover-region metrics forwarder.
63    pub fn metrics_endpoint_override(&self) -> Option<(String, String)> {
64        if !self.enabled {
65            return None;
66        }
67
68        Some((self.metrics_endpoint.clone()?, self.api_key.clone()?))
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    fn mrf_config(mrf: multi_region_failover::Domain) -> MrfConfiguration {
77        MrfConfiguration::from_configuration(&mrf)
78    }
79
80    #[test]
81    fn carries_the_resolved_multi_region_failover_configuration() {
82        let config = mrf_config(multi_region_failover::Domain {
83            enabled: true,
84            failover_metrics: true,
85            metric_allowlist: vec!["first.metric".to_string(), "second.metric".to_string()],
86            api_key: Some("mrf-api-key".to_string()),
87            site: Some("datadoghq.eu".to_string()),
88            dd_url: None,
89        });
90
91        assert!(config.is_metrics_forwarding_requested());
92        assert_eq!(config.metric_allowlist(), ["first.metric", "second.metric"]);
93        assert_eq!(Some("mrf-api-key"), config.api_key());
94        assert_eq!(Some("https://app.mrf.datadoghq.eu"), config.metrics_endpoint_url());
95    }
96
97    #[test]
98    fn metrics_endpoint_override_requires_api_key_and_endpoint() {
99        let missing_api_key = mrf_config(multi_region_failover::Domain {
100            enabled: true,
101            failover_metrics: true,
102            site: Some("datadoghq.eu".to_string()),
103            ..Default::default()
104        });
105        assert_eq!(None, missing_api_key.metrics_endpoint_override());
106
107        let missing_endpoint = mrf_config(multi_region_failover::Domain {
108            enabled: true,
109            failover_metrics: true,
110            api_key: Some("mrf-api-key".to_string()),
111            ..Default::default()
112        });
113        assert_eq!(None, missing_endpoint.metrics_endpoint_override());
114
115        let ready = mrf_config(multi_region_failover::Domain {
116            enabled: true,
117            failover_metrics: true,
118            api_key: Some("mrf-api-key".to_string()),
119            dd_url: Some("https://mrf.example.com".to_string()),
120            ..Default::default()
121        });
122        assert_eq!(
123            Some(("https://mrf.example.com".to_string(), "mrf-api-key".to_string())),
124            ready.metrics_endpoint_override()
125        );
126    }
127
128    #[test]
129    fn metrics_endpoint_override_does_not_require_failover_metrics() {
130        let config = mrf_config(multi_region_failover::Domain {
131            enabled: true,
132            failover_metrics: false,
133            api_key: Some("mrf-api-key".to_string()),
134            dd_url: Some("https://mrf.example.com".to_string()),
135            ..Default::default()
136        });
137
138        assert!(!config.is_metrics_forwarding_requested());
139        assert_eq!(
140            Some(("https://mrf.example.com".to_string(), "mrf-api-key".to_string())),
141            config.metrics_endpoint_override()
142        );
143    }
144
145    #[test]
146    fn metrics_endpoint_override_is_none_when_disabled() {
147        // Even with a fully-populated endpoint and API key, `metrics_endpoint_override` short-circuits to `None`
148        // when multi-region failover is disabled (the `if !self.enabled` guard at the top of the method).
149        let config = mrf_config(multi_region_failover::Domain {
150            enabled: false,
151            failover_metrics: true,
152            api_key: Some("mrf-api-key".to_string()),
153            dd_url: Some("https://mrf.example.com".to_string()),
154            ..Default::default()
155        });
156
157        assert!(!config.is_enabled());
158        assert_eq!(None, config.metrics_endpoint_override());
159
160        // The endpoint itself still resolves; only the override is gated on `enabled`, which confirms the `None`
161        // above comes from the disabled short-circuit rather than a missing endpoint or API key.
162        assert_eq!(Some("https://mrf.example.com"), config.metrics_endpoint_url());
163        assert_eq!(Some("mrf-api-key"), config.api_key());
164    }
165}