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

Use Synthetic bean for producing OpenTelemetry #34990

Merged
merged 1 commit into from
Jul 25, 2023
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 @@ -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