1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StatsdDuplicateTo {
pub shard_map: Vec<String>,
pub suffix: Option<String>,
pub prefix: Option<String>,
pub input_blacklist: Option<String>,
pub input_filter: Option<String>,
pub counter_cardinality: Option<u32>,
pub sampling_threshold: Option<u32>,
pub sampling_window: Option<u32>,
pub gauge_cardinality: Option<u32>,
pub gauge_sampling_threshold: Option<u32>,
pub gauge_sampling_window: Option<u32>,
pub timer_cardinality: Option<u32>,
pub timer_sampling_threshold: Option<u32>,
pub timer_sampling_window: Option<u32>,
pub reservoir_size: Option<u32>,
}
impl StatsdDuplicateTo {
pub fn from_shards(shards: Vec<String>) -> Self {
StatsdDuplicateTo {
shard_map: shards,
suffix: None,
prefix: None,
input_blacklist: None,
input_filter: None,
counter_cardinality: None,
sampling_threshold: None,
sampling_window: None,
gauge_cardinality: None,
gauge_sampling_threshold: None,
gauge_sampling_window: None,
timer_cardinality: None,
timer_sampling_threshold: None,
timer_sampling_window: None,
reservoir_size: None,
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct StatsdConfig {
pub bind: String,
pub point_tag_regex: Option<String>,
pub validate: Option<bool>,
pub tcp_cork: Option<bool>,
pub shard_map: Vec<String>,
pub duplicate_to: Option<Vec<StatsdDuplicateTo>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct LegacyConfig {
pub statsd: StatsdConfig,
}
pub fn load_legacy_config(path: &str) -> anyhow::Result<LegacyConfig> {
let input = std::fs::read_to_string(path)?;
let config: LegacyConfig = serde_json::from_str(input.as_ref())?;
Ok(config)
}
#[cfg(test)]
pub mod test {
use super::*;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn load_example_config() {
let config = r#"
{
"statsd": {
"bind": "127.0.0.1:BIND_STATSD_PORT",
"duplicate_to": [
{
"prefix": "test-1.",
"shard_map": [
"127.0.0.1:SEND_STATSD_PORT"
],
"suffix": ".suffix"
},
{
"input_filter": "^(?=dontmatchme)",
"prefix": "test-2.",
"shard_map": [
"127.0.0.1:SEND_STATSD_PORT"
]
}
],
"point_tag_regex": "\\.__([a-zA-Z][a-zA-Z0-9_]+)=[a-zA-Z0-9_/-]+",
"shard_map": [
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT",
"127.0.0.1:SEND_STATSD_PORT"
],
"tcp_cork": true,
"validate": true
}
}
"#;
let mut tf = NamedTempFile::new().unwrap();
tf.write_all(config.as_bytes()).unwrap();
let config = load_legacy_config(tf.path().to_str().unwrap()).unwrap();
assert_eq!(config.statsd.validate, Some(true));
}
}