Skip to content
This repository was archived by the owner on May 27, 2025. It is now read-only.

Commit 1460721

Browse files
authored
Merge pull request #4 from base/global-tags
chore: add support for hostname prometheus tag and global tags
2 parents 78fa1ba + bc09363 commit 1460721

File tree

3 files changed

+127
-3
lines changed

3 files changed

+127
-3
lines changed

Cargo.lock

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ metrics = "0.24.1"
2222
metrics-derive = "0.1"
2323
thiserror = "2.0.11"
2424
serde_json = "1.0.138"
25+
hostname = "0.4.0"
2526

2627
[features]
2728
integration = []

src/main.rs

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::sync::Arc;
2121
use tokio::signal::unix::{signal, SignalKind};
2222
use tokio::sync::broadcast;
2323
use tokio_util::sync::CancellationToken;
24-
use tracing::{error, info, trace, Level};
24+
use tracing::{error, info, trace, warn, Level};
2525
use tracing_subscriber::EnvFilter;
2626

2727
#[derive(Parser, Debug)]
@@ -85,6 +85,14 @@ struct Args {
8585
#[arg(long, env, default_value = "0.0.0.0:9000")]
8686
metrics_addr: SocketAddr,
8787

88+
/// Tags to add to every metrics emitted, should be in the format --metrics-global-labels label1=value1,label2=value2
89+
#[arg(long, env, default_value = "")]
90+
metrics_global_labels: String,
91+
92+
/// Add the hostname as a label to all Prometheus metrics
93+
#[arg(long, env, default_value = "false")]
94+
metrics_host_label: bool,
95+
8896
/// Maximum backoff allowed for upstream connections
8997
#[arg(long, env, default_value = "20")]
9098
subscriber_max_interval: u64,
@@ -117,8 +125,21 @@ async fn main() {
117125
address = args.metrics_addr.to_string()
118126
);
119127

120-
PrometheusBuilder::new()
121-
.with_http_listener(args.metrics_addr)
128+
let mut builder = PrometheusBuilder::new().with_http_listener(args.metrics_addr);
129+
130+
if args.metrics_host_label {
131+
let hostname = hostname::get()
132+
.expect("could not find hostname")
133+
.into_string()
134+
.expect("could not convert hostname to string");
135+
builder = builder.add_global_label("hostname", hostname);
136+
}
137+
138+
for (key, value) in parse_global_metrics(args.metrics_global_labels) {
139+
builder = builder.add_global_label(key, value);
140+
}
141+
142+
builder
122143
.install()
123144
.expect("failed to setup Prometheus endpoint")
124145
}
@@ -191,3 +212,74 @@ async fn main() {
191212
}
192213
}
193214
}
215+
216+
fn parse_global_metrics(metrics: String) -> Vec<(String, String)> {
217+
let mut result = Vec::new();
218+
219+
for metric in metrics.split(',') {
220+
if metric.is_empty() {
221+
continue;
222+
}
223+
224+
let parts = metric
225+
.splitn(2, '=')
226+
.map(|s| s.to_string())
227+
.collect::<Vec<String>>();
228+
229+
if parts.len() != 2 {
230+
warn!(
231+
message = "malformed global metric: invalid count",
232+
metric = metric
233+
);
234+
continue;
235+
}
236+
237+
let label = parts[0].to_string();
238+
let value = parts[1].to_string();
239+
240+
if label.is_empty() || value.is_empty() {
241+
warn!(
242+
message = "malformed global metric: empty value",
243+
metric = metric
244+
);
245+
continue;
246+
}
247+
248+
result.push((label, value));
249+
}
250+
251+
result
252+
}
253+
254+
#[cfg(test)]
255+
mod test {
256+
use crate::parse_global_metrics;
257+
258+
#[test]
259+
fn test_parse_global_metrics() {
260+
assert_eq!(
261+
parse_global_metrics("".into()),
262+
Vec::<(String, String)>::new(),
263+
);
264+
265+
assert_eq!(
266+
parse_global_metrics("key=value".into()),
267+
vec![("key".into(), "value".into())]
268+
);
269+
270+
assert_eq!(
271+
parse_global_metrics("key=value,key2=value2".into()),
272+
vec![
273+
("key".into(), "value".into()),
274+
("key2".into(), "value2".into())
275+
],
276+
);
277+
278+
assert_eq!(parse_global_metrics("gibberish".into()), Vec::new());
279+
280+
assert_eq!(
281+
parse_global_metrics("key=value,key2=,".into()),
282+
vec![("key".into(), "value".into())],
283+
);
284+
}
285+
}

0 commit comments

Comments
 (0)