Skip to content

Commit

Permalink
OTel Metrics wiring plus exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
brunobat committed Mar 8, 2024
1 parent 6bbae01 commit e449bba
Show file tree
Hide file tree
Showing 33 changed files with 1,022 additions and 567 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;

import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
Expand All @@ -26,9 +29,9 @@
import io.quarkus.opentelemetry.runtime.config.build.exporter.OtlpExporterBuildConfig;
import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig;
import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterRuntimeConfig;
import io.quarkus.opentelemetry.runtime.exporter.otlp.EndUserSpanProcessor;
import io.quarkus.opentelemetry.runtime.exporter.otlp.LateBoundBatchSpanProcessor;
import io.quarkus.opentelemetry.runtime.exporter.otlp.OTelExporterRecorder;
import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.EndUserSpanProcessor;
import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.LateBoundBatchSpanProcessor;
import io.quarkus.runtime.TlsConfig;
import io.quarkus.vertx.core.deployment.CoreVertxBuildItem;

Expand Down Expand Up @@ -84,4 +87,32 @@ void createBatchSpanProcessor(OTelExporterRecorder recorder,
vertxBuildItem.getVertx()))
.done());
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
void createMetricsExporterProcessor(
OTelExporterRecorder recorder,
List<ExternalOtelExporterBuildItem> externalOtelExporterBuildItem,
OTelRuntimeConfig otelRuntimeConfig,
OtlpExporterRuntimeConfig exporterRuntimeConfig,
TlsConfig tlsConfig,
CoreVertxBuildItem vertxBuildItem,
BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItemBuildProducer) {
if (!externalOtelExporterBuildItem.isEmpty()) {
// if there is an external exporter, we don't want to create the default one
return;
}

syntheticBeanBuildItemBuildProducer.produce(SyntheticBeanBuildItem
.configure(PeriodicMetricReader.class)// FIXME concrete class?
.types(MetricReader.class)
.setRuntimeInit()
.scope(Singleton.class)
.unremovable()
.addInjectionPoint(ParameterizedType.create(DotName.createSimple(Instance.class),
new Type[] { ClassType.create(DotName.createSimple(MetricExporter.class.getName())) }, null))
.createWith(recorder.createMetricReader(otelRuntimeConfig, exporterRuntimeConfig, tlsConfig,
vertxBuildItem.getVertx()))
.done());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;

import io.opentelemetry.api.OpenTelemetry;
import io.quarkus.opentelemetry.runtime.exporter.otlp.LateBoundBatchSpanProcessor;
import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.LateBoundBatchSpanProcessor;
import io.quarkus.test.QuarkusUnitTest;

@Disabled("Not implemented")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;

import io.opentelemetry.api.OpenTelemetry;
import io.quarkus.opentelemetry.runtime.exporter.otlp.LateBoundBatchSpanProcessor;
import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.LateBoundBatchSpanProcessor;
import io.quarkus.test.QuarkusUnitTest;

public class OtlpExporterDisabledTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Predicate;

import jakarta.enterprise.inject.Any;
import jakarta.enterprise.inject.Instance;
Expand All @@ -17,6 +18,9 @@
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.IdGenerator;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
Expand All @@ -25,7 +29,8 @@
import io.quarkus.arc.All;
import io.quarkus.opentelemetry.runtime.config.build.OTelBuildConfig;
import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig;
import io.quarkus.opentelemetry.runtime.exporter.otlp.RemoveableLateBoundBatchSpanProcessor;
import io.quarkus.opentelemetry.runtime.exporter.otlp.metrics.NoopMetricReader;
import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.RemoveableLateBoundBatchSpanProcessor;
import io.quarkus.opentelemetry.runtime.propagation.TextMapPropagatorCustomizer;
import io.quarkus.opentelemetry.runtime.tracing.DelayedAttributes;
import io.quarkus.opentelemetry.runtime.tracing.DropTargetsSampler;
Expand Down Expand Up @@ -71,7 +76,12 @@ public Resource apply(Resource existingResource, ConfigProperties configProperti
// inside resource customizer
String serviceName = oTelRuntimeConfig
.serviceName()
.filter(sn -> !sn.equals(appConfig.name.orElse("unset")))
.filter(new Predicate<String>() {
@Override
public boolean test(String sn) {
return !sn.equals(appConfig.name.orElse("unset"));
}
})
.orElse(null);

// must be resolved at startup, once.
Expand Down Expand Up @@ -174,7 +184,12 @@ public SdkTracerProviderBuilder apply(SdkTracerProviderBuilder tracerProviderBui
ConfigProperties configProperties) {
if (oTelBuildConfig.traces().enabled().orElse(TRUE)) {
idGenerator.stream().findFirst().ifPresent(tracerProviderBuilder::setIdGenerator); // from cdi
spanProcessors.stream().filter(sp -> !(sp instanceof RemoveableLateBoundBatchSpanProcessor))
spanProcessors.stream().filter(new Predicate<SpanProcessor>() {
@Override
public boolean test(SpanProcessor sp) {
return !(sp instanceof RemoveableLateBoundBatchSpanProcessor);
}
})
.forEach(tracerProviderBuilder::addSpanProcessor);
}
return tracerProviderBuilder;
Expand All @@ -183,6 +198,47 @@ public SdkTracerProviderBuilder apply(SdkTracerProviderBuilder tracerProviderBui
}
}

@Singleton
final class MetricProviderCustomizer implements AutoConfiguredOpenTelemetrySdkBuilderCustomizer {
private final OTelBuildConfig oTelBuildConfig;
private final OTelRuntimeConfig oTelRuntimeConfig;
private final Clock clock;
private final List<MetricReader> metricReaders;

public MetricProviderCustomizer(OTelBuildConfig oTelBuildConfig,
final OTelRuntimeConfig oTelRuntimeConfig,
final Clock clock,
final List<MetricReader> metricReaders) {
this.oTelBuildConfig = oTelBuildConfig;
this.oTelRuntimeConfig = oTelRuntimeConfig;
this.clock = clock;
this.metricReaders = metricReaders;
}

@Override
public void customize(AutoConfiguredOpenTelemetrySdkBuilder builder) {
if (oTelBuildConfig.metrics().enabled().orElse(TRUE)) {
builder.addMeterProviderCustomizer(
new BiFunction<SdkMeterProviderBuilder, ConfigProperties, SdkMeterProviderBuilder>() {
@Override
public SdkMeterProviderBuilder apply(SdkMeterProviderBuilder metricProvider,
ConfigProperties configProperties) {
metricProvider.setClock(clock);
metricReaders.stream()
.filter(new Predicate<MetricReader>() {
@Override
public boolean test(MetricReader metricReader) {
return !(metricReader instanceof NoopMetricReader);
}
})
.forEach(metricProvider::registerMetricReader);
return metricProvider;
}
});
}
}
}

@Singleton
final class TextMapPropagatorCustomizers implements AutoConfiguredOpenTelemetrySdkBuilderCustomizer {

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

import java.util.Optional;

import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.EndUserSpanProcessor;
import io.quarkus.runtime.annotations.ConfigGroup;
import io.smallrye.config.WithDefault;

Expand All @@ -12,9 +13,9 @@
public interface EndUserSpanProcessorConfig {

/**
* Enable the {@link io.quarkus.opentelemetry.runtime.exporter.otlp.EndUserSpanProcessor}.
* Enable the {@link EndUserSpanProcessor}.
* <p>
* The {@link io.quarkus.opentelemetry.runtime.exporter.otlp.EndUserSpanProcessor} adds
* The {@link EndUserSpanProcessor} adds
* the {@link io.opentelemetry.semconv.SemanticAttributes.ENDUSER_ID}
* and {@link io.opentelemetry.semconv.SemanticAttributes.ENDUSER_ROLE} to the Span.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.quarkus.opentelemetry.runtime.config.runtime;

import static io.quarkus.opentelemetry.runtime.config.runtime.ExemplarsFilterType.Constants.TRACE_BASED;

import java.time.Duration;

import io.smallrye.config.WithDefault;
Expand All @@ -22,14 +20,14 @@ public interface MetricsRuntimeConfig {
@WithDefault("60s")
Duration exportInterval();

/**
* The filter for exemplar sampling. Can be ALWAYS_OFF, ALWAYS_ON or TRACE_BASED.
* <p>
* Default is TRACE_BASED.
*
* @return the value from {@value io.quarkus.opentelemetry.runtime.config.runtime.ExemplarsFilterType}.
*/
@WithName("exemplars.filter")
@WithDefault(TRACE_BASED)
String exemplarsFilter();
// /**
// * The filter for exemplar sampling. Can be ALWAYS_OFF, ALWAYS_ON or TRACE_BASED.
// * <p>
// * Default is TRACE_BASED.
// *
// * @return the value from {@value io.quarkus.opentelemetry.runtime.config.runtime.ExemplarsFilterType}.
// */
// @WithName("exemplars.filter")
// @WithDefault(TRACE_BASED)
// String exemplarsFilter();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package io.quarkus.opentelemetry.runtime.config.runtime.exporter;

import static io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterRuntimeConfig.DEFAULT_GRPC_BASE_URI;

import java.time.Duration;
import java.util.List;
import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigGroup;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithName;

@ConfigGroup
public interface OtlpExporterConfig {

/**
* OTLP Exporter specific. Will override <code>otel.exporter.otlp.endpoint</code>, if set.
* <p>
* Fallbacks to the legacy property <code>quarkus.opentelemetry.tracer.exporter.otlp.endpoint<</code> or
* defaults to {@value OtlpExporterRuntimeConfig#DEFAULT_GRPC_BASE_URI}.
*/
@WithDefault(DEFAULT_GRPC_BASE_URI)
Optional<String> endpoint();

/**
* Key-value pairs to be used as headers associated with gRPC requests.
* The format is similar to the {@code OTEL_EXPORTER_OTLP_HEADERS} environment variable,
* a list of key-value pairs separated by the "=" character. i.e.: key1=value1,key2=value2
*/
Optional<List<String>> headers();

/**
* Sets the method used to compress payloads. If unset, compression is disabled. Currently
* supported compression methods include `gzip` and `none`.
*/
Optional<CompressionType> compression();

/**
* Sets the maximum time to wait for the collector to process an exported batch of spans. If
* unset, defaults to {@value OtlpExporterRuntimeConfig#DEFAULT_TIMEOUT_SECS}s.
*/
@WithDefault("10s")
Duration timeout();

/**
* OTLP defines the encoding of telemetry data and the protocol used to exchange data between the client and the
* server. Depending on the exporter, the available protocols will be different.
* <p>
* Currently, only {@code grpc} and {@code http/protobuf} are allowed.
*/
@WithDefault(Protocol.GRPC)
Optional<String> protocol();

/**
* Key/cert configuration in the PEM format.
*/
@WithName("key-cert")
KeyCert keyCert();

/**
* Trust configuration in the PEM format.
*/
@WithName("trust-cert")
TrustCert trustCert();

interface KeyCert {
/**
* Comma-separated list of the path to the key files (Pem format).
*/
Optional<List<String>> keys();

/**
* Comma-separated list of the path to the certificate files (Pem format).
*/
Optional<List<String>> certs();
}

interface TrustCert {
/**
* Comma-separated list of the trust certificate files (Pem format).
*/
Optional<List<String>> certs();
}

class Protocol {
public static final String GRPC = "grpc";
public static final String HTTP_PROTOBUF = "http/protobuf";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ public interface OtlpExporterRuntimeConfig {
* OTLP traces exporter configuration.
*/
OtlpExporterTracesConfig traces();
// TODO metrics();

/**
* OTLP metrics exporter configuration.
*/
OtlpExporterConfig metrics();
// TODO logs();
// TODO additional global exporter configuration

Expand Down
Loading

0 comments on commit e449bba

Please sign in to comment.