1use figment::{
3 providers::Serialized,
4 value::{Dict, Map},
5 Error, Metadata, Profile, Provider,
6};
7
8pub const KEY_ALIASES: &[(&str, &str)] = &[
15 ("proxy.http", "proxy_http"),
19 ("proxy.https", "proxy_https"),
20 ("proxy.no_proxy", "proxy_no_proxy"),
21 ("apm_config.enable_rare_sampler", "apm_enable_rare_sampler"),
22 (
23 "apm_config.error_tracking_standalone.enabled",
24 "apm_error_tracking_standalone_enabled",
25 ),
26 (
31 "apm_config.obfuscation.credit_cards.enabled",
32 "apm_obfuscation_credit_cards_enabled",
33 ),
34 (
35 "apm_config.obfuscation.credit_cards.keep_values",
36 "apm_obfuscation_credit_cards_keep_values",
37 ),
38 (
39 "apm_config.obfuscation.credit_cards.luhn",
40 "apm_obfuscation_credit_cards_luhn",
41 ),
42 (
43 "apm_config.obfuscation.elasticsearch.enabled",
44 "apm_obfuscation_elasticsearch_enabled",
45 ),
46 (
47 "apm_config.obfuscation.elasticsearch.keep_values",
48 "apm_obfuscation_elasticsearch_keep_values",
49 ),
50 (
51 "apm_config.obfuscation.elasticsearch.obfuscate_sql_values",
52 "apm_obfuscation_elasticsearch_obfuscate_sql_values",
53 ),
54 (
55 "apm_config.obfuscation.http.remove_paths_with_digits",
56 "apm_obfuscation_http_remove_paths_with_digits",
57 ),
58 (
59 "apm_config.obfuscation.http.remove_query_string",
60 "apm_obfuscation_http_remove_query_string",
61 ),
62 (
63 "apm_config.obfuscation.memcached.enabled",
64 "apm_obfuscation_memcached_enabled",
65 ),
66 (
67 "apm_config.obfuscation.memcached.keep_command",
68 "apm_obfuscation_memcached_keep_command",
69 ),
70 (
71 "apm_config.obfuscation.mongodb.enabled",
72 "apm_obfuscation_mongodb_enabled",
73 ),
74 (
75 "apm_config.obfuscation.mongodb.keep_values",
76 "apm_obfuscation_mongodb_keep_values",
77 ),
78 (
79 "apm_config.obfuscation.mongodb.obfuscate_sql_values",
80 "apm_obfuscation_mongodb_obfuscate_sql_values",
81 ),
82 (
83 "apm_config.obfuscation.opensearch.enabled",
84 "apm_obfuscation_opensearch_enabled",
85 ),
86 (
87 "apm_config.obfuscation.opensearch.keep_values",
88 "apm_obfuscation_opensearch_keep_values",
89 ),
90 (
91 "apm_config.obfuscation.opensearch.obfuscate_sql_values",
92 "apm_obfuscation_opensearch_obfuscate_sql_values",
93 ),
94 ("apm_config.obfuscation.redis.enabled", "apm_obfuscation_redis_enabled"),
95 (
96 "apm_config.obfuscation.redis.remove_all_args",
97 "apm_obfuscation_redis_remove_all_args",
98 ),
99 (
100 "apm_config.obfuscation.valkey.enabled",
101 "apm_obfuscation_valkey_enabled",
102 ),
103 (
104 "apm_config.obfuscation.valkey.remove_all_args",
105 "apm_obfuscation_valkey_remove_all_args",
106 ),
107 ("apm_config.obfuscation.sql.dbms", "apm_obfuscation_sql_dbms"),
108 (
109 "apm_config.obfuscation.sql.dollar_quoted_func",
110 "apm_obfuscation_sql_dollar_quoted_func",
111 ),
112 (
113 "apm_config.obfuscation.sql.keep_sql_alias",
114 "apm_obfuscation_sql_keep_sql_alias",
115 ),
116 (
117 "apm_config.obfuscation.sql.replace_digits",
118 "apm_obfuscation_sql_replace_digits",
119 ),
120 (
121 "apm_config.obfuscation.sql.table_names",
122 "apm_obfuscation_sql_table_names",
123 ),
124 (
129 "otlp_config.traces.probabilistic_sampler.sampling_percentage",
130 "otlp_config_traces_probabilistic_sampler_sampling_percentage",
131 ),
132 (
136 "observability_pipelines_worker.metrics.enabled",
137 "observability_pipelines_worker_metrics_enabled",
138 ),
139 (
140 "observability_pipelines_worker.metrics.url",
141 "observability_pipelines_worker_metrics_url",
142 ),
143 ("vector.metrics.enabled", "vector_metrics_enabled"),
144 ("vector.metrics.url", "vector_metrics_url"),
145 ("agent_ipc.grpc_max_message_size", "agent_ipc_grpc_max_message_size"),
151 ("use_v2_api.series", "use_v2_api_series"),
154];
155
156const ENV_REMAPPINGS: &[(&str, &str)] = &[("http_proxy", "proxy_http"), ("https_proxy", "proxy_https")];
160
161pub struct DatadogRemapper {
174 values: serde_json::Map<String, serde_json::Value>,
175}
176
177impl DatadogRemapper {
178 pub fn new() -> Self {
180 let mut values = serde_json::Map::new();
181
182 for (env_key, env_value) in std::env::vars() {
183 let lower = env_key.to_lowercase();
184 for &(from, to) in ENV_REMAPPINGS {
185 if lower == from && !values.contains_key(to) {
186 values.insert(to.to_string(), serde_json::Value::String(env_value.clone()));
187 }
188 }
189 }
190
191 Self { values }
192 }
193}
194
195impl Default for DatadogRemapper {
196 fn default() -> Self {
197 Self::new()
198 }
199}
200
201impl Provider for DatadogRemapper {
202 fn metadata(&self) -> Metadata {
203 Metadata::named("Datadog config remapper")
204 }
205
206 fn data(&self) -> Result<Map<Profile, Dict>, Error> {
207 if self.values.is_empty() {
208 return Ok(Map::new());
209 }
210 Serialized::defaults(serde_json::Value::Object(self.values.clone())).data()
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 static ENV_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
219
220 #[test]
221 fn env_var_remapped_case_insensitively() {
222 let _guard = ENV_MUTEX.lock().unwrap();
223
224 std::env::set_var("HTTP_PROXY", "http://proxy.example.com");
225 let remapper = DatadogRemapper::new();
226 std::env::remove_var("HTTP_PROXY");
227
228 assert_eq!(
229 remapper.values.get("proxy_http").and_then(|v| v.as_str()),
230 Some("http://proxy.example.com"),
231 );
232 }
233
234 #[test]
235 fn env_var_not_remapped_when_absent() {
236 let _guard = ENV_MUTEX.lock().unwrap();
237
238 std::env::remove_var("HTTP_PROXY");
239 std::env::remove_var("http_proxy");
240 std::env::remove_var("HTTPS_PROXY");
241 std::env::remove_var("https_proxy");
242
243 let remapper = DatadogRemapper::new();
244
245 assert!(remapper.values.get("proxy_http").is_none());
246 assert!(remapper.values.get("proxy_https").is_none());
247 }
248}