Skip to main content

atomr_telemetry/exporters/
config.rs

1//! Runtime configuration for exporters. Safe to parse even when the
2//! corresponding exporter cargo features are disabled — applying an
3//! unknown exporter returns an error rather than panicking.
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Default, Serialize, Deserialize)]
8pub struct ExportersConfig {
9    #[serde(default)]
10    pub prometheus: Option<PrometheusConfig>,
11    #[serde(default)]
12    pub otlp: Option<OtlpConfig>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct PrometheusConfig {
17    #[serde(default)]
18    pub namespace: Option<String>,
19    #[serde(default = "default_true")]
20    pub enabled: bool,
21}
22
23fn default_true() -> bool {
24    true
25}
26
27impl Default for PrometheusConfig {
28    fn default() -> Self {
29        Self { namespace: None, enabled: true }
30    }
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct OtlpConfig {
35    #[serde(default = "default_true")]
36    pub enabled: bool,
37    /// OTLP collector endpoint (e.g. `http://localhost:4317` for gRPC or
38    /// `http://localhost:4318` for HTTP).
39    pub endpoint: String,
40    /// Transport protocol: `grpc` or `http`.
41    #[serde(default = "default_protocol")]
42    pub protocol: String,
43    /// Service name attached as the `service.name` resource attribute.
44    #[serde(default)]
45    pub service_name: Option<String>,
46    /// Metric push interval in seconds.
47    #[serde(default = "default_interval")]
48    pub interval_secs: u64,
49    /// Optional headers (e.g. auth tokens).
50    #[serde(default)]
51    pub headers: std::collections::HashMap<String, String>,
52    /// Extra resource attributes beyond `service.name`.
53    #[serde(default)]
54    pub resource_attributes: std::collections::HashMap<String, String>,
55    /// Emit traces (spans) in addition to metrics.
56    #[serde(default = "default_true")]
57    pub traces: bool,
58    /// Use the stdout exporter instead of OTLP. Useful for dev/tests.
59    #[serde(default)]
60    pub stdout: bool,
61}
62
63fn default_protocol() -> String {
64    "grpc".into()
65}
66
67fn default_interval() -> u64 {
68    30
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn parses_full_config_from_toml() {
77        let toml = r#"
78            [prometheus]
79            namespace = "atomr"
80
81            [otlp]
82            endpoint = "http://collector:4317"
83            protocol = "grpc"
84            service_name = "my-service"
85            interval_secs = 15
86            stdout = false
87
88            [otlp.headers]
89            authorization = "Bearer x"
90        "#;
91        let parsed: ExportersConfig = toml::from_str(toml).unwrap();
92        assert_eq!(parsed.prometheus.unwrap().namespace.unwrap(), "atomr");
93        let otlp = parsed.otlp.unwrap();
94        assert_eq!(otlp.endpoint, "http://collector:4317");
95        assert_eq!(otlp.protocol, "grpc");
96        assert_eq!(otlp.headers.get("authorization").unwrap(), "Bearer x");
97    }
98}