diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java index d7ff085e7d956a..39d54355bcda58 100644 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java +++ b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java @@ -16,7 +16,6 @@ import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.exporter.otlp.internal.OtlpSpanExporterProvider; import io.opentelemetry.instrumentation.annotations.SpanAttribute; @@ -30,6 +29,7 @@ import io.quarkus.agroal.spi.OpenTelemetryInitBuildItem; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; +import io.quarkus.arc.deployment.BeanContainerBuildItem; import io.quarkus.arc.deployment.InterceptorBindingRegistrarBuildItem; import io.quarkus.arc.deployment.ValidationPhaseBuildItem.ValidationErrorBuildItem; import io.quarkus.arc.processor.AnnotationsTransformer; @@ -43,7 +43,6 @@ import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.LaunchModeBuildItem; import io.quarkus.deployment.builditem.RemovedResourceBuildItem; -import io.quarkus.deployment.builditem.ShutdownContextBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; @@ -56,7 +55,6 @@ import io.quarkus.opentelemetry.runtime.tracing.cdi.WithSpanInterceptor; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.InstrumentationRecorder; import io.quarkus.runtime.LaunchMode; -import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.configuration.ConfigurationException; import io.quarkus.vertx.core.deployment.CoreVertxBuildItem; @@ -185,21 +183,23 @@ public void transform(TransformationContext context) { @Produce(OpenTelemetryInitBuildItem.class) void createOpenTelemetry( OpenTelemetryRecorder recorder, - InstrumentationRecorder instrumentationRecorder, CoreVertxBuildItem vertx, - LaunchModeBuildItem launchMode, - ShutdownContextBuildItem shutdownContextBuildItem) { + LaunchModeBuildItem launchMode) { if (launchMode.getLaunchMode() == LaunchMode.DEVELOPMENT || launchMode.getLaunchMode() == LaunchMode.TEST) { recorder.resetGlobalOpenTelemetryForDevMode(); } - RuntimeValue openTelemetry = recorder.createOpenTelemetry(shutdownContextBuildItem); - recorder.eagerlyCreateContextStorage(); recorder.storeVertxOnContextStorage(vertx.getVertx()); + } + + @BuildStep + @Record(ExecutionTime.RUNTIME_INIT) + void setupVertx(InstrumentationRecorder recorder, + BeanContainerBuildItem beanContainerBuildItem) { - instrumentationRecorder.setTracer(instrumentationRecorder.createTracers(openTelemetry)); + recorder.setupVertxTracer(beanContainerBuildItem.getValue()); } @BuildStep diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java index 92d2d12e9d604c..6859fd1662aa47 100644 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java +++ b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java @@ -4,20 +4,28 @@ import java.util.function.BooleanSupplier; -import io.quarkus.arc.deployment.AdditionalBeanBuildItem; -import io.quarkus.arc.deployment.BeanContainerBuildItem; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Singleton; + +import org.jboss.jandex.ClassType; +import org.jboss.jandex.DotName; +import org.jboss.jandex.ParameterizedType; +import org.jboss.jandex.Type; + +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.quarkus.arc.deployment.SyntheticBeanBuildItem; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.BuildSteps; import io.quarkus.deployment.annotations.ExecutionTime; import io.quarkus.deployment.annotations.Record; -import io.quarkus.deployment.builditem.LaunchModeBuildItem; import io.quarkus.opentelemetry.runtime.config.build.OTelBuildConfig; 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.OtlpExporterProvider; +import io.quarkus.opentelemetry.runtime.exporter.otlp.LateBoundBatchSpanProcessor; import io.quarkus.opentelemetry.runtime.exporter.otlp.OtlpRecorder; -import io.quarkus.vertx.deployment.VertxBuildItem; +import io.quarkus.vertx.core.deployment.CoreVertxBuildItem; @BuildSteps(onlyIf = OtlpExporterProcessor.OtlpExporterEnabled.class) public class OtlpExporterProcessor { @@ -34,25 +42,24 @@ public boolean getAsBoolean() { } } - @BuildStep - AdditionalBeanBuildItem createBatchSpanProcessor() { - return AdditionalBeanBuildItem.builder() - .addBeanClass(OtlpExporterProvider.class) - .setUnremovable().build(); - } - + @SuppressWarnings("deprecation") @BuildStep @Record(ExecutionTime.RUNTIME_INIT) - void installBatchSpanProcessorForOtlp( - OtlpRecorder recorder, - LaunchModeBuildItem launchModeBuildItem, + SyntheticBeanBuildItem createBatchSpanProcessor(OtlpRecorder recorder, OTelRuntimeConfig otelRuntimeConfig, OtlpExporterRuntimeConfig exporterRuntimeConfig, - VertxBuildItem vertxBuildItem, - BeanContainerBuildItem beanContainerBuildItem) { - recorder.installBatchSpanProcessorForOtlp(otelRuntimeConfig, - exporterRuntimeConfig, - vertxBuildItem.getVertx(), - launchModeBuildItem.getLaunchMode()); + CoreVertxBuildItem vertxBuildItem) { + return SyntheticBeanBuildItem + .configure(LateBoundBatchSpanProcessor.class) + .types(SpanProcessor.class) + .setRuntimeInit() + .scope(Singleton.class) + .unremovable() + .addInjectionPoint(ParameterizedType.create(DotName.createSimple(Instance.class), + new Type[] { ClassType.create(DotName.createSimple(SpanExporter.class.getName())) }, null)) + .createWith(recorder.batchSpanProcessorForOtlp(otelRuntimeConfig, exporterRuntimeConfig, + vertxBuildItem.getVertx())) + .done(); + } } diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerIdGeneratorBuildItem.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerIdGeneratorBuildItem.java deleted file mode 100644 index 7374cb84762807..00000000000000 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerIdGeneratorBuildItem.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.quarkus.opentelemetry.deployment.tracing; - -import java.util.Optional; - -import io.opentelemetry.sdk.trace.IdGenerator; -import io.quarkus.builder.item.SimpleBuildItem; -import io.quarkus.runtime.RuntimeValue; - -public final class TracerIdGeneratorBuildItem extends SimpleBuildItem { - private final RuntimeValue> idGenerator; - - public TracerIdGeneratorBuildItem(RuntimeValue> idGenerator) { - this.idGenerator = idGenerator; - } - - public RuntimeValue> getIdGenerator() { - return idGenerator; - } -} diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProcessor.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProcessor.java index c958840b8e702d..35641cf858a209 100644 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProcessor.java +++ b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProcessor.java @@ -143,42 +143,14 @@ void dropNames( @BuildStep @Record(ExecutionTime.STATIC_INIT) - TracerIdGeneratorBuildItem createIdGenerator(TracerRecorder recorder, - BeanContainerBuildItem beanContainerBuildItem) { - return new TracerIdGeneratorBuildItem(recorder.createIdGenerator()); - } - - @BuildStep - @Record(ExecutionTime.STATIC_INIT) - TracerResourceBuildItem createResource(TracerRecorder recorder, - ApplicationInfoBuildItem appInfo, - BeanContainerBuildItem beanContainerBuildItem) { - String serviceName = appInfo.getName(); - String serviceVersion = appInfo.getVersion(); - return new TracerResourceBuildItem(recorder.createResource(Version.getVersion(), serviceName, serviceVersion)); - } - - @BuildStep - @Record(ExecutionTime.STATIC_INIT) - TracerSpanExportersBuildItem createSpanExporters(TracerRecorder recorder, - BeanContainerBuildItem beanContainerBuildItem) { - return new TracerSpanExportersBuildItem(recorder.createSpanExporter()); - } - - @BuildStep - @Record(ExecutionTime.STATIC_INIT) - TracerSpanProcessorsBuildItem createSpanProcessors(TracerRecorder recorder, - BeanContainerBuildItem beanContainerBuildItem) { - return new TracerSpanProcessorsBuildItem(recorder.createSpanProcessors()); - } - - @BuildStep - @Record(ExecutionTime.STATIC_INIT) - void setupTracer( + void staticInitSetup( TracerRecorder recorder, + ApplicationInfoBuildItem appInfo, + BeanContainerBuildItem beanContainerBuildItem, DropNonApplicationUrisBuildItem dropNonApplicationUris, DropStaticResourcesBuildItem dropStaticResources) { - + recorder.setAttributes(beanContainerBuildItem.getValue(), Version.getVersion(), + appInfo.getName(), appInfo.getVersion()); recorder.setupSampler( dropNonApplicationUris.getDropNames(), dropStaticResources.getDropNames()); diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProviderBuildItem.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProviderBuildItem.java deleted file mode 100644 index a912f3b776e052..00000000000000 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerProviderBuildItem.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.quarkus.opentelemetry.deployment.tracing; - -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.quarkus.builder.item.SimpleBuildItem; -import io.quarkus.runtime.RuntimeValue; - -public final class TracerProviderBuildItem extends SimpleBuildItem { - - private final RuntimeValue tracerProvider; - - TracerProviderBuildItem(RuntimeValue tracerProvider) { - this.tracerProvider = tracerProvider; - } - - public RuntimeValue getTracerProvider() { - return tracerProvider; - } -} diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerResourceBuildItem.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerResourceBuildItem.java deleted file mode 100644 index 824bbff551e032..00000000000000 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerResourceBuildItem.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.quarkus.opentelemetry.deployment.tracing; - -import io.opentelemetry.sdk.resources.Resource; -import io.quarkus.builder.item.SimpleBuildItem; -import io.quarkus.runtime.RuntimeValue; - -public final class TracerResourceBuildItem extends SimpleBuildItem { - private final RuntimeValue resource; - - public TracerResourceBuildItem(RuntimeValue resource) { - this.resource = resource; - } - - public RuntimeValue getResource() { - return resource; - } -} diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerSpanExportersBuildItem.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerSpanExportersBuildItem.java deleted file mode 100644 index 629f911e172695..00000000000000 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerSpanExportersBuildItem.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.quarkus.opentelemetry.deployment.tracing; - -import java.util.List; - -import io.opentelemetry.sdk.trace.export.SpanExporter; -import io.quarkus.builder.item.SimpleBuildItem; -import io.quarkus.runtime.RuntimeValue; - -public final class TracerSpanExportersBuildItem extends SimpleBuildItem { - private final RuntimeValue> spanExporters; - - public TracerSpanExportersBuildItem(RuntimeValue> spanExporters) { - this.spanExporters = spanExporters; - } - - public RuntimeValue> getSpanExporters() { - return spanExporters; - } -} diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerSpanProcessorsBuildItem.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerSpanProcessorsBuildItem.java deleted file mode 100644 index 0b0209f72fef04..00000000000000 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/TracerSpanProcessorsBuildItem.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.quarkus.opentelemetry.deployment.tracing; - -import java.util.List; - -import io.opentelemetry.sdk.trace.SpanProcessor; -import io.quarkus.builder.item.SimpleBuildItem; -import io.quarkus.runtime.RuntimeValue; - -public final class TracerSpanProcessorsBuildItem extends SimpleBuildItem { - private final RuntimeValue> spanProcessors; - - public TracerSpanProcessorsBuildItem(RuntimeValue> spanExporters) { - this.spanProcessors = spanExporters; - } - - public RuntimeValue> getSpanProcessors() { - return spanProcessors; - } -} diff --git a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterBadEndpointTest.java b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterBadEndpointTest.java index 0c9906fb63af8b..5d9ab2e4ea83f9 100644 --- a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterBadEndpointTest.java +++ b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterBadEndpointTest.java @@ -16,7 +16,7 @@ public class OtlpExporterBadEndpointTest { .withEmptyApplication() .overrideConfigKey("quarkus.otel.traces.exporter", "cdi") .overrideConfigKey("quarkus.opentelemetry.tracer.exporter.otlp.endpoint", "httz://nada:zero") - .setExpectedException(IllegalStateException.class); + .setExpectedException(IllegalArgumentException.class); @Inject OpenTelemetry openTelemetry; diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryProducer.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryProducer.java index d1ad23b1dd4322..f2087cdbb0b862 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryProducer.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryProducer.java @@ -10,6 +10,7 @@ import java.util.function.BiFunction; import jakarta.enterprise.inject.Any; +import jakarta.enterprise.inject.Disposes; import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; @@ -18,6 +19,7 @@ import org.eclipse.microprofile.config.ConfigProvider; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.resources.Resource; @@ -62,6 +64,14 @@ public class OpenTelemetryProducer { @Inject ApplicationConfig appConfig; + public void disposeOfOpenTelemetry(@Disposes OpenTelemetry openTelemetry) { + if (openTelemetry instanceof OpenTelemetrySdk) { + var openTelemetrySdk = ((OpenTelemetrySdk) openTelemetry); + openTelemetrySdk.getSdkTracerProvider().forceFlush(); + openTelemetrySdk.getSdkTracerProvider().shutdown(); + } + } + @Produces @Singleton @DefaultBean diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java index 4b8612c59ef026..47939edcbc01db 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryRecorder.java @@ -2,18 +2,10 @@ import java.util.function.Supplier; -import jakarta.enterprise.inject.Any; -import jakarta.enterprise.inject.spi.BeanManager; - import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.events.GlobalEventEmitterProvider; import io.opentelemetry.api.logs.GlobalLoggerProvider; import io.opentelemetry.context.ContextStorage; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.quarkus.arc.Arc; -import io.quarkus.runtime.RuntimeValue; -import io.quarkus.runtime.ShutdownContext; import io.quarkus.runtime.annotations.Recorder; import io.vertx.core.Vertx; @@ -29,24 +21,6 @@ public void resetGlobalOpenTelemetryForDevMode() { GlobalEventEmitterProvider.resetForTest(); } - /* RUNTIME INIT */ - public RuntimeValue createOpenTelemetry(ShutdownContext shutdownContext) { - - BeanManager beanManager = Arc.container().beanManager(); - - OpenTelemetry openTelemetry = beanManager.createInstance() - .select(OpenTelemetry.class, Any.Literal.INSTANCE).get(); - - // Because we are producing the ObfuscatedOpenTelemetry. These methods are not be available otherwise. - // Register shutdown tasks, because we are using CDI beans - shutdownContext.addShutdownTask(() -> { - ((OpenTelemetrySdk) openTelemetry).getSdkTracerProvider().forceFlush(); - ((OpenTelemetrySdk) openTelemetry).getSdkTracerProvider().shutdown(); - }); - - return new RuntimeValue<>(openTelemetry); - } - /* RUNTIME INIT */ public void eagerlyCreateContextStorage() { ContextStorage.get(); diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProvider.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProvider.java deleted file mode 100644 index 4d8b016d97b02d..00000000000000 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.quarkus.opentelemetry.runtime.exporter.otlp; - -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Singleton; - -@Deprecated -@Singleton -public class OtlpExporterProvider { - @Produces - @Singleton - public LateBoundBatchSpanProcessor batchSpanProcessorForOtlp() { - return new LateBoundBatchSpanProcessor(); - } -} diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorder.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorder.java index 7704736dcc051c..b03a806eaee35c 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorder.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorder.java @@ -8,9 +8,11 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; -import jakarta.enterprise.inject.Any; -import jakarta.enterprise.inject.spi.CDI; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.util.TypeLiteral; import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.exporter.internal.ExporterBuilderUtil; @@ -18,12 +20,11 @@ import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder; import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.quarkus.arc.SyntheticCreationalContext; import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig; import io.quarkus.opentelemetry.runtime.config.runtime.exporter.CompressionType; import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterRuntimeConfig; import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterTracesConfig; -import io.quarkus.runtime.LaunchMode; -import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientOptions; @@ -31,152 +32,162 @@ import io.vertx.core.net.PemKeyCertOptions; import io.vertx.core.net.PemTrustOptions; +@SuppressWarnings("deprecation") @Recorder public class OtlpRecorder { - static String resolveEndpoint(final OtlpExporterRuntimeConfig runtimeConfig) { - String endpoint = runtimeConfig.traces().legacyEndpoint() - .filter(OtlpRecorder::excludeDefaultEndpoint) - .orElse(runtimeConfig.traces().endpoint() - .filter(OtlpRecorder::excludeDefaultEndpoint) - .orElse(runtimeConfig.endpoint() - .filter(OtlpRecorder::excludeDefaultEndpoint) - .orElse(DEFAULT_GRPC_BASE_URI))); - return endpoint.trim(); - } - - private static boolean excludeDefaultEndpoint(String endpoint) { - return !DEFAULT_GRPC_BASE_URI.equals(endpoint); - } - - public void installBatchSpanProcessorForOtlp( + public Function, LateBoundBatchSpanProcessor> batchSpanProcessorForOtlp( OTelRuntimeConfig otelRuntimeConfig, OtlpExporterRuntimeConfig exporterRuntimeConfig, - RuntimeValue vertx, - LaunchMode launchMode) { - - if (otelRuntimeConfig.sdkDisabled()) { - return; - } - String grpcBaseUri = resolveEndpoint(exporterRuntimeConfig).trim(); - - // Only create the OtlpGrpcSpanExporter if an endpoint was set in runtime config - if (grpcBaseUri.length() > 0) { - try { - // Load span exporter if provided by user - SpanExporter spanExporter = CDI.current() - .select(SpanExporter.class, Any.Literal.INSTANCE).stream().findFirst().orElse(null); - // CDI exporter was already added to a processor by OTEL - if (spanExporter == null) { - spanExporter = createOtlpGrpcSpanExporter(exporterRuntimeConfig, grpcBaseUri, vertx.getValue()); - - // Create BatchSpanProcessor for OTLP and install into LateBoundBatchSpanProcessor - LateBoundBatchSpanProcessor delayedProcessor = CDI.current() - .select(LateBoundBatchSpanProcessor.class, Any.Literal.INSTANCE).get(); - - BatchSpanProcessorBuilder processorBuilder = BatchSpanProcessor.builder(spanExporter); - - processorBuilder.setScheduleDelay(otelRuntimeConfig.bsp().scheduleDelay()); - processorBuilder.setMaxQueueSize(otelRuntimeConfig.bsp().maxQueueSize()); - processorBuilder.setMaxExportBatchSize(otelRuntimeConfig.bsp().maxExportBatchSize()); - processorBuilder.setExporterTimeout(otelRuntimeConfig.bsp().exportTimeout()); - // processorBuilder.setMeterProvider() // TODO add meter provider to span processor. - - delayedProcessor.setBatchSpanProcessorDelegate(processorBuilder.build()); + Supplier vertx) { + var result = new LateBoundBatchSpanProcessor(); + URI grpcBaseUri = getGrpcBaseUri(exporterRuntimeConfig); // do the creation and validation here in order to preserve backward compatibility + return new Function<>() { + @Override + public LateBoundBatchSpanProcessor apply( + SyntheticCreationalContext context) { + if (otelRuntimeConfig.sdkDisabled()) { + return result; } - } catch (IllegalArgumentException iae) { - throw new IllegalStateException("Unable to install OTLP Exporter", iae); - } - } - } - private SpanExporter createOtlpGrpcSpanExporter(OtlpExporterRuntimeConfig exporterRuntimeConfig, String endpoint, - Vertx vertx) { + // Only create the OtlpGrpcSpanExporter if an endpoint was set in runtime config and was properly validated at startup + if (grpcBaseUri != null) { + try { + Instance spanExporters = context.getInjectedReference(new TypeLiteral<>() { + }); + if (spanExporters.isUnsatisfied()) { + var spanExporter = createOtlpGrpcSpanExporter(exporterRuntimeConfig, vertx.get(), grpcBaseUri); - OtlpExporterTracesConfig tracesConfig = exporterRuntimeConfig.traces(); - if (tracesConfig.protocol().isPresent()) { - if (!tracesConfig.protocol().get().equals(HTTP_PROTOBUF)) { - throw new IllegalStateException("Only the GRPC Exporter is currently supported. " + - "Please check `quarkus.otel.exporter.otlp.traces.protocol` property"); - } - } + BatchSpanProcessorBuilder processorBuilder = BatchSpanProcessor.builder(spanExporter); - boolean compressionEnabled = false; - if (tracesConfig.compression().isPresent()) { - compressionEnabled = (tracesConfig.compression().get() == CompressionType.GZIP); - } + processorBuilder.setScheduleDelay(otelRuntimeConfig.bsp().scheduleDelay()); + processorBuilder.setMaxQueueSize(otelRuntimeConfig.bsp().maxQueueSize()); + processorBuilder.setMaxExportBatchSize(otelRuntimeConfig.bsp().maxExportBatchSize()); + processorBuilder.setExporterTimeout(otelRuntimeConfig.bsp().exportTimeout()); + // processorBuilder.setMeterProvider() // TODO add meter provider to span processor. - Map headersMap = new HashMap<>(); - OtlpUserAgent.addUserAgentHeader(headersMap::put); - if (tracesConfig.headers().isPresent()) { - List headers = tracesConfig.headers().get(); - if (!headers.isEmpty()) { - for (String header : headers) { - if (header.isEmpty()) { - continue; + result.setBatchSpanProcessorDelegate(processorBuilder.build()); + } + } catch (IllegalArgumentException iae) { + throw new IllegalStateException("Unable to install OTLP Exporter", iae); } - String[] parts = header.split("=", 2); - String key = parts[0].trim(); - String value = parts[1].trim(); - headersMap.put(key, value); } + + return result; } - } - URI grpcBaseUri = ExporterBuilderUtil.validateEndpoint(endpoint); - return new VertxGrpcExporter( - "otlp", // use the same as OTel does - "span", // use the same as OTel does - MeterProvider::noop, - grpcBaseUri, - compressionEnabled, - tracesConfig.timeout(), - headersMap, - new Consumer<>() { - @Override - public void accept(HttpClientOptions options) { - configureTLS(options); + private SpanExporter createOtlpGrpcSpanExporter(OtlpExporterRuntimeConfig exporterRuntimeConfig, + Vertx vertx, final URI grpcBaseUri) { + + OtlpExporterTracesConfig tracesConfig = exporterRuntimeConfig.traces(); + if (tracesConfig.protocol().isPresent()) { + if (!tracesConfig.protocol().get().equals(HTTP_PROTOBUF)) { + throw new IllegalStateException("Only the GRPC Exporter is currently supported. " + + "Please check `quarkus.otel.exporter.otlp.traces.protocol` property"); } + } - private void configureTLS(HttpClientOptions options) { - // TODO: this can reuse existing stuff when https://github.com/quarkusio/quarkus/pull/33228 is in - options.setKeyCertOptions(toPemKeyCertOptions(tracesConfig)); - options.setPemTrustOptions(toPemTrustOptions(tracesConfig)); + boolean compressionEnabled = false; + if (tracesConfig.compression().isPresent()) { + compressionEnabled = (tracesConfig.compression().get() == CompressionType.GZIP); + } - if (VertxGrpcExporter.isHttps(grpcBaseUri)) { - options.setSsl(true); - options.setUseAlpn(true); + Map headersMap = new HashMap<>(); + OtlpUserAgent.addUserAgentHeader(headersMap::put); + if (tracesConfig.headers().isPresent()) { + List headers = tracesConfig.headers().get(); + if (!headers.isEmpty()) { + for (String header : headers) { + if (header.isEmpty()) { + continue; + } + String[] parts = header.split("=", 2); + String key = parts[0].trim(); + String value = parts[1].trim(); + headersMap.put(key, value); } } + } - private KeyCertOptions toPemKeyCertOptions(OtlpExporterTracesConfig configuration) { - PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions(); - OtlpExporterTracesConfig.KeyCert keyCert = configuration.keyCert(); - if (keyCert.certs().isPresent()) { - for (String cert : keyCert.certs().get()) { - pemKeyCertOptions.addCertPath(cert); + return new VertxGrpcExporter( + "otlp", // use the same as OTel does + "span", // use the same as OTel does + MeterProvider::noop, + grpcBaseUri, + compressionEnabled, + tracesConfig.timeout(), + headersMap, + new Consumer<>() { + @Override + public void accept(HttpClientOptions options) { + configureTLS(options); } - } - if (keyCert.keys().isPresent()) { - for (String cert : keyCert.keys().get()) { - pemKeyCertOptions.addKeyPath(cert); + + private void configureTLS(HttpClientOptions options) { + // TODO: this can reuse existing stuff when https://github.com/quarkusio/quarkus/pull/33228 is in + options.setKeyCertOptions(toPemKeyCertOptions(tracesConfig)); + options.setPemTrustOptions(toPemTrustOptions(tracesConfig)); + + if (VertxGrpcExporter.isHttps(grpcBaseUri)) { + options.setSsl(true); + options.setUseAlpn(true); + } } - } - return pemKeyCertOptions; - } - private PemTrustOptions toPemTrustOptions(OtlpExporterTracesConfig configuration) { - PemTrustOptions pemTrustOptions = new PemTrustOptions(); - OtlpExporterTracesConfig.TrustCert trustCert = configuration.trustCert(); - if (trustCert.certs().isPresent()) { - for (String cert : trustCert.certs().get()) { - pemTrustOptions.addCertPath(cert); + private KeyCertOptions toPemKeyCertOptions(OtlpExporterTracesConfig configuration) { + PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions(); + OtlpExporterTracesConfig.KeyCert keyCert = configuration.keyCert(); + if (keyCert.certs().isPresent()) { + for (String cert : keyCert.certs().get()) { + pemKeyCertOptions.addCertPath(cert); + } + } + if (keyCert.keys().isPresent()) { + for (String cert : keyCert.keys().get()) { + pemKeyCertOptions.addKeyPath(cert); + } + } + return pemKeyCertOptions; } - } - return pemTrustOptions; - } - }, - vertx); + private PemTrustOptions toPemTrustOptions(OtlpExporterTracesConfig configuration) { + PemTrustOptions pemTrustOptions = new PemTrustOptions(); + OtlpExporterTracesConfig.TrustCert trustCert = configuration.trustCert(); + if (trustCert.certs().isPresent()) { + for (String cert : trustCert.certs().get()) { + pemTrustOptions.addCertPath(cert); + } + } + return pemTrustOptions; + } + }, + vertx); + + } + }; + } + + private URI getGrpcBaseUri(OtlpExporterRuntimeConfig exporterRuntimeConfig) { + String endpoint = resolveEndpoint(exporterRuntimeConfig).trim(); + if (endpoint.isEmpty()) { + return null; + } + return ExporterBuilderUtil.validateEndpoint(endpoint); + } + + static String resolveEndpoint(final OtlpExporterRuntimeConfig runtimeConfig) { + String endpoint = runtimeConfig.traces().legacyEndpoint() + .filter(OtlpRecorder::excludeDefaultEndpoint) + .orElse(runtimeConfig.traces().endpoint() + .filter(OtlpRecorder::excludeDefaultEndpoint) + .orElse(runtimeConfig.endpoint() + .filter(OtlpRecorder::excludeDefaultEndpoint) + .orElse(DEFAULT_GRPC_BASE_URI))); + return endpoint.trim(); } + + private static boolean excludeDefaultEndpoint(String endpoint) { + return !DEFAULT_GRPC_BASE_URI.equals(endpoint); + } + } diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java index 7075f8389532ef..163ab17705b613 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerRecorder.java @@ -2,22 +2,12 @@ import java.util.HashSet; import java.util.List; -import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; - -import jakarta.enterprise.inject.Any; -import jakarta.enterprise.inject.Instance; -import jakarta.enterprise.inject.spi.BeanManager; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.IdGenerator; -import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import io.quarkus.arc.Arc; -import io.quarkus.runtime.RuntimeValue; +import io.quarkus.arc.runtime.BeanContainer; import io.quarkus.runtime.annotations.Recorder; @Recorder @@ -27,24 +17,13 @@ public class TracerRecorder { public static final Set dropStaticResourceTargets = new HashSet<>(); /* STATIC INIT */ - public RuntimeValue> createIdGenerator() { - BeanManager beanManager = Arc.container().beanManager(); - - Instance idGenerator = beanManager.createInstance() - .select(IdGenerator.class, Any.Literal.INSTANCE); - - return new RuntimeValue<>(idGenerator.isResolvable() ? Optional.of(idGenerator.get()) : Optional.empty()); - } - - /* STATIC INIT */ - public RuntimeValue createResource( + public void setAttributes( + BeanContainer beanContainer, String quarkusVersion, String serviceName, String serviceVersion) { - BeanManager beanManager = Arc.container().beanManager(); - DelayedAttributes delayedAttributes = beanManager.createInstance() - .select(DelayedAttributes.class, Any.Literal.INSTANCE).get(); + DelayedAttributes delayedAttributes = beanContainer.beanInstance(DelayedAttributes.class); delayedAttributes.setAttributesDelegate(Resource.getDefault() .merge(Resource.create( @@ -54,30 +33,6 @@ public RuntimeValue createResource( ResourceAttributes.WEBENGINE_NAME, "Quarkus", ResourceAttributes.WEBENGINE_VERSION, quarkusVersion))) .getAttributes()); - - return new RuntimeValue<>(Resource.create(delayedAttributes)); - } - - /* STATIC INIT */ - public RuntimeValue> createSpanExporter() { - BeanManager beanManager = Arc.container().beanManager(); - // Find all SpanExporter instances - Instance allExporters = beanManager.createInstance() - .select(SpanExporter.class, Any.Literal.INSTANCE); - - return new RuntimeValue<>(allExporters.stream().collect(Collectors.toList())); - } - - /* STATIC INIT */ - public RuntimeValue> createSpanProcessors() { - BeanManager beanManager = Arc.container().beanManager(); - - // Find all SpanProcessor instances - Instance allProcessors = beanManager.createInstance() - .select(SpanProcessor.class, Any.Literal.INSTANCE); - - return new RuntimeValue<>(allProcessors.stream().collect(Collectors.toList())); - } /* STATIC INIT */ diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/InstrumentationRecorder.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/InstrumentationRecorder.java index 85856e611726a3..9613b7a13eebca 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/InstrumentationRecorder.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/InstrumentationRecorder.java @@ -1,18 +1,16 @@ package io.quarkus.opentelemetry.runtime.tracing.intrumentation; -import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import io.opentelemetry.api.OpenTelemetry; +import io.quarkus.arc.runtime.BeanContainer; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.EventBusInstrumenterVertxTracer; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.HttpInstrumenterVertxTracer; -import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.InstrumenterVertxTracer; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.OpenTelemetryVertxMetricsFactory; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.OpenTelemetryVertxTracer; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.OpenTelemetryVertxTracingFactory; import io.quarkus.opentelemetry.runtime.tracing.intrumentation.vertx.SqlClientInstrumenterVertxTracer; -import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; import io.vertx.core.VertxOptions; import io.vertx.core.metrics.MetricsOptions; @@ -23,16 +21,6 @@ public class InstrumentationRecorder { public static final OpenTelemetryVertxTracingFactory FACTORY = new OpenTelemetryVertxTracingFactory(); - /* RUNTIME INIT */ - public RuntimeValue createTracers(RuntimeValue openTelemetry) { - List> instrumenterVertxTracers = new ArrayList<>(); - instrumenterVertxTracers.add(new HttpInstrumenterVertxTracer(openTelemetry.getValue())); - instrumenterVertxTracers.add(new EventBusInstrumenterVertxTracer(openTelemetry.getValue())); - // TODO - Selectively register this in the recorder if the SQL Client is available. - instrumenterVertxTracers.add(new SqlClientInstrumenterVertxTracer(openTelemetry.getValue())); - return new RuntimeValue<>(new OpenTelemetryVertxTracer(instrumenterVertxTracers)); - } - /* RUNTIME INIT */ public Consumer getVertxTracingOptions() { TracingOptions tracingOptions = new TracingOptions() @@ -41,8 +29,14 @@ public Consumer getVertxTracingOptions() { } /* RUNTIME INIT */ - public void setTracer(RuntimeValue tracer) { - FACTORY.getVertxTracerDelegator().setDelegate(tracer.getValue()); + public void setupVertxTracer(BeanContainer beanContainer) { + OpenTelemetry openTelemetry = beanContainer.beanInstance(OpenTelemetry.class); + OpenTelemetryVertxTracer openTelemetryVertxTracer = new OpenTelemetryVertxTracer(List.of( + new HttpInstrumenterVertxTracer(openTelemetry), + new EventBusInstrumenterVertxTracer(openTelemetry), + // TODO - Selectively register this in the recorder if the SQL Client is available. + new SqlClientInstrumenterVertxTracer(openTelemetry))); + FACTORY.getVertxTracerDelegator().setDelegate(openTelemetryVertxTracer); } /* RUNTIME INIT */ @@ -52,4 +46,5 @@ public Consumer getVertxTracingMetricsOptions() { .setFactory(new OpenTelemetryVertxMetricsFactory()); return vertxOptions -> vertxOptions.setMetricsOptions(metricsOptions); } + } diff --git a/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorderTest.java b/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java similarity index 99% rename from extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorderTest.java rename to extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java index 643667e8a3a1bd..50b17e200707e5 100644 --- a/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpRecorderTest.java +++ b/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java @@ -13,7 +13,7 @@ import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterRuntimeConfig; import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterTracesConfig; -class OtlpRecorderTest { +class OtlpExporterProviderTest { @Test public void resolveEndpoint_legacyWins() {