From 956b5660de8d2095aa8209cfc2aee89403d8ad29 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Thu, 10 Feb 2022 02:48:13 +0100 Subject: [PATCH] Implement NamingConvention support in Micrometer bridge (#5328) * Implement NamingConvention support in Micrometer bridge * default naming convention --- .../micrometer/v1_5/Bridging.java | 20 +- .../micrometer/v1_5/OpenTelemetryCounter.java | 9 +- .../OpenTelemetryDistributionSummary.java | 9 +- .../v1_5/OpenTelemetryFunctionCounter.java | 10 +- .../v1_5/OpenTelemetryFunctionTimer.java | 8 +- .../micrometer/v1_5/OpenTelemetryGauge.java | 11 +- .../v1_5/OpenTelemetryLongTaskTimer.java | 10 +- .../micrometer/v1_5/OpenTelemetryMeter.java | 10 +- .../v1_5/OpenTelemetryMeterRegistry.java | 34 ++- .../micrometer/v1_5/OpenTelemetryTimer.java | 9 +- .../micrometer/v1_5/NamingConventionTest.java | 253 ++++++++++++++++++ 11 files changed, 352 insertions(+), 31 deletions(-) create mode 100644 instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/Bridging.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/Bridging.java index bf5afd621d2d..b6292385d382 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/Bridging.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/Bridging.java @@ -8,6 +8,7 @@ import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.Statistic; import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.config.NamingConvention; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; @@ -17,18 +18,28 @@ final class Bridging { private static final Cache> tagsCache = Cache.bounded(1024); - static Attributes tagsAsAttributes(Meter.Id id) { + static Attributes tagsAsAttributes(Meter.Id id, NamingConvention namingConvention) { Iterable tags = id.getTagsAsIterable(); if (!tags.iterator().hasNext()) { return Attributes.empty(); } AttributesBuilder builder = Attributes.builder(); for (Tag tag : tags) { - builder.put(tagsCache.computeIfAbsent(tag.getKey(), AttributeKey::stringKey), tag.getValue()); + String tagKey = namingConvention.tagKey(tag.getKey()); + String tagValue = namingConvention.tagValue(tag.getValue()); + builder.put(tagsCache.computeIfAbsent(tagKey, AttributeKey::stringKey), tagValue); } return builder.build(); } + static String name(Meter.Id id, NamingConvention namingConvention) { + return name(id.getName(), id, namingConvention); + } + + private static String name(String name, Meter.Id id, NamingConvention namingConvention) { + return namingConvention.name(name, id.getType(), id.getBaseUnit()); + } + static String description(Meter.Id id) { String description = id.getDescription(); return description == null ? "" : description; @@ -39,12 +50,13 @@ static String baseUnit(Meter.Id id) { return baseUnit == null ? "1" : baseUnit; } - static String statisticInstrumentName(Meter.Id id, Statistic statistic) { + static String statisticInstrumentName( + Meter.Id id, Statistic statistic, NamingConvention namingConvention) { String prefix = id.getName() + "."; // use "total_time" instead of "total" to avoid clashing with Statistic.TOTAL String statisticStr = statistic == Statistic.TOTAL_TIME ? "total_time" : statistic.getTagValueRepresentation(); - return prefix + statisticStr; + return name(prefix + statisticStr, id, namingConvention); } private Bridging() {} diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryCounter.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryCounter.java index 40f991e6bee2..995d61db4a11 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryCounter.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryCounter.java @@ -7,10 +7,12 @@ import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.baseUnit; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description; +import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.Measurement; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.MeterEquivalence; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleCounter; @@ -28,16 +30,17 @@ final class OpenTelemetryCounter implements Counter, RemovableMeter { private volatile boolean removed = false; - OpenTelemetryCounter(Id id, Meter otelMeter) { + OpenTelemetryCounter(Id id, NamingConvention namingConvention, Meter otelMeter) { this.id = id; + + this.attributes = tagsAsAttributes(id, namingConvention); this.otelCounter = otelMeter - .counterBuilder(id.getName()) + .counterBuilder(name(id, namingConvention)) .setDescription(description(id)) .setUnit(baseUnit(id)) .ofDoubles() .build(); - this.attributes = tagsAsAttributes(id); } @Override diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryDistributionSummary.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryDistributionSummary.java index 5d5ae6b5cab0..aa0c4d869c35 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryDistributionSummary.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryDistributionSummary.java @@ -7,6 +7,7 @@ import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.baseUnit; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description; +import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes; @@ -15,6 +16,7 @@ import io.micrometer.core.instrument.DistributionSummary; import io.micrometer.core.instrument.Measurement; import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import io.micrometer.core.instrument.distribution.NoopHistogram; import io.micrometer.core.instrument.distribution.TimeWindowMax; @@ -41,6 +43,7 @@ final class OpenTelemetryDistributionSummary extends AbstractDistributionSummary OpenTelemetryDistributionSummary( Id id, + NamingConvention namingConvention, Clock clock, DistributionStatisticConfig distributionStatisticConfig, double scale, @@ -55,16 +58,16 @@ final class OpenTelemetryDistributionSummary extends AbstractDistributionSummary } max = new TimeWindowMax(clock, distributionStatisticConfig); - this.attributes = tagsAsAttributes(id); + this.attributes = tagsAsAttributes(id, namingConvention); this.otelHistogram = otelMeter - .histogramBuilder(id.getName()) + .histogramBuilder(name(id, namingConvention)) .setDescription(description(id)) .setUnit(baseUnit(id)) .build(); this.maxHandle = asyncInstrumentRegistry.buildGauge( - statisticInstrumentName(id, Statistic.MAX), + statisticInstrumentName(id, Statistic.MAX, namingConvention), description(id), baseUnit(id), attributes, diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionCounter.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionCounter.java index c7d88b82ebed..a4d530a7eb22 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionCounter.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionCounter.java @@ -7,10 +7,12 @@ import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.baseUnit; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description; +import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes; import io.micrometer.core.instrument.FunctionCounter; import io.micrometer.core.instrument.Measurement; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.MeterEquivalence; import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry; import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry.AsyncMeasurementHandle; @@ -26,6 +28,7 @@ final class OpenTelemetryFunctionCounter implements FunctionCounter, Removabl OpenTelemetryFunctionCounter( Id id, + NamingConvention namingConvention, T obj, ToDoubleFunction countFunction, AsyncInstrumentRegistry asyncInstrumentRegistry) { @@ -33,7 +36,12 @@ final class OpenTelemetryFunctionCounter implements FunctionCounter, Removabl countMeasurementHandle = asyncInstrumentRegistry.buildDoubleCounter( - id.getName(), description(id), baseUnit(id), tagsAsAttributes(id), obj, countFunction); + name(id, namingConvention), + description(id), + baseUnit(id), + tagsAsAttributes(id, namingConvention), + obj, + countFunction); } @Override diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionTimer.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionTimer.java index fd5d91a60ae6..fd7f35246854 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionTimer.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionTimer.java @@ -13,6 +13,7 @@ import io.micrometer.core.instrument.FunctionTimer; import io.micrometer.core.instrument.Measurement; import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.MeterEquivalence; import io.micrometer.core.instrument.util.TimeUtils; import io.opentelemetry.api.common.Attributes; @@ -34,6 +35,7 @@ final class OpenTelemetryFunctionTimer implements FunctionTimer, RemovableMet OpenTelemetryFunctionTimer( Id id, + NamingConvention namingConvention, T obj, ToLongFunction countFunction, ToDoubleFunction totalTimeFunction, @@ -44,9 +46,9 @@ final class OpenTelemetryFunctionTimer implements FunctionTimer, RemovableMet this.id = id; this.baseTimeUnit = baseTimeUnit; - String countMeterName = statisticInstrumentName(id, Statistic.COUNT); - String totalTimeMeterName = statisticInstrumentName(id, Statistic.TOTAL_TIME); - Attributes attributes = tagsAsAttributes(id); + String countMeterName = statisticInstrumentName(id, Statistic.COUNT, namingConvention); + String totalTimeMeterName = statisticInstrumentName(id, Statistic.TOTAL_TIME, namingConvention); + Attributes attributes = tagsAsAttributes(id, namingConvention); countMeasurementHandle = asyncInstrumentRegistry.buildLongCounter( diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryGauge.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryGauge.java index bd94792db959..b36f91be2e2f 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryGauge.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryGauge.java @@ -7,10 +7,12 @@ import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.baseUnit; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description; +import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.Measurement; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.MeterEquivalence; import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry; import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry.AsyncMeasurementHandle; @@ -26,14 +28,21 @@ final class OpenTelemetryGauge implements Gauge, RemovableMeter { OpenTelemetryGauge( Id id, + NamingConvention namingConvention, @Nullable T obj, ToDoubleFunction objMetric, AsyncInstrumentRegistry asyncInstrumentRegistry) { + this.id = id; gaugeMeasurementHandle = asyncInstrumentRegistry.buildGauge( - id.getName(), description(id), baseUnit(id), tagsAsAttributes(id), obj, objMetric); + name(id, namingConvention), + description(id), + baseUnit(id), + tagsAsAttributes(id, namingConvention), + obj, + objMetric); } @Override diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java index e1a1e596afd4..e8fd8f0fb7f3 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.micrometer.v1_5; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description; +import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes; import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString; @@ -13,6 +14,7 @@ import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Measurement; import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import io.micrometer.core.instrument.internal.DefaultLongTaskTimer; import io.micrometer.core.instrument.util.TimeUtils; @@ -36,6 +38,7 @@ final class OpenTelemetryLongTaskTimer extends DefaultLongTaskTimer implements R OpenTelemetryLongTaskTimer( Id id, + NamingConvention namingConvention, Clock clock, TimeUnit baseTimeUnit, DistributionStatisticConfig distributionStatisticConfig, @@ -47,17 +50,18 @@ final class OpenTelemetryLongTaskTimer extends DefaultLongTaskTimer implements R this.otelHistogram = otelMeter - .histogramBuilder(id.getName()) + .histogramBuilder(name(id, namingConvention)) .setDescription(description(id)) .setUnit(getUnitString(baseTimeUnit)) .build(); this.otelActiveTasksCounter = otelMeter - .upDownCounterBuilder(statisticInstrumentName(id, Statistic.ACTIVE_TASKS)) + .upDownCounterBuilder( + statisticInstrumentName(id, Statistic.ACTIVE_TASKS, namingConvention)) .setDescription(description(id)) .setUnit("tasks") .build(); - this.attributes = tagsAsAttributes(id); + this.attributes = tagsAsAttributes(id, namingConvention); } @Override diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeter.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeter.java index 9a7491f95d86..b57c646297e3 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeter.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeter.java @@ -12,6 +12,7 @@ import io.micrometer.core.instrument.Measurement; import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.MeterEquivalence; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry; @@ -28,13 +29,16 @@ final class OpenTelemetryMeter implements Meter, RemovableMeter { private final List measurementHandles; OpenTelemetryMeter( - Id id, Iterable measurements, AsyncInstrumentRegistry asyncInstrumentRegistry) { + Id id, + NamingConvention namingConvention, + Iterable measurements, + AsyncInstrumentRegistry asyncInstrumentRegistry) { this.id = id; - Attributes attributes = tagsAsAttributes(id); + Attributes attributes = tagsAsAttributes(id, namingConvention); List measurementHandles = new ArrayList<>(); for (Measurement measurement : measurements) { - String name = statisticInstrumentName(id, measurement.getStatistic()); + String name = statisticInstrumentName(id, measurement.getStatistic(), namingConvention); String description = description(id); String baseUnit = baseUnit(id); diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java index 6e219bebce10..fb0c3570b879 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java @@ -16,6 +16,7 @@ import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import io.micrometer.core.instrument.distribution.HistogramGauges; import io.micrometer.core.instrument.distribution.pause.PauseDetector; @@ -59,17 +60,21 @@ public static OpenTelemetryMeterRegistryBuilder builder(OpenTelemetry openTeleme this.baseTimeUnit = baseTimeUnit; this.otelMeter = otelMeter; this.asyncInstrumentRegistry = AsyncInstrumentRegistry.getOrCreate(otelMeter); - this.config().onMeterRemoved(OpenTelemetryMeterRegistry::onMeterRemoved); + + this.config() + .namingConvention(NamingConvention.identity) + .onMeterRemoved(OpenTelemetryMeterRegistry::onMeterRemoved); } @Override protected Gauge newGauge(Meter.Id id, @Nullable T obj, ToDoubleFunction valueFunction) { - return new OpenTelemetryGauge<>(id, obj, valueFunction, asyncInstrumentRegistry); + return new OpenTelemetryGauge<>( + id, config().namingConvention(), obj, valueFunction, asyncInstrumentRegistry); } @Override protected Counter newCounter(Meter.Id id) { - return new OpenTelemetryCounter(id, otelMeter); + return new OpenTelemetryCounter(id, config().namingConvention(), otelMeter); } @Override @@ -77,7 +82,12 @@ protected LongTaskTimer newLongTaskTimer( Meter.Id id, DistributionStatisticConfig distributionStatisticConfig) { OpenTelemetryLongTaskTimer timer = new OpenTelemetryLongTaskTimer( - id, clock, getBaseTimeUnit(), distributionStatisticConfig, otelMeter); + id, + config().namingConvention(), + clock, + getBaseTimeUnit(), + distributionStatisticConfig, + otelMeter); if (timer.isUsingMicrometerHistograms()) { HistogramGauges.registerWithCommonFormat(timer, this); } @@ -92,6 +102,7 @@ protected Timer newTimer( OpenTelemetryTimer timer = new OpenTelemetryTimer( id, + config().namingConvention(), clock, distributionStatisticConfig, pauseDetector, @@ -109,7 +120,13 @@ protected DistributionSummary newDistributionSummary( Meter.Id id, DistributionStatisticConfig distributionStatisticConfig, double scale) { OpenTelemetryDistributionSummary distributionSummary = new OpenTelemetryDistributionSummary( - id, clock, distributionStatisticConfig, scale, otelMeter, asyncInstrumentRegistry); + id, + config().namingConvention(), + clock, + distributionStatisticConfig, + scale, + otelMeter, + asyncInstrumentRegistry); if (distributionSummary.isUsingMicrometerHistograms()) { HistogramGauges.registerWithCommonFormat(distributionSummary, this); } @@ -118,7 +135,8 @@ protected DistributionSummary newDistributionSummary( @Override protected Meter newMeter(Meter.Id id, Meter.Type type, Iterable measurements) { - return new OpenTelemetryMeter(id, measurements, asyncInstrumentRegistry); + return new OpenTelemetryMeter( + id, config().namingConvention(), measurements, asyncInstrumentRegistry); } @Override @@ -130,6 +148,7 @@ protected FunctionTimer newFunctionTimer( TimeUnit totalTimeFunctionUnit) { return new OpenTelemetryFunctionTimer<>( id, + config().namingConvention(), obj, countFunction, totalTimeFunction, @@ -141,7 +160,8 @@ protected FunctionTimer newFunctionTimer( @Override protected FunctionCounter newFunctionCounter( Meter.Id id, T obj, ToDoubleFunction countFunction) { - return new OpenTelemetryFunctionCounter<>(id, obj, countFunction, asyncInstrumentRegistry); + return new OpenTelemetryFunctionCounter<>( + id, config().namingConvention(), obj, countFunction, asyncInstrumentRegistry); } @Override diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java index fec2020a1013..d4596a1a2139 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.micrometer.v1_5; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description; +import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName; import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes; import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString; @@ -14,6 +15,7 @@ import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Measurement; import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import io.micrometer.core.instrument.distribution.NoopHistogram; import io.micrometer.core.instrument.distribution.TimeWindowMax; @@ -42,6 +44,7 @@ final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter { OpenTelemetryTimer( Id id, + NamingConvention namingConvention, Clock clock, DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector, @@ -58,16 +61,16 @@ final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter { max = new TimeWindowMax(clock, distributionStatisticConfig); this.baseTimeUnit = baseTimeUnit; - this.attributes = tagsAsAttributes(id); + this.attributes = tagsAsAttributes(id, namingConvention); this.otelHistogram = otelMeter - .histogramBuilder(id.getName()) + .histogramBuilder(name(id, namingConvention)) .setDescription(description(id)) .setUnit(getUnitString(baseTimeUnit)) .build(); this.maxHandle = asyncInstrumentRegistry.buildGauge( - statisticInstrumentName(id, Statistic.MAX), + statisticInstrumentName(id, Statistic.MAX, namingConvention), description(id), getUnitString(baseTimeUnit), attributes, diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java new file mode 100644 index 000000000000..603d180dc0f3 --- /dev/null +++ b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java @@ -0,0 +1,253 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.micrometer.v1_5; + +import static io.opentelemetry.sdk.testing.assertj.MetricAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.DistributionSummary; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.config.NamingConvention; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +@SuppressWarnings("PreferJavaTimeOverload") +class NamingConventionTest { + + static final String INSTRUMENTATION_NAME = "io.opentelemetry.micrometer-1.5"; + + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + static MeterRegistry otelMeterRegistry; + + @BeforeAll + public static void setUpRegistry() { + otelMeterRegistry = OpenTelemetryMeterRegistry.create(testing.getOpenTelemetry()); + otelMeterRegistry + .config() + .namingConvention( + new NamingConvention() { + @Override + public String name(String name, Meter.Type type, String baseUnit) { + return "test." + name; + } + + @Override + public String tagKey(String key) { + return "test." + key; + } + + @Override + public String tagValue(String value) { + return "test." + value; + } + }); + Metrics.addRegistry(otelMeterRegistry); + } + + @AfterAll + public static void tearDownRegistry() { + Metrics.removeRegistry(otelMeterRegistry); + } + + final AtomicLong num = new AtomicLong(42); + + @Test + void renameCounter() { + // when + Counter counter = Metrics.counter("renamedCounter", "tag", "value"); + counter.increment(); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedCounter", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleSum() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + } + + @Test + void renameDistributionSummary() { + // when + DistributionSummary summary = Metrics.summary("renamedSummary", "tag", "value"); + summary.record(42); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedSummary", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleHistogram() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedSummary.max", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGauge() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + } + + @Test + void renameFunctionCounter() { + // when + Metrics.more().counter("renamedFunctionCounter", Tags.of("tag", "value"), num); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedFunctionCounter", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleSum() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + } + + @Test + void renameFunctionTimer() { + // when + Metrics.more() + .timer( + "renamedFunctionTimer", + Tags.of("tag", "value"), + num, + AtomicLong::longValue, + AtomicLong::doubleValue, + TimeUnit.SECONDS); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedFunctionTimer.count", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasLongSum() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedFunctionTimer.total_time", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleSum() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + } + + @Test + void renameGauge() { + // when + Metrics.gauge("renamedGauge", Tags.of("tag", "value"), num); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedGauge", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGauge() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + } + + @Test + void renameTimer() { + // when + Timer timer = Metrics.timer("renamedTimer", "tag", "value"); + timer.record(10, TimeUnit.SECONDS); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedTimer", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleHistogram() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.renamedTimer.max", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGauge() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .attributes() + .containsOnly(attributeEntry("test.tag", "test.value"))))); + } +}