Skip to content

Commit efbcfb8

Browse files
authored
fix: keep custom exemplar labels caller-controlled (#2194)
1 parent 4220f82 commit efbcfb8

2 files changed

Lines changed: 21 additions & 15 deletions

File tree

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/exemplars/ExemplarSampler.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ private long durationUntilNextExemplarExpires(long now) {
339339

340340
private long updateCustomExemplar(int index, double value, Labels labels, long now) {
341341
if (!labels.contains(Exemplar.TRACE_ID) && !labels.contains(Exemplar.SPAN_ID)) {
342-
labels = mergeLabels(labels, doSampleExemplar());
342+
labels = mergeLabels(labels, sampleTraceContextLabels());
343343
}
344344
customExemplars[index] =
345345
Exemplar.builder().value(value).labels(labels).timestampMillis(now).build();
@@ -358,6 +358,19 @@ private long updateExemplar(int index, double value, long now) {
358358
}
359359

360360
private Labels doSampleExemplar() {
361+
Labels labels = sampleTraceContextLabels();
362+
if (labels.isEmpty()) {
363+
return labels;
364+
}
365+
// Per-metric supplier first (more specific), then the global supplier. On a name
366+
// collision the earlier (more specific) value is kept; the reserved trace_id/span_id
367+
// labels always win over both.
368+
labels = mergeAdditionalLabels(labels, additionalLabelsSupplier);
369+
labels = mergeAdditionalLabels(labels, ExemplarLabelsSupplier.getExemplarLabelsSupplier());
370+
return labels;
371+
}
372+
373+
private Labels sampleTraceContextLabels() {
361374
// Using the qualified name so that Micrometer can exclude the dependency on
362375
// prometheus-metrics-tracer-initializer
363376
// as they provide their own implementation of SpanContextSupplier.
@@ -374,14 +387,7 @@ private Labels doSampleExemplar() {
374387
String traceId = spanContext.getCurrentTraceId();
375388
if (spanId != null && traceId != null) {
376389
spanContext.markCurrentSpanAsExemplar();
377-
Labels labels = Labels.of(Exemplar.TRACE_ID, traceId, Exemplar.SPAN_ID, spanId);
378-
// Per-metric supplier first (more specific), then the global supplier. On a name
379-
// collision the earlier (more specific) value is kept; the reserved trace_id/span_id
380-
// labels always win over both.
381-
labels = mergeAdditionalLabels(labels, additionalLabelsSupplier);
382-
labels =
383-
mergeAdditionalLabels(labels, ExemplarLabelsSupplier.getExemplarLabelsSupplier());
384-
return labels;
390+
return Labels.of(Exemplar.TRACE_ID, traceId, Exemplar.SPAN_ID, spanId);
385391
}
386392
}
387393
}

prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -502,22 +502,22 @@ void globalSupplierWithoutSpanContextProducesNoExemplar() {
502502
}
503503

504504
@Test
505-
void globalSupplierMergedIntoCustomExemplar() throws Exception {
505+
void globalSupplierDoesNotApplyToCustomExemplar() throws Exception {
506506
SpanContextSupplier.setSpanContext(sampledSpanContext("trace-abc", "span-def"));
507507
ExemplarLabelsSupplier.setExemplarLabelsSupplier(() -> Labels.of("management_id", "mgmt-42"));
508508

509509
Counter counter = Counter.builder().name("requests_total").build();
510510
counter.incWithExemplar(Labels.of("k", "v"));
511511

512512
assertThat(openMetrics(counter))
513-
.contains("management_id=\"mgmt-42\"")
514513
.contains("k=\"v\"")
515514
.contains("trace_id=\"trace-abc\"")
516-
.contains("span_id=\"span-def\"");
515+
.contains("span_id=\"span-def\"")
516+
.doesNotContain("management_id=\"mgmt-42\"");
517517
}
518518

519519
@Test
520-
void callerLabelsWinOverGlobalSupplierInCustomExemplar() throws Exception {
520+
void callerControlsCustomExemplarLabels() throws Exception {
521521
SpanContextSupplier.setSpanContext(sampledSpanContext("trace-abc", "span-def"));
522522
ExemplarLabelsSupplier.setExemplarLabelsSupplier(
523523
() -> Labels.of("k", "global", "management_id", "mgmt-42"));
@@ -527,10 +527,10 @@ void callerLabelsWinOverGlobalSupplierInCustomExemplar() throws Exception {
527527

528528
assertThat(openMetrics(counter))
529529
.contains("k=\"caller\"")
530-
.contains("management_id=\"mgmt-42\"")
531530
.contains("trace_id=\"trace-abc\"")
532531
.contains("span_id=\"span-def\"")
533-
.doesNotContain("k=\"global\"");
532+
.doesNotContain("k=\"global\"")
533+
.doesNotContain("management_id=\"mgmt-42\"");
534534
}
535535

536536
@Test

0 commit comments

Comments
 (0)