Skip to content

Commit 0e8c3ae

Browse files
committed
Make per-meter OTLP configuration more flexible
Allow users to configure in more ways than an exact match on the meter name.
1 parent f4e4a05 commit 0e8c3ae

File tree

4 files changed

+74
-24
lines changed

4 files changed

+74
-24
lines changed

Diff for: implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java

+16-12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package io.micrometer.registry.otlp;
1717

18+
import io.micrometer.core.instrument.Meter;
1819
import io.micrometer.core.instrument.config.InvalidConfigurationException;
1920
import io.micrometer.core.instrument.config.validate.Validated;
2021
import io.micrometer.core.instrument.push.PushRegistryConfig;
@@ -23,6 +24,7 @@
2324
import java.net.URLDecoder;
2425
import java.util.*;
2526
import java.util.concurrent.TimeUnit;
27+
import java.util.function.Function;
2628
import java.util.stream.Collectors;
2729

2830
import static io.micrometer.core.instrument.config.MeterRegistryConfigValidator.*;
@@ -229,15 +231,16 @@ default HistogramFlavor histogramFlavor() {
229231

230232
/**
231233
* Configures the histogram flavor to use on a per-meter level. This will override the
232-
* {@link #histogramFlavor()} configuration for matching Meters. The key is used to do
233-
* an exact match on the Meter's name.
234-
* @return mapping of meter name to histogram flavor
234+
* {@link #histogramFlavor()} configuration for matching Meters. By default, the key
235+
* is used to do an exact match on the Meter's name.
236+
* @return mapping of meter ID to histogram flavor
235237
* @since 1.15.0
236238
* @see #histogramFlavor()
237239
*/
238-
default Map<String, HistogramFlavor> histogramFlavorPerMeter() {
239-
return getStringMap(this, "histogramFlavorPerMeter", HistogramFlavor::fromString)
240-
.orElse(Collections.emptyMap());
240+
default Function<Meter.Id, HistogramFlavor> histogramFlavorPerMeter() {
241+
return id -> getStringMap(this, "histogramFlavorPerMeter", HistogramFlavor::fromString)
242+
.orElse(Collections.emptyMap())
243+
.getOrDefault(id.getName(), histogramFlavor());
241244
}
242245

243246
/**
@@ -267,15 +270,16 @@ default int maxBucketCount() {
267270

268271
/**
269272
* Configures the max bucket count to use on a per-meter level. This will override the
270-
* {@link #maxBucketCount()} configuration for matching Meters. The key is used to do
271-
* an exact match on the Meter's name. This has no effect on a meter if it does not
272-
* have an exponential bucket histogram configured.
273-
* @return mapping of meter name to max bucket count
273+
* {@link #maxBucketCount()} configuration for matching Meters. By default, the key is
274+
* used to do an exact match on the Meter's name. This has no effect on a meter if it
275+
* does not have an exponential bucket histogram configured.
276+
* @return mapping of meter ID to max bucket count
274277
* @since 1.15.0
275278
* @see #maxBucketCount()
276279
*/
277-
default Map<String, Integer> maxBucketsPerMeter() {
278-
return getStringMap(this, "maxBucketsPerMeter", Integer::parseInt).orElse(Collections.emptyMap());
280+
default Function<Meter.Id, Integer> maxBucketsPerMeter() {
281+
return id -> getStringMap(this, "maxBucketsPerMeter", Integer::parseInt).orElse(Collections.emptyMap())
282+
.getOrDefault(id.getName(), maxBucketCount());
279283
}
280284

281285
@Override

Diff for: implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpMeterRegistry.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,12 @@ private Histogram getHistogram(Meter.Id id, DistributionStatisticConfig distribu
430430
}
431431

432432
private int getMaxBuckets(Meter.Id id) {
433-
return config.maxBucketsPerMeter().getOrDefault(id.getName(), config.maxBucketCount());
433+
return config.maxBucketsPerMeter().apply(id);
434434
}
435435

436436
private HistogramFlavor histogramFlavor(Meter.Id id, OtlpConfig otlpConfig,
437437
DistributionStatisticConfig distributionStatisticConfig) {
438-
HistogramFlavor preferredHistogramFlavor = otlpConfig.histogramFlavorPerMeter()
439-
.getOrDefault(id.getName(), otlpConfig.histogramFlavor());
438+
HistogramFlavor preferredHistogramFlavor = otlpConfig.histogramFlavorPerMeter().apply(id);
440439

441440
final double[] serviceLevelObjectiveBoundaries = distributionStatisticConfig
442441
.getServiceLevelObjectiveBoundaries();

Diff for: implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java

+50-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package io.micrometer.registry.otlp;
1717

18+
import io.micrometer.core.instrument.Meter;
19+
import io.micrometer.core.instrument.Tags;
1820
import io.micrometer.core.instrument.config.InvalidConfigurationException;
1921
import org.junit.jupiter.api.Test;
2022

@@ -23,9 +25,10 @@
2325
import java.util.HashMap;
2426
import java.util.Map;
2527
import java.util.concurrent.TimeUnit;
28+
import java.util.function.Function;
2629
import java.util.stream.Stream;
2730

28-
import static java.util.Map.entry;
31+
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getStringMap;
2932
import static org.assertj.core.api.Assertions.assertThat;
3033
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3134
import static uk.org.webcompere.systemstubs.SystemStubs.withEnvironmentVariable;
@@ -284,9 +287,47 @@ void histogramFlavorPerMeter() {
284287
"a.b.c=explicit_bucket_histogram ,expo =base2_exponential_bucket_histogram");
285288
OtlpConfig otlpConfig = properties::get;
286289
assertThat(otlpConfig.validate().isValid()).isTrue();
287-
assertThat(otlpConfig.histogramFlavorPerMeter()).containsExactly(
288-
entry("a.b.c", HistogramFlavor.EXPLICIT_BUCKET_HISTOGRAM),
289-
entry("expo", HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM));
290+
assertThat(otlpConfig.histogramFlavorPerMeter().apply(idWithName("a.b.c")))
291+
.isEqualTo(HistogramFlavor.EXPLICIT_BUCKET_HISTOGRAM);
292+
assertThat(otlpConfig.histogramFlavorPerMeter().apply(idWithName("expo")))
293+
.isEqualTo(HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM);
294+
}
295+
296+
@Test
297+
void customHistogramFlavorPerMeterFunction() {
298+
Map<String, String> properties = new HashMap<>();
299+
properties.put("otlp.histogramFlavorPerMeter",
300+
"a.b.c=explicit_bucket_histogram,expo=base2_exponential_bucket_histogram");
301+
OtlpConfig otlpConfig = new OtlpConfig() {
302+
@Override
303+
public String get(String key) {
304+
return properties.get(key);
305+
}
306+
307+
@Override
308+
public Function<Meter.Id, HistogramFlavor> histogramFlavorPerMeter() {
309+
return id -> {
310+
Map<String, HistogramFlavor> histogramFlavorPerMeter = getStringMap(this, "histogramFlavorPerMeter",
311+
HistogramFlavor::fromString)
312+
.orElse(Collections.emptyMap());
313+
for (Map.Entry<String, HistogramFlavor> entry : histogramFlavorPerMeter.entrySet()) {
314+
if (id.getName().startsWith(entry.getKey())) {
315+
return entry.getValue();
316+
}
317+
}
318+
return histogramFlavor();
319+
};
320+
}
321+
};
322+
assertThat(otlpConfig.validate().isValid()).isTrue();
323+
assertThat(otlpConfig.histogramFlavorPerMeter().apply(idWithName("something")))
324+
.isEqualTo(otlpConfig.histogramFlavor());
325+
assertThat(otlpConfig.histogramFlavorPerMeter().apply(idWithName("a.b.c")))
326+
.isEqualTo(HistogramFlavor.EXPLICIT_BUCKET_HISTOGRAM);
327+
assertThat(otlpConfig.histogramFlavorPerMeter().apply(idWithName("expo")))
328+
.isEqualTo(HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM);
329+
assertThat(otlpConfig.histogramFlavorPerMeter().apply(idWithName("expo.other")))
330+
.isEqualTo(HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM);
290331
}
291332

292333
@Test
@@ -295,7 +336,11 @@ void maxBucketsPerMeter() {
295336
properties.put("otlp.maxBucketsPerMeter", "a.b.c = 10");
296337
OtlpConfig otlpConfig = properties::get;
297338
assertThat(otlpConfig.validate().isValid()).isTrue();
298-
assertThat(otlpConfig.maxBucketsPerMeter()).containsExactly(entry("a.b.c", 10));
339+
assertThat(otlpConfig.maxBucketsPerMeter().apply(idWithName("a.b.c"))).isEqualTo(10);
340+
}
341+
342+
Meter.Id idWithName(String name) {
343+
return new Meter.Id(name, Tags.empty(), null, null, Meter.Type.OTHER);
299344
}
300345

301346
}

Diff for: implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMeterRegistryTest.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.time.Duration;
3232
import java.util.*;
3333
import java.util.concurrent.TimeUnit;
34+
import java.util.function.Function;
3435
import java.util.stream.IntStream;
3536

3637
import static org.assertj.core.api.Assertions.assertThat;
@@ -427,8 +428,9 @@ public HistogramFlavor histogramFlavor() {
427428
}
428429

429430
@Override
430-
public Map<String, HistogramFlavor> histogramFlavorPerMeter() {
431-
return Collections.singletonMap("expo", HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM);
431+
public Function<Meter.Id, HistogramFlavor> histogramFlavorPerMeter() {
432+
return id -> id.getName().equals("expo") ? HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM
433+
: histogramFlavor();
432434
}
433435
};
434436
OtlpMeterRegistry meterRegistry = new OtlpMeterRegistry(config, clock);
@@ -477,8 +479,8 @@ public int maxBucketCount() {
477479
}
478480

479481
@Override
480-
public Map<String, Integer> maxBucketsPerMeter() {
481-
return Collections.singletonMap("low.variation", 15);
482+
public Function<Meter.Id, Integer> maxBucketsPerMeter() {
483+
return id -> id.getName().equals("low.variation") ? 15 : maxBucketCount();
482484
}
483485
};
484486
OtlpMeterRegistry meterRegistry = new OtlpMeterRegistry(config, clock);

0 commit comments

Comments
 (0)