Skip to content

Commit

Permalink
Merge pull request #34990 from geoand/OpenTelemetry-synthetic
Browse files Browse the repository at this point in the history
Use Synthetic bean for producing OpenTelemetry
  • Loading branch information
geoand authored Jul 25, 2023
2 parents 48bd9c7 + 09cd879 commit d2ed11f
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@
import java.util.Optional;
import java.util.Set;

import jakarta.enterprise.inject.Instance;
import jakarta.inject.Singleton;

import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.ConfigValue;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassType;
import org.jboss.jandex.DotName;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.exporter.otlp.internal.OtlpSpanExporterProvider;
import io.opentelemetry.instrumentation.annotations.SpanAttribute;
Expand All @@ -31,6 +38,7 @@
import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.arc.deployment.InterceptorBindingRegistrarBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.ValidationPhaseBuildItem.ValidationErrorBuildItem;
import io.quarkus.arc.processor.AnnotationsTransformer;
import io.quarkus.arc.processor.InterceptorBindingRegistrar;
Expand All @@ -49,10 +57,11 @@
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.util.ServiceUtil;
import io.quarkus.maven.dependency.ArtifactKey;
import io.quarkus.opentelemetry.OpenTelemetryDestroyer;
import io.quarkus.opentelemetry.runtime.AutoConfiguredOpenTelemetrySdkBuilderCustomizer;
import io.quarkus.opentelemetry.runtime.OpenTelemetryProducer;
import io.quarkus.opentelemetry.runtime.OpenTelemetryRecorder;
import io.quarkus.opentelemetry.runtime.QuarkusContextStorage;
import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig;
import io.quarkus.opentelemetry.runtime.tracing.cdi.WithSpanInterceptor;
import io.quarkus.opentelemetry.runtime.tracing.intrumentation.InstrumentationRecorder;
import io.quarkus.runtime.LaunchMode;
Expand All @@ -73,14 +82,34 @@ public class OpenTelemetryProcessor {
AdditionalBeanBuildItem ensureProducerIsRetained() {
return AdditionalBeanBuildItem.builder()
.setUnremovable()
.addBeanClasses(OpenTelemetryProducer.class,
.addBeanClasses(
AutoConfiguredOpenTelemetrySdkBuilderCustomizer.ResourceCustomizer.class,
AutoConfiguredOpenTelemetrySdkBuilderCustomizer.SamplerCustomizer.class,
AutoConfiguredOpenTelemetrySdkBuilderCustomizer.TracerProviderCustomizer.class,
AutoConfiguredOpenTelemetrySdkBuilderCustomizer.TextMapPropagatorCustomizers.class)
.build();
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
SyntheticBeanBuildItem openTelemetryBean(OpenTelemetryRecorder recorder, OTelRuntimeConfig oTelRuntimeConfig) {
return SyntheticBeanBuildItem.configure(OpenTelemetry.class)
.defaultBean()
.setRuntimeInit()
.unremovable()
.scope(Singleton.class)
.addInjectionPoint(
ParameterizedType.create(
DotName.createSimple(Instance.class),
new Type[] { ClassType.create(
DotName.createSimple(
AutoConfiguredOpenTelemetrySdkBuilderCustomizer.class.getName())) },
null))
.createWith(recorder.opentelemetryBean(oTelRuntimeConfig))
.destroyer(OpenTelemetryDestroyer.class)
.done();
}

@BuildStep
void registerNativeImageResources(BuildProducer<ServiceProviderBuildItem> services,
BuildProducer<RemovedResourceBuildItem> removedResources,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.quarkus.opentelemetry;

import java.util.Map;

import jakarta.enterprise.context.spi.CreationalContext;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.quarkus.arc.BeanDestroyer;

public class OpenTelemetryDestroyer implements BeanDestroyer<OpenTelemetry> {
@Override
public void destroy(OpenTelemetry openTelemetry, CreationalContext<OpenTelemetry> creationalContext,
Map<String, Object> params) {
if (openTelemetry instanceof OpenTelemetrySdk) {
var openTelemetrySdk = ((OpenTelemetrySdk) openTelemetry);
openTelemetrySdk.getSdkTracerProvider().forceFlush();
openTelemetrySdk.getSdkTracerProvider().shutdown();
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
package io.quarkus.opentelemetry.runtime;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.util.TypeLiteral;

import org.eclipse.microprofile.config.ConfigProvider;

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.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.quarkus.arc.SyntheticCreationalContext;
import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig;
import io.quarkus.runtime.annotations.Recorder;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.NameIterator;
import io.smallrye.config.SmallRyeConfig;
import io.vertx.core.Vertx;

@Recorder
Expand All @@ -31,4 +46,60 @@ public void storeVertxOnContextStorage(Supplier<Vertx> vertx) {
QuarkusContextStorage.vertx = vertx.get();
}

/* RUNTIME INIT */
public Function<SyntheticCreationalContext<OpenTelemetry>, OpenTelemetry> opentelemetryBean(
OTelRuntimeConfig oTelRuntimeConfig) {
return new Function<>() {
@Override
public OpenTelemetry apply(SyntheticCreationalContext<OpenTelemetry> context) {
Instance<AutoConfiguredOpenTelemetrySdkBuilderCustomizer> builderCustomizers = context
.getInjectedReference(new TypeLiteral<>() {
});

final Map<String, String> oTelConfigs = getOtelConfigs();

if (oTelRuntimeConfig.sdkDisabled()) {
return AutoConfiguredOpenTelemetrySdk.builder()
.setResultAsGlobal(true)
.registerShutdownHook(false)
.addPropertiesSupplier(() -> oTelConfigs)
.build()
.getOpenTelemetrySdk();
}

var builder = AutoConfiguredOpenTelemetrySdk.builder()
.setResultAsGlobal(true)
.registerShutdownHook(false)
.addPropertiesSupplier(() -> oTelConfigs)
.setServiceClassLoader(Thread.currentThread().getContextClassLoader());
for (var customizer : builderCustomizers) {
customizer.customize(builder);
}

return builder.build().getOpenTelemetrySdk();
}

private Map<String, String> getOtelConfigs() {
Map<String, String> oTelConfigs = new HashMap<>();
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);

// instruct OTel that we are using the AutoConfiguredOpenTelemetrySdk
oTelConfigs.put("otel.java.global-autoconfigure.enabled", "true");

// load new properties
for (String propertyName : config.getPropertyNames()) {
if (propertyName.startsWith("quarkus.otel.")) {
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue.getValue() != null) {
NameIterator name = new NameIterator(propertyName);
name.next();
oTelConfigs.put(name.getName().substring(name.getPosition() + 1), configValue.getValue());
}
}
}
return oTelConfigs;
}
};
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package io.quarkus.opentelemetry.runtime.exporter.otlp;

import io.quarkus.opentelemetry.runtime.OpenTelemetryProducer;
import io.quarkus.opentelemetry.runtime.AutoConfiguredOpenTelemetrySdkBuilderCustomizer.TracerProviderCustomizer;

/**
* The only point in having this class is to allow {@link OpenTelemetryProducer}
* The only point in having this class is to allow {@link TracerProviderCustomizer}
* to easily ignore the configured {@link LateBoundBatchSpanProcessor}.
* <p>
* In the future when {@link OpenTelemetryProducer} is replaced by a synthetic bean, this class will no longer be necessary
*/
public final class RemoveableLateBoundBatchSpanProcessor extends LateBoundBatchSpanProcessor {

Expand Down

0 comments on commit d2ed11f

Please sign in to comment.