1use figment::{
13 providers::Serialized,
14 value::{Dict, Map},
15 Error, Metadata, Profile, Provider,
16};
17
18pub const KEY_ALIASES: &[(&str, &str)] = &[
25 ("proxy.http", "proxy_http"),
29 ("proxy.https", "proxy_https"),
30 ("proxy.no_proxy", "proxy_no_proxy"),
31 ("apm_config.enable_rare_sampler", "apm_enable_rare_sampler"),
32 (
33 "apm_config.error_tracking_standalone.enabled",
34 "apm_error_tracking_standalone_enabled",
35 ),
36 (
41 "apm_config.obfuscation.credit_cards.enabled",
42 "apm_obfuscation_credit_cards_enabled",
43 ),
44 (
45 "apm_config.obfuscation.credit_cards.keep_values",
46 "apm_obfuscation_credit_cards_keep_values",
47 ),
48 (
49 "apm_config.obfuscation.credit_cards.luhn",
50 "apm_obfuscation_credit_cards_luhn",
51 ),
52 (
53 "apm_config.obfuscation.elasticsearch.enabled",
54 "apm_obfuscation_elasticsearch_enabled",
55 ),
56 (
57 "apm_config.obfuscation.elasticsearch.keep_values",
58 "apm_obfuscation_elasticsearch_keep_values",
59 ),
60 (
61 "apm_config.obfuscation.elasticsearch.obfuscate_sql_values",
62 "apm_obfuscation_elasticsearch_obfuscate_sql_values",
63 ),
64 (
65 "apm_config.obfuscation.http.remove_paths_with_digits",
66 "apm_obfuscation_http_remove_paths_with_digits",
67 ),
68 (
69 "apm_config.obfuscation.http.remove_query_string",
70 "apm_obfuscation_http_remove_query_string",
71 ),
72 (
73 "apm_config.obfuscation.memcached.enabled",
74 "apm_obfuscation_memcached_enabled",
75 ),
76 (
77 "apm_config.obfuscation.memcached.keep_command",
78 "apm_obfuscation_memcached_keep_command",
79 ),
80 (
81 "apm_config.obfuscation.mongodb.enabled",
82 "apm_obfuscation_mongodb_enabled",
83 ),
84 (
85 "apm_config.obfuscation.mongodb.keep_values",
86 "apm_obfuscation_mongodb_keep_values",
87 ),
88 (
89 "apm_config.obfuscation.mongodb.obfuscate_sql_values",
90 "apm_obfuscation_mongodb_obfuscate_sql_values",
91 ),
92 (
93 "apm_config.obfuscation.opensearch.enabled",
94 "apm_obfuscation_opensearch_enabled",
95 ),
96 (
97 "apm_config.obfuscation.opensearch.keep_values",
98 "apm_obfuscation_opensearch_keep_values",
99 ),
100 (
101 "apm_config.obfuscation.opensearch.obfuscate_sql_values",
102 "apm_obfuscation_opensearch_obfuscate_sql_values",
103 ),
104 ("apm_config.obfuscation.redis.enabled", "apm_obfuscation_redis_enabled"),
105 (
106 "apm_config.obfuscation.redis.remove_all_args",
107 "apm_obfuscation_redis_remove_all_args",
108 ),
109 (
110 "apm_config.obfuscation.valkey.enabled",
111 "apm_obfuscation_valkey_enabled",
112 ),
113 (
114 "apm_config.obfuscation.valkey.remove_all_args",
115 "apm_obfuscation_valkey_remove_all_args",
116 ),
117 ("apm_config.obfuscation.sql.dbms", "apm_obfuscation_sql_dbms"),
118 (
119 "apm_config.obfuscation.sql.dollar_quoted_func",
120 "apm_obfuscation_sql_dollar_quoted_func",
121 ),
122 (
123 "apm_config.obfuscation.sql.keep_sql_alias",
124 "apm_obfuscation_sql_keep_sql_alias",
125 ),
126 (
127 "apm_config.obfuscation.sql.replace_digits",
128 "apm_obfuscation_sql_replace_digits",
129 ),
130 (
131 "apm_config.obfuscation.sql.table_names",
132 "apm_obfuscation_sql_table_names",
133 ),
134 (
139 "otlp_config.traces.probabilistic_sampler.sampling_percentage",
140 "otlp_config_traces_probabilistic_sampler_sampling_percentage",
141 ),
142 (
146 "observability_pipelines_worker.metrics.enabled",
147 "observability_pipelines_worker_metrics_enabled",
148 ),
149 (
150 "observability_pipelines_worker.metrics.url",
151 "observability_pipelines_worker_metrics_url",
152 ),
153 (
154 "observability_pipelines_worker.metrics.use_v3_api.series",
155 "observability_pipelines_worker_metrics_use_v3_api_series",
156 ),
157 ("vector.metrics.enabled", "vector_metrics_enabled"),
158 ("vector.metrics.url", "vector_metrics_url"),
159 ("vector.metrics.use_v3_api.series", "vector_metrics_use_v3_api_series"),
160 ("agent_ipc.grpc_max_message_size", "agent_ipc_grpc_max_message_size"),
166 ("use_v2_api.series", "use_v2_api_series"),
169 ("use_v3_api.series.enabled", "use_v3_api_series_enabled"),
172 ("use_v3_api.series.endpoints", "use_v3_api_series_endpoints"),
173 (
177 "data_plane.serializer_zstd_compressor_level",
178 "data_plane_serializer_zstd_compressor_level",
179 ),
180];
181
182const ENV_REMAPPINGS: &[(&str, &str)] = &[("http_proxy", "proxy_http"), ("https_proxy", "proxy_https")];
186
187pub struct DatadogRemapper {
199 values: serde_json::Map<String, serde_json::Value>,
200}
201
202impl DatadogRemapper {
203 pub fn new() -> Self {
206 Self::from_env_iter(std::env::vars())
207 }
208
209 pub fn from_env_vars(env_vars: Vec<(String, String)>) -> Self {
215 Self::from_env_iter(env_vars)
216 }
217
218 fn from_env_iter<I>(env_vars: I) -> Self
219 where
220 I: IntoIterator<Item = (String, String)>,
221 {
222 let mut values = serde_json::Map::new();
223
224 for (env_key, env_value) in env_vars {
225 let lower = env_key.to_lowercase();
226 for &(from, to) in ENV_REMAPPINGS {
227 if lower == from && !values.contains_key(to) {
228 values.insert(to.to_string(), serde_json::Value::String(env_value.clone()));
229 }
230 }
231 }
232
233 Self { values }
234 }
235}
236
237impl Default for DatadogRemapper {
238 fn default() -> Self {
239 Self::new()
240 }
241}
242
243impl Provider for DatadogRemapper {
244 fn metadata(&self) -> Metadata {
245 Metadata::named("Datadog config remapper")
246 }
247
248 fn data(&self) -> Result<Map<Profile, Dict>, Error> {
249 if self.values.is_empty() {
250 return Ok(Map::new());
251 }
252 Serialized::defaults(serde_json::Value::Object(self.values.clone())).data()
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259
260 static ENV_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
261
262 #[test]
263 fn env_var_remapped_case_insensitively() {
264 let _guard = ENV_MUTEX.lock().unwrap();
265
266 std::env::set_var("HTTP_PROXY", "http://proxy.example.com");
267 let remapper = DatadogRemapper::new();
268 std::env::remove_var("HTTP_PROXY");
269
270 assert_eq!(
271 remapper.values.get("proxy_http").and_then(|v| v.as_str()),
272 Some("http://proxy.example.com"),
273 );
274 }
275
276 #[test]
277 fn env_var_not_remapped_when_absent() {
278 let _guard = ENV_MUTEX.lock().unwrap();
279
280 std::env::remove_var("HTTP_PROXY");
281 std::env::remove_var("http_proxy");
282 std::env::remove_var("HTTPS_PROXY");
283 std::env::remove_var("https_proxy");
284
285 let remapper = DatadogRemapper::new();
286
287 assert!(remapper.values.get("proxy_http").is_none());
288 assert!(remapper.values.get("proxy_https").is_none());
289 }
290
291 #[test]
292 fn first_matching_env_var_wins_for_remapped_key() {
293 let remapper = DatadogRemapper::from_env_vars(vec![
298 ("HTTP_PROXY".to_string(), "http://first.example.com".to_string()),
299 ("http_proxy".to_string(), "http://second.example.com".to_string()),
300 ]);
301
302 assert_eq!(
303 remapper.values.get("proxy_http").and_then(|v| v.as_str()),
304 Some("http://first.example.com"),
305 );
306 }
307}