Skip to content

Commit dd6442e

Browse files
Malletscursoragent
andauthored
feat(metrics): add configurable system prefix and separator (#6445)
* feat(metrics): add configurable system prefix to counter, gauge, and histogram macros Replace the `__key_name!` macro with a `const fn __sep()` + `concatcp!` approach so that both string literals and const paths (like `SYSTEM`) work uniformly as the system prefix. Each metric macro now accepts an optional `system:` argument. When omitted, the system defaults to `$crate::SYSTEM` ("quickwit"). All existing call sites continue to work without changes. Co-authored-by: Cursor <cursoragent@cursor.com> * test(metrics): add key name coverage for system and subsystem cases Add explicit counter, gauge, and histogram tests for custom, default, empty, and const system/subsystem combinations, and assert emitted values for each case. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(metrics): add configurable metric name separator Extend counter, gauge, and histogram base declaration macros to accept a configurable separator while defaulting to SEPARATOR, and add key-name tests for custom separators. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(metrics): add custom separator example in http_service Show how to override the default metric name separator with "." in the example service and print the resulting dotted metric key. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: cargo fmt * fix(metrics): allow separator override with default system Add subsystem+separator macro arms for counter, gauge, and histogram so callers can customize separators without explicitly overriding system, and cover this with key-name tests. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent dd8ad7e commit dd6442e

9 files changed

Lines changed: 708 additions & 36 deletions

File tree

quickwit/quickwit-metrics/examples/http_service.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,47 @@ static HTTP_ACTIVE_CONNECTIONS_BY_REGION: LazyGauge = lazy_gauge!(
6767
"region" => "us-east-1",
6868
);
6969

70+
// ─── Custom system prefix ───
71+
//
72+
// Override the default system prefix ("quickwit") with a custom value.
73+
// This produces metric names like "myapp_db_queries_total" instead of
74+
// "quickwit_db_queries_total".
75+
76+
static DB_QUERIES_TOTAL: LazyCounter = lazy_counter!(
77+
name: "queries_total",
78+
description: "Total number of database queries",
79+
system: "myapp",
80+
subsystem: "db",
81+
);
82+
83+
static DB_QUERY_DURATION: LazyHistogram = lazy_histogram!(
84+
name: "query_duration_seconds",
85+
description: "Time spent executing database queries",
86+
system: "myapp",
87+
subsystem: "db",
88+
buckets: vec![0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0],
89+
);
90+
91+
static DB_CONNECTIONS: LazyGauge = lazy_gauge!(
92+
name: "connections",
93+
description: "Number of active database connections",
94+
system: "myapp",
95+
subsystem: "db",
96+
);
97+
98+
// ─── Custom separator ───
99+
//
100+
// Override the default "_" separator with ".".
101+
// This produces metric names like "myapp.http.requests_total".
102+
103+
static HTTP_REQUESTS_DOTTED: LazyCounter = lazy_counter!(
104+
name: "requests_total",
105+
description: "Total HTTP requests with dotted metric name",
106+
system: "myapp",
107+
subsystem: "http",
108+
separator: ".",
109+
);
110+
70111
// ─── LabelNames<N> examples ───
71112

72113
const ROUTE_LABEL_NAMES: LabelNames<2> = label_names!("method", "path");
@@ -183,6 +224,23 @@ fn main() {
183224
println!(" set quickwit_http_requests_total absolute = 1,000,000");
184225
println!();
185226

227+
println!("=== Custom system prefix ===");
228+
DB_QUERIES_TOTAL.inc();
229+
println!(" myapp_db_queries_total = {}", DB_QUERIES_TOTAL.get());
230+
DB_QUERY_DURATION.observe(0.042);
231+
println!(" myapp_db_query_duration_seconds observed 0.042");
232+
DB_CONNECTIONS.set(5.0);
233+
println!(" myapp_db_connections = {}", DB_CONNECTIONS.get());
234+
println!();
235+
236+
println!("=== Custom separator ===");
237+
HTTP_REQUESTS_DOTTED.inc_by(3);
238+
println!(
239+
" myapp.http.requests_total = {}",
240+
HTTP_REQUESTS_DOTTED.get()
241+
);
242+
println!();
243+
186244
println!("Prometheus scrape endpoint: http://127.0.0.1:9000/metrics");
187245
println!("Press Ctrl+C to stop.");
188246
std::thread::park();

quickwit/quickwit-metrics/src/counter.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,18 +260,22 @@ impl CounterFn for Counter {
260260
/// ```
261261
#[macro_export]
262262
macro_rules! counter {
263-
// Base declaration: all-static name, labels, and key — zero allocations.
263+
// Base declaration with explicit separator, system, and subsystem prefix - zero allocations.
264264
(
265265
name: $name:literal,
266266
description: $description:literal,
267-
subsystem: $subsystem:tt
267+
system: $system:expr,
268+
subsystem: $subsystem:expr,
269+
separator: $separator:expr
268270
$(, $label:literal => $value:literal)* $(,)?
269271
) => {{
270272
$crate::__key_info_metadata!(
271273
kind: $crate::MetricKind::Counter,
272274
name: $name,
273275
description: $description,
274-
subsystem: $subsystem
276+
system: $system,
277+
subsystem: $subsystem,
278+
separator: $separator
275279
$(, $label => $value)*
276280
);
277281
$crate::__metric_declaration!(
@@ -282,6 +286,58 @@ macro_rules! counter {
282286
)
283287
}};
284288

289+
// Base declaration with explicit system and subsystem prefix - zero allocations.
290+
(
291+
name: $name:literal,
292+
description: $description:literal,
293+
system: $system:expr,
294+
subsystem: $subsystem:expr
295+
$(, $label:literal => $value:literal)* $(,)?
296+
) => {{
297+
$crate::counter!(
298+
name: $name,
299+
description: $description,
300+
system: $system,
301+
subsystem: $subsystem,
302+
separator: $crate::SEPARATOR
303+
$(, $label => $value)*
304+
)
305+
}};
306+
307+
// Base declaration with subsystem only — system defaults to SYSTEM.
308+
(
309+
name: $name:literal,
310+
description: $description:literal,
311+
subsystem: $subsystem:expr,
312+
separator: $separator:expr
313+
$(, $label:literal => $value:literal)* $(,)?
314+
) => {{
315+
$crate::counter!(
316+
name: $name,
317+
description: $description,
318+
system: $crate::SYSTEM,
319+
subsystem: $subsystem,
320+
separator: $separator
321+
$(, $label => $value)*
322+
)
323+
}};
324+
325+
// Base declaration with subsystem only — system defaults to SYSTEM.
326+
(
327+
name: $name:literal,
328+
description: $description:literal,
329+
subsystem: $subsystem:expr
330+
$(, $label:literal => $value:literal)* $(,)?
331+
) => {{
332+
$crate::counter!(
333+
name: $name,
334+
description: $description,
335+
system: $crate::SYSTEM,
336+
subsystem: $subsystem
337+
$(, $label => $value)*
338+
)
339+
}};
340+
285341
// Parent extension with inline dynamic labels.
286342
// Derives a child counter by inheriting the parent's name and labels,
287343
// appending new (possibly dynamic) key => value pairs.

quickwit/quickwit-metrics/src/gauge.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,18 +331,22 @@ impl Drop for GaugeGuard {
331331
/// ```
332332
#[macro_export]
333333
macro_rules! gauge {
334-
// Base declaration: all-static name, labels, and key — zero allocations.
334+
// Base declaration with explicit separator, system, and subsystem prefix - zero allocations.
335335
(
336336
name: $name:literal,
337337
description: $description:literal,
338-
subsystem: $subsystem:tt
338+
system: $system:expr,
339+
subsystem: $subsystem:expr,
340+
separator: $separator:expr
339341
$(, $label:literal => $value:literal)* $(,)?
340342
) => {{
341343
$crate::__key_info_metadata!(
342344
kind: $crate::MetricKind::Gauge,
343345
name: $name,
344346
description: $description,
345-
subsystem: $subsystem
347+
system: $system,
348+
subsystem: $subsystem,
349+
separator: $separator
346350
$(, $label => $value)*
347351
);
348352
$crate::__metric_declaration!(
@@ -353,6 +357,58 @@ macro_rules! gauge {
353357
)
354358
}};
355359

360+
// Base declaration with explicit system and subsystem prefix - zero allocations.
361+
(
362+
name: $name:literal,
363+
description: $description:literal,
364+
system: $system:expr,
365+
subsystem: $subsystem:expr
366+
$(, $label:literal => $value:literal)* $(,)?
367+
) => {{
368+
$crate::gauge!(
369+
name: $name,
370+
description: $description,
371+
system: $system,
372+
subsystem: $subsystem,
373+
separator: $crate::SEPARATOR
374+
$(, $label => $value)*
375+
)
376+
}};
377+
378+
// Base declaration with subsystem only — system defaults to SYSTEM.
379+
(
380+
name: $name:literal,
381+
description: $description:literal,
382+
subsystem: $subsystem:expr,
383+
separator: $separator:expr
384+
$(, $label:literal => $value:literal)* $(,)?
385+
) => {{
386+
$crate::gauge!(
387+
name: $name,
388+
description: $description,
389+
system: $crate::SYSTEM,
390+
subsystem: $subsystem,
391+
separator: $separator
392+
$(, $label => $value)*
393+
)
394+
}};
395+
396+
// Base declaration with subsystem only — system defaults to SYSTEM.
397+
(
398+
name: $name:literal,
399+
description: $description:literal,
400+
subsystem: $subsystem:expr
401+
$(, $label:literal => $value:literal)* $(,)?
402+
) => {{
403+
$crate::gauge!(
404+
name: $name,
405+
description: $description,
406+
system: $crate::SYSTEM,
407+
subsystem: $subsystem
408+
$(, $label => $value)*
409+
)
410+
}};
411+
356412
// Parent extension with inline dynamic labels.
357413
// Derives a child gauge by inheriting the parent's name and labels,
358414
// appending new (possibly dynamic) key => value pairs.

quickwit/quickwit-metrics/src/histogram.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -261,30 +261,30 @@ impl Drop for HistogramTimer {
261261
/// ```
262262
#[macro_export]
263263
macro_rules! histogram {
264-
// Base declaration: all-static name, labels, and key — zero allocations.
264+
// Base declaration with explicit separator, system, and subsystem prefix - zero allocations.
265265
(
266266
name: $name:literal,
267267
description: $description:literal,
268-
subsystem: $subsystem:tt,
268+
system: $system:expr,
269+
subsystem: $subsystem:expr,
270+
separator: $separator:expr,
269271
buckets: $buckets:expr
270272
$(, $label:literal => $value:literal)* $(,)?
271273
) => {{
272-
// Expand compile-time statics: KEY_NAME, INFO, KEY, LABELS, METADATA.
273274
$crate::__key_info_metadata!(
274275
kind: $crate::MetricKind::Histogram,
275276
name: $name,
276277
description: $description,
277-
subsystem: $subsystem
278+
system: $system,
279+
subsystem: $subsystem,
280+
separator: $separator
278281
$(, $label => $value)*
279282
);
280-
// Link histogram bucket configuration to the metric info and register it
281-
// with the inventory so the recorder can configure bucket boundaries.
282283
static HISTOGRAM_CONFIG: $crate::HistogramConfig = $crate::HistogramConfig {
283284
info: &INFO,
284285
buckets_fn: || $buckets,
285286
};
286287
$crate::__inventory::submit!(HISTOGRAM_CONFIG);
287-
// Thread-local cache + global DashMap registration.
288288
$crate::__metric_declaration!(
289289
metric_type: $crate::Histogram,
290290
register_fn: $crate::__histogram_get_or_register,
@@ -293,6 +293,64 @@ macro_rules! histogram {
293293
)
294294
}};
295295

296+
// Base declaration with explicit system and subsystem prefix - zero allocations.
297+
(
298+
name: $name:literal,
299+
description: $description:literal,
300+
system: $system:expr,
301+
subsystem: $subsystem:expr,
302+
buckets: $buckets:expr
303+
$(, $label:literal => $value:literal)* $(,)?
304+
) => {{
305+
$crate::histogram!(
306+
name: $name,
307+
description: $description,
308+
system: $system,
309+
subsystem: $subsystem,
310+
separator: $crate::SEPARATOR,
311+
buckets: $buckets
312+
$(, $label => $value)*
313+
)
314+
}};
315+
316+
// Base declaration with subsystem only — system defaults to SYSTEM.
317+
(
318+
name: $name:literal,
319+
description: $description:literal,
320+
subsystem: $subsystem:expr,
321+
separator: $separator:expr,
322+
buckets: $buckets:expr
323+
$(, $label:literal => $value:literal)* $(,)?
324+
) => {{
325+
$crate::histogram!(
326+
name: $name,
327+
description: $description,
328+
system: $crate::SYSTEM,
329+
subsystem: $subsystem,
330+
separator: $separator,
331+
buckets: $buckets
332+
$(, $label => $value)*
333+
)
334+
}};
335+
336+
// Base declaration with subsystem only — system defaults to SYSTEM.
337+
(
338+
name: $name:literal,
339+
description: $description:literal,
340+
subsystem: $subsystem:expr,
341+
buckets: $buckets:expr
342+
$(, $label:literal => $value:literal)* $(,)?
343+
) => {{
344+
$crate::histogram!(
345+
name: $name,
346+
description: $description,
347+
system: $crate::SYSTEM,
348+
subsystem: $subsystem,
349+
buckets: $buckets
350+
$(, $label => $value)*
351+
)
352+
}};
353+
296354
// Parent extension with inline dynamic labels.
297355
// Derives a child histogram by inheriting the parent's name and labels,
298356
// appending new (possibly dynamic) key => value pairs.

0 commit comments

Comments
 (0)