Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "Prometheus mode" for better micrometer->OTel->Prometheus support #4274

Merged
merged 2 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import io.micrometer.core.instrument.AbstractDistributionSummary;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.Measurement;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
Expand All @@ -26,7 +25,7 @@
import java.util.concurrent.atomic.LongAdder;

final class OpenTelemetryDistributionSummary extends AbstractDistributionSummary
implements DistributionSummary, RemovableMeter {
implements RemovableMeter {

private final Measurements measurements;
private final TimeWindowMax max;
Expand Down Expand Up @@ -77,7 +76,7 @@ boolean isUsingMicrometerHistograms() {

@Override
protected void recordNonNegative(double amount) {
if (amount >= 0 && !removed) {
if (!removed) {
otelHistogram.record(amount, attributes);
measurements.record(amount);
max.record(amount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ public static OpenTelemetryMeterRegistryBuilder builder(OpenTelemetry openTeleme
private final io.opentelemetry.api.metrics.Meter otelMeter;

OpenTelemetryMeterRegistry(
Clock clock, TimeUnit baseTimeUnit, io.opentelemetry.api.metrics.Meter otelMeter) {
Clock clock,
TimeUnit baseTimeUnit,
NamingConvention namingConvention,
io.opentelemetry.api.metrics.Meter otelMeter) {
super(clock);
this.baseTimeUnit = baseTimeUnit;
this.otelMeter = otelMeter;

this.config()
.namingConvention(NamingConvention.identity)
.namingConvention(namingConvention)
.onMeterRemoved(OpenTelemetryMeterRegistry::onMeterRemoved);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.config.NamingConvention;
import io.opentelemetry.api.OpenTelemetry;
import java.util.concurrent.TimeUnit;

Expand All @@ -19,6 +20,7 @@ public final class OpenTelemetryMeterRegistryBuilder {
private final OpenTelemetry openTelemetry;
private Clock clock = Clock.SYSTEM;
private TimeUnit baseTimeUnit = TimeUnit.MILLISECONDS;
private boolean prometheusMode = false;

OpenTelemetryMeterRegistryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
Expand All @@ -36,12 +38,32 @@ public OpenTelemetryMeterRegistryBuilder setBaseTimeUnit(TimeUnit baseTimeUnit)
return this;
}

/**
* Enables the "Prometheus mode" - this will simulate the behavior of Micrometer's {@code
* PrometheusMeterRegistry}. The instruments will be renamed to match Micrometer instrument
* naming, and the base time unit will be set to seconds.
*
* <p>Set this to {@code true} if you are using the Prometheus metrics exporter.
*/
public OpenTelemetryMeterRegistryBuilder setPrometheusMode(boolean prometheusMode) {
this.prometheusMode = prometheusMode;
return this;
}

/**
* Returns a new {@link OpenTelemetryMeterRegistry} with the settings of this {@link
* OpenTelemetryMeterRegistryBuilder}.
*/
public MeterRegistry build() {
// prometheus mode overrides any unit settings with SECONDS
TimeUnit baseTimeUnit = prometheusMode ? TimeUnit.SECONDS : this.baseTimeUnit;
NamingConvention namingConvention =
prometheusMode ? PrometheusModeNamingConvention.INSTANCE : NamingConvention.identity;

return new OpenTelemetryMeterRegistry(
clock, baseTimeUnit, openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME));
clock,
baseTimeUnit,
namingConvention,
openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ boolean isUsingMicrometerHistograms() {

@Override
protected void recordNonNegative(long amount, TimeUnit unit) {
if (amount >= 0 && !removed) {
if (!removed) {
long nanos = unit.toNanos(amount);
double time = TimeUtils.nanosToUnit(nanos, baseTimeUnit);
otelHistogram.record(time, attributes);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.micrometer1shim;

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import javax.annotation.Nullable;

// This naming strategy does not replace '.' with '_', and it does not append '_total' to counter
// names - the reason behind it is that this is already done by the Prometheus exporter; see the
// io.opentelemetry.exporter.prometheus.MetricAdapter class
enum PrometheusModeNamingConvention implements NamingConvention {
INSTANCE;

@Override
public String name(String name, Meter.Type type, @Nullable String baseUnit) {
if (type == Meter.Type.COUNTER
|| type == Meter.Type.DISTRIBUTION_SUMMARY
|| type == Meter.Type.GAUGE) {
if (baseUnit != null && !name.endsWith("." + baseUnit)) {
name = name + "." + baseUnit;
}
}

if (type == Meter.Type.LONG_TASK_TIMER || type == Meter.Type.TIMER) {
if (!name.endsWith(".seconds")) {
name = name + ".seconds";
}
}

return name;
}
}
Loading