Skip to content

Commit

Permalink
JIT exporter metrics (open-telemetry#4993)
Browse files Browse the repository at this point in the history
* Build ExporterMetrics instruments just in time

* Exporters use GlobalOpenTelemetry#getMeterProvider() if meter provider is not set

* FullConfigTest reset GlobalOpenTelemetry

* MetricExporters use MeterProvider.noop()
  • Loading branch information
jack-berg authored and dmarkwat committed Dec 30, 2022
1 parent 2ac57ee commit 7e576c5
Show file tree
Hide file tree
Showing 17 changed files with 106 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterProvider;
import java.util.function.Supplier;
import javax.annotation.Nullable;

/**
* Helper for recording metrics from exporters.
Expand All @@ -25,45 +27,77 @@ public class ExporterMetrics {
private static final AttributeKey<String> ATTRIBUTE_KEY_TYPE = stringKey("type");
private static final AttributeKey<Boolean> ATTRIBUTE_KEY_SUCCESS = booleanKey("success");

private final LongCounter seen;
private final LongCounter exported;

private final Supplier<MeterProvider> meterProviderSupplier;
private final String exporterName;
private final String transportName;
private final Attributes seenAttrs;
private final Attributes successAttrs;
private final Attributes failedAttrs;

/** Access via {@link #seen()}. */
@Nullable private volatile LongCounter seen;

/** Access via {@link #exported()} . */
@Nullable private volatile LongCounter exported;

private ExporterMetrics(
MeterProvider meterProvider, String exporterName, String type, String transportName) {
Meter meter =
meterProvider.get("io.opentelemetry.exporters." + exporterName + "-" + transportName);
seenAttrs = Attributes.builder().put(ATTRIBUTE_KEY_TYPE, type).build();
seen = meter.counterBuilder(exporterName + ".exporter.seen").build();
exported = meter.counterBuilder(exporterName + ".exporter.exported").build();
successAttrs = seenAttrs.toBuilder().put(ATTRIBUTE_KEY_SUCCESS, true).build();
failedAttrs = seenAttrs.toBuilder().put(ATTRIBUTE_KEY_SUCCESS, false).build();
Supplier<MeterProvider> meterProviderSupplier,
String exporterName,
String type,
String transportName) {
this.meterProviderSupplier = meterProviderSupplier;
this.exporterName = exporterName;
this.transportName = transportName;
this.seenAttrs = Attributes.builder().put(ATTRIBUTE_KEY_TYPE, type).build();
this.successAttrs = this.seenAttrs.toBuilder().put(ATTRIBUTE_KEY_SUCCESS, true).build();
this.failedAttrs = this.seenAttrs.toBuilder().put(ATTRIBUTE_KEY_SUCCESS, false).build();
}

/** Record number of records seen. */
public void addSeen(long value) {
seen.add(value, seenAttrs);
seen().add(value, seenAttrs);
}

/** Record number of records which successfully exported. */
public void addSuccess(long value) {
exported.add(value, successAttrs);
exported().add(value, successAttrs);
}

/** Record number of records which failed to export. */
public void addFailed(long value) {
exported.add(value, failedAttrs);
exported().add(value, failedAttrs);
}

private LongCounter seen() {
LongCounter seen = this.seen;
if (seen == null) {
seen = meter().counterBuilder(exporterName + ".exporter.seen").build();
this.seen = seen;
}
return seen;
}

private LongCounter exported() {
LongCounter exported = this.exported;
if (exported == null) {
exported = meter().counterBuilder(exporterName + ".exporter.exported").build();
this.exported = exported;
}
return exported;
}

private Meter meter() {
return meterProviderSupplier
.get()
.get("io.opentelemetry.exporters." + exporterName + "-" + transportName);
}

/**
* Create an instance for recording exporter metrics under the meter {@code
* "io.opentelemetry.exporters." + exporterName + "-grpc}".
*/
public static ExporterMetrics createGrpc(
String exporterName, String type, MeterProvider meterProvider) {
String exporterName, String type, Supplier<MeterProvider> meterProvider) {
return new ExporterMetrics(meterProvider, exporterName, type, "grpc");
}

Expand All @@ -72,7 +106,7 @@ public static ExporterMetrics createGrpc(
* "io.opentelemetry.exporters." + exporterName + "-grpc-okhttp}".
*/
public static ExporterMetrics createGrpcOkHttp(
String exporterName, String type, MeterProvider meterProvider) {
String exporterName, String type, Supplier<MeterProvider> meterProvider) {
return new ExporterMetrics(meterProvider, exporterName, type, "grpc-okhttp");
}

Expand All @@ -81,7 +115,7 @@ public static ExporterMetrics createGrpcOkHttp(
* "io.opentelemetry.exporters." + exporterName + "-http}".
*/
public static ExporterMetrics createHttpProtobuf(
String exporterName, String type, MeterProvider meterProvider) {
String exporterName, String type, Supplier<MeterProvider> meterProvider) {
return new ExporterMetrics(meterProvider, exporterName, type, "http");
}

Expand All @@ -90,7 +124,7 @@ public static ExporterMetrics createHttpProtobuf(
* "io.opentelemetry.exporters." + exporterName + "-http-json}".
*/
public static ExporterMetrics createHttpJson(
String exporterName, String type, MeterProvider meterProvider) {
String exporterName, String type, Supplier<MeterProvider> meterProvider) {
return new ExporterMetrics(meterProvider, exporterName, type, "http-json");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import io.grpc.ManagedChannel;
import io.grpc.Metadata;
import io.grpc.stub.MetadataUtils;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
import io.opentelemetry.exporter.internal.TlsUtil;
Expand Down Expand Up @@ -58,7 +59,7 @@ public class GrpcExporterBuilder<T extends Marshaler> {
@Nullable private byte[] privateKeyPem;
@Nullable private byte[] certificatePem;
@Nullable private RetryPolicy retryPolicy;
private MeterProvider meterProvider = MeterProvider.noop();
private Supplier<MeterProvider> meterProviderSupplier = GlobalOpenTelemetry::getMeterProvider;

// Use Object type since gRPC may not be on the classpath.
@Nullable private Object grpcChannel;
Expand Down Expand Up @@ -124,7 +125,7 @@ public GrpcExporterBuilder<T> setRetryPolicy(RetryPolicy retryPolicy) {
}

public GrpcExporterBuilder<T> setMeterProvider(MeterProvider meterProvider) {
this.meterProvider = meterProvider;
this.meterProviderSupplier = () -> meterProvider;
return this;
}

Expand Down Expand Up @@ -177,7 +178,7 @@ public GrpcExporter<T> build() {
exporterName,
type,
clientBuilder.build(),
meterProvider,
meterProviderSupplier,
endpoint,
headers.build(),
compressionEnabled);
Expand Down Expand Up @@ -209,7 +210,8 @@ private GrpcExporter<T> buildWithChannel(Channel channel) {
.get()
.apply(channel, authorityOverride)
.withCompression(codec.getMessageEncoding());
return new UpstreamGrpcExporter<>(exporterName, type, stub, meterProvider, timeoutNanos);
return new UpstreamGrpcExporter<>(
exporterName, type, stub, meterProviderSupplier, timeoutNanos);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -75,12 +76,13 @@ public final class OkHttpGrpcExporter<T extends Marshaler> implements GrpcExport
String exporterName,
String type,
OkHttpClient client,
MeterProvider meterProvider,
Supplier<MeterProvider> meterProviderSupplier,
String endpoint,
Headers headers,
boolean compressionEnabled) {
this.type = type;
this.exporterMetrics = ExporterMetrics.createGrpcOkHttp(exporterName, type, meterProvider);
this.exporterMetrics =
ExporterMetrics.createGrpcOkHttp(exporterName, type, meterProviderSupplier);
this.client = client;
this.url = HttpUrl.get(endpoint);
this.headers = headers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.opentelemetry.sdk.internal.ThrottlingLogger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down Expand Up @@ -46,10 +47,10 @@ public final class UpstreamGrpcExporter<T extends Marshaler> implements GrpcExpo
String exporterName,
String type,
MarshalerServiceStub<T, ?, ?> stub,
MeterProvider meterProvider,
Supplier<MeterProvider> meterProviderSupplier,
long timeoutNanos) {
this.type = type;
this.exporterMetrics = ExporterMetrics.createGrpc(exporterName, type, meterProvider);
this.exporterMetrics = ExporterMetrics.createGrpc(exporterName, type, meterProviderSupplier);
this.timeoutNanos = timeoutNanos;
this.stub = stub;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.opentelemetry.sdk.internal.ThrottlingLogger;
import java.io.IOException;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -57,7 +58,7 @@ public final class OkHttpExporter<T extends Marshaler> {
String exporterName,
String type,
OkHttpClient client,
MeterProvider meterProvider,
Supplier<MeterProvider> meterProviderSupplier,
String endpoint,
@Nullable Headers headers,
boolean compressionEnabled,
Expand All @@ -70,8 +71,8 @@ public final class OkHttpExporter<T extends Marshaler> {
this.requestBodyCreator = exportAsJson ? JsonRequestBody::new : ProtoRequestBody::new;
this.exporterMetrics =
exportAsJson
? ExporterMetrics.createHttpJson(exporterName, type, meterProvider)
: ExporterMetrics.createHttpProtobuf(exporterName, type, meterProvider);
? ExporterMetrics.createHttpJson(exporterName, type, meterProviderSupplier)
: ExporterMetrics.createHttpProtobuf(exporterName, type, meterProviderSupplier);
}

public CompletableResultCode export(T exportRequest, int numItems) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.opentelemetry.exporter.internal.okhttp;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
import io.opentelemetry.exporter.internal.TlsUtil;
Expand All @@ -15,6 +16,7 @@
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import javax.net.ssl.SSLException;
import javax.net.ssl.X509KeyManager;
Expand Down Expand Up @@ -46,7 +48,7 @@ public final class OkHttpExporterBuilder<T extends Marshaler> {
@Nullable private byte[] privateKeyPem;
@Nullable private byte[] certificatePem;
@Nullable private RetryPolicy retryPolicy;
private MeterProvider meterProvider = MeterProvider.noop();
private Supplier<MeterProvider> meterProviderSupplier = GlobalOpenTelemetry::getMeterProvider;
@Nullable private Authenticator authenticator;

public OkHttpExporterBuilder(String exporterName, String type, String defaultEndpoint) {
Expand Down Expand Up @@ -101,7 +103,7 @@ public OkHttpExporterBuilder<T> setClientTls(byte[] privateKeyPem, byte[] certif
}

public OkHttpExporterBuilder<T> setMeterProvider(MeterProvider meterProvider) {
this.meterProvider = meterProvider;
this.meterProviderSupplier = () -> meterProvider;
return this;
}

Expand Down Expand Up @@ -158,7 +160,7 @@ public OkHttpExporter<T> build() {
exporterName,
type,
clientBuilder.build(),
meterProvider,
meterProviderSupplier,
endpoint,
headers,
compressionEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static java.util.Objects.requireNonNull;

import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
Expand Down Expand Up @@ -119,8 +120,8 @@ public JaegerGrpcSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] c
}

/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, metrics
* will not be collected.
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.
*
* @since 1.15.0
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static io.opentelemetry.api.internal.Utils.checkArgument;
import static java.util.Objects.requireNonNull;

import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.okhttp.OkHttpExporterBuilder;
import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler;
Expand Down Expand Up @@ -39,6 +40,7 @@ public final class OtlpHttpMetricExporterBuilder {

OtlpHttpMetricExporterBuilder() {
delegate = new OkHttpExporterBuilder<>("otlp", "metric", DEFAULT_ENDPOINT);
delegate.setMeterProvider(MeterProvider.noop());
OtlpUserAgent.addUserAgentHeader(delegate::addHeader);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static io.opentelemetry.api.internal.Utils.checkArgument;
import static java.util.Objects.requireNonNull;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.okhttp.OkHttpExporterBuilder;
import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
Expand Down Expand Up @@ -100,8 +101,8 @@ public OtlpHttpSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] cer
}

/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, metrics
* will not be collected.
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpHttpSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static java.util.Objects.requireNonNull;

import io.grpc.ManagedChannel;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
Expand Down Expand Up @@ -57,6 +58,7 @@ public final class OtlpGrpcMetricExporterBuilder {
DEFAULT_ENDPOINT,
() -> MarshalerMetricsServiceGrpc::newFutureStub,
GRPC_ENDPOINT_PATH);
delegate.setMeterProvider(MeterProvider.noop());
OtlpUserAgent.addUserAgentHeader(delegate::addHeader);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static java.util.Objects.requireNonNull;

import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
Expand Down Expand Up @@ -141,8 +142,8 @@ public OtlpGrpcSpanExporterBuilder addHeader(String key, String value) {
}

/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, metrics
* will not be collected.
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpGrpcSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static io.opentelemetry.api.internal.Utils.checkArgument;
import static java.util.Objects.requireNonNull;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.okhttp.OkHttpExporterBuilder;
import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
Expand Down Expand Up @@ -97,8 +98,8 @@ public OtlpHttpLogRecordExporterBuilder setClientTls(
}

/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, metrics
* will not be collected.
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpHttpLogRecordExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
Expand Down
Loading

0 comments on commit 7e576c5

Please sign in to comment.