Skip to content

Commit

Permalink
No jdbc spans if otel off ar build time or sdk is disabled at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
brunobat committed Jan 22, 2025
1 parent 0f1decf commit a978058
Show file tree
Hide file tree
Showing 19 changed files with 213 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.agroal.deployment;

import static io.quarkus.agroal.deployment.AgroalDataSourceBuildUtil.qualifiers;
import static io.quarkus.arc.deployment.OpenTelemetrySdkBuildItem.isOtelSdkEnabled;
import static io.quarkus.deployment.Capability.OPENTELEMETRY_TRACER;

import java.sql.Driver;
Expand All @@ -26,6 +27,7 @@
import io.agroal.api.AgroalPoolInterceptor;
import io.quarkus.agroal.DataSource;
import io.quarkus.agroal.runtime.AgroalDataSourceSupport;
import io.quarkus.agroal.runtime.AgroalOpenTelemetryWrapper;
import io.quarkus.agroal.runtime.AgroalRecorder;
import io.quarkus.agroal.runtime.DataSourceJdbcBuildTimeConfig;
import io.quarkus.agroal.runtime.DataSources;
Expand All @@ -34,9 +36,9 @@
import io.quarkus.agroal.runtime.TransactionIntegration;
import io.quarkus.agroal.spi.JdbcDataSourceBuildItem;
import io.quarkus.agroal.spi.JdbcDriverBuildItem;
import io.quarkus.agroal.spi.OpenTelemetryInitBuildItem;
import io.quarkus.arc.BeanDestroyer;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.OpenTelemetrySdkBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
import io.quarkus.arc.processor.DotNames;
Expand Down Expand Up @@ -127,7 +129,7 @@ void build(
// at least one datasource is using OpenTelemetry JDBC instrumentation,
// therefore we register the OpenTelemetry data source wrapper bean
additionalBeans.produce(new AdditionalBeanBuildItem.Builder()
.addBeanClass("io.quarkus.agroal.runtime.AgroalOpenTelemetryWrapper")
.addBeanClass(AgroalOpenTelemetryWrapper.class)
.setDefaultScope(DotNames.SINGLETON).build());
}

Expand Down Expand Up @@ -244,13 +246,13 @@ void generateDataSourceSupportBean(AgroalRecorder recorder,

@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep
@Consume(OpenTelemetryInitBuildItem.class)
@Consume(NarayanaInitBuildItem.class)
void generateDataSourceBeans(AgroalRecorder recorder,
DataSourcesRuntimeConfig dataSourcesRuntimeConfig,
List<AggregatedDataSourceBuildTimeConfigBuildItem> aggregatedBuildTimeConfigBuildItems,
SslNativeConfigBuildItem sslNativeConfig,
Capabilities capabilities,
Optional<OpenTelemetrySdkBuildItem> openTelemetrySdkBuildItem,
BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItemBuildProducer,
BuildProducer<JdbcDataSourceBuildItem> jdbcDataSource) {
if (aggregatedBuildTimeConfigBuildItems.isEmpty()) {
Expand All @@ -275,7 +277,8 @@ void generateDataSourceBeans(AgroalRecorder recorder,
.checkActive(recorder.agroalDataSourceCheckActiveSupplier(dataSourceName))
// pass the runtime config into the recorder to ensure that the DataSource related beans
// are created after runtime configuration has been set up
.createWith(recorder.agroalDataSourceSupplier(dataSourceName, dataSourcesRuntimeConfig))
.createWith(recorder.agroalDataSourceSupplier(
dataSourceName, dataSourcesRuntimeConfig, isOtelSdkEnabled(openTelemetrySdkBuildItem)))
.destroyer(BeanDestroyer.AutoCloseableDestroyer.class);

if (!DataSourceUtil.isDefault(dataSourceName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ public ActiveResult get() {

public Function<SyntheticCreationalContext<AgroalDataSource>, AgroalDataSource> agroalDataSourceSupplier(
String dataSourceName,
@SuppressWarnings("unused") DataSourcesRuntimeConfig dataSourcesRuntimeConfig) {
@SuppressWarnings("unused") DataSourcesRuntimeConfig dataSourcesRuntimeConfig,
Optional<RuntimeValue<Boolean>> otelEnabled) {
return new Function<>() {
@SuppressWarnings("deprecation")
@Override
public AgroalDataSource apply(SyntheticCreationalContext<AgroalDataSource> context) {
DataSources dataSources = context.getInjectedReference(DataSources.class);
return dataSources.createDataSource(dataSourceName);
return dataSources.createDataSource(dataSourceName,
otelEnabled.isPresent() ? otelEnabled.get().getValue() : false);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public AgroalDataSource getDataSource(String dataSourceName) {
}

@SuppressWarnings("resource")
public AgroalDataSource createDataSource(String dataSourceName) {
public AgroalDataSource createDataSource(String dataSourceName, boolean otelEnabled) {
if (!agroalDataSourceSupport.entries.containsKey(dataSourceName)) {
throw new IllegalArgumentException("No datasource named '" + dataSourceName + "' exists");
}
Expand Down Expand Up @@ -221,7 +221,9 @@ public AgroalDataSource createDataSource(String dataSourceName) {
dataSource.setPoolInterceptors(interceptorList);
}

if (dataSourceJdbcBuildTimeConfig.telemetry() && dataSourceJdbcRuntimeConfig.telemetry().orElse(true)) {
if (dataSourceJdbcBuildTimeConfig.telemetry() &&
dataSourceJdbcRuntimeConfig.telemetry().orElse(true) &&
otelEnabled) {
// activate OpenTelemetry JDBC instrumentation by wrapping AgroalDatasource
// use an optional CDI bean as we can't reference optional OpenTelemetry classes here
dataSource = agroalOpenTelemetryWrapper.get().apply(dataSource);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.arc.deployment;

import java.util.Optional;

import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.runtime.RuntimeValue;

public final class OpenTelemetrySdkBuildItem extends SimpleBuildItem {

private final RuntimeValue<Boolean> runtimeEnabled;

public OpenTelemetrySdkBuildItem(RuntimeValue<Boolean> sdkEnabled) {
this.runtimeEnabled = sdkEnabled;
}

/**
* True if the OpenTelemetry SDK is enabled at build and runtime.
*/
public RuntimeValue<Boolean> isRuntimeEnabled() {
return runtimeEnabled;
}

public static Optional<RuntimeValue<Boolean>> isOtelSdkEnabled(Optional<OpenTelemetrySdkBuildItem> buildItem) {
// optional is empty if the extension is disabled at build time
return buildItem.isPresent() ? Optional.of(buildItem.get().isRuntimeEnabled()) : Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.quarkus.agroal.spi.JdbcDataSourceBuildItem;
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.OpenTelemetrySdkBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.ValidationPhaseBuildItem.ValidationErrorBuildItem;
import io.quarkus.arc.processor.InterceptorBindingRegistrar;
Expand All @@ -52,7 +52,6 @@
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.BuildSteps;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Produce;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.RemovedResourceBuildItem;
Expand Down Expand Up @@ -107,8 +106,11 @@ AdditionalBeanBuildItem ensureProducerIsRetained() {

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
SyntheticBeanBuildItem openTelemetryBean(OpenTelemetryRecorder recorder, OTelRuntimeConfig oTelRuntimeConfig) {
return SyntheticBeanBuildItem.configure(OpenTelemetry.class)
void openTelemetryBean(OpenTelemetryRecorder recorder,
OTelRuntimeConfig oTelRuntimeConfig,
BuildProducer<SyntheticBeanBuildItem> syntheticProducer,
BuildProducer<OpenTelemetrySdkBuildItem> openTelemetrySdkBuildItemBuildProducer) {
syntheticProducer.produce(SyntheticBeanBuildItem.configure(OpenTelemetry.class)
.defaultBean()
.setRuntimeInit()
.unremovable()
Expand All @@ -122,7 +124,10 @@ SyntheticBeanBuildItem openTelemetryBean(OpenTelemetryRecorder recorder, OTelRun
null))
.createWith(recorder.opentelemetryBean(oTelRuntimeConfig))
.destroyer(OpenTelemetryDestroyer.class)
.done();
.done());

openTelemetrySdkBuildItemBuildProducer.produce(
new OpenTelemetrySdkBuildItem(recorder.isOtelSdkEnabled(oTelRuntimeConfig)));
}

@BuildStep
Expand Down Expand Up @@ -258,7 +263,6 @@ void transformWithSpan(BuildProducer<AnnotationsTransformerBuildItem> annotation

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
@Produce(OpenTelemetryInitBuildItem.class)
void createOpenTelemetry(
OpenTelemetryRecorder recorder,
CoreVertxBuildItem vertx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.quarkus.agroal.spi.OpenTelemetryInitBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.arc.deployment.OpenTelemetrySdkBuildItem;
import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
Expand Down Expand Up @@ -45,7 +45,7 @@ void nativeSupport(BuildProducer<ServiceProviderBuildItem> servicesProducer) {

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
@Consume(OpenTelemetryInitBuildItem.class)
@Consume(OpenTelemetrySdkBuildItem.class)
LogHandlerBuildItem build(OpenTelemetryLogRecorder recorder,
OTelRuntimeConfig config,
BeanContainerBuildItem beanContainerBuildItem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.quarkus.arc.SyntheticCreationalContext;
import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.annotations.RuntimeInit;
import io.quarkus.runtime.annotations.StaticInit;
Expand All @@ -38,6 +39,11 @@ public void resetGlobalOpenTelemetryForDevMode() {
GlobalEventLoggerProvider.resetForTest();
}

@RuntimeInit
public RuntimeValue<Boolean> isOtelSdkEnabled(OTelRuntimeConfig oTelRuntimeConfig) {
return new RuntimeValue<>(!oTelRuntimeConfig.sdkDisabled());
}

@RuntimeInit
public void eagerlyCreateContextStorage() {
ContextStorage.get();
Expand Down
17 changes: 17 additions & 0 deletions integration-tests/opentelemetry-jdbc-instrumentation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2</artifactId>
</dependency>

<!-- Test Dependencies -->
<dependency>
Expand Down Expand Up @@ -215,6 +219,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

</dependencies>

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

import io.quarkus.it.opentelemetry.model.Hit;
import io.quarkus.it.opentelemetry.model.db2.Db2Hit;
import io.quarkus.it.opentelemetry.model.h2.H2Hit;
import io.quarkus.it.opentelemetry.model.mariadb.MariaDbHit;
import io.quarkus.it.opentelemetry.model.oracle.OracleHit;
import io.quarkus.it.opentelemetry.model.pg.PgHit;
Expand All @@ -39,6 +40,9 @@ public Hit createHit(@QueryParam("id") Long id, @PathParam("tenant") String tena
case "db2":
persist(Db2Hit::new, id);
return Db2Hit.findById(id);
case "h2":
persist(H2Hit::new, id);
return H2Hit.findById(id);
default:
throw new IllegalArgumentException();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.it.opentelemetry.model.h2;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.it.opentelemetry.model.Hit;

@Entity
public class H2Hit extends PanacheEntityBase implements Hit {

@Id
public Long id;

public String message;

@Override
public Long getId() {
return id;
}

@Override
public String getMessage() {
return message;
}

@Override
public void setId(Long id) {
this.id = id;
}

@Override
public void setMessage(String message) {
this.message = message;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ quarkus.datasource.db2.db-kind=db2
quarkus.datasource.db2.jdbc.max-size=1
quarkus.datasource.db2.jdbc.telemetry=true

# H2 data source
quarkus.hibernate-orm.h2.datasource=h2
quarkus.hibernate-orm.h2.packages=${model-base-dir}h2
quarkus.hibernate-orm.h2.database.generation=none
quarkus.datasource.h2.db-kind=h2
quarkus.datasource.h2.jdbc.max-size=1
quarkus.datasource.h2.jdbc.telemetry=true

# speed up build
quarkus.otel.bsp.schedule.delay=100
quarkus.otel.bsp.export.timeout=5s
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public Map<String, String> start() {
properties.put("quarkus.hibernate-orm.oracle.active", "false");
properties.put("quarkus.hibernate-orm.postgresql.active", "false");
properties.put("quarkus.hibernate-orm.mariadb.active", "false");
properties.put("quarkus.hibernate-orm.h2.active", "false");

return properties;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.quarkus.it.opentelemetry;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.h2.tools.Server;

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

public class H2DatabaseTestResource implements QuarkusTestResourceLifecycleManager {

public static final String QUARKUS_OTEL_SDK_DISABLED = "quarkus.otel.sdk.disabled";
private Server tcpServer;
private Map<String, String> initProperties;

@Override
public void init(Map<String, String> initArgs) {
initProperties = initArgs;
}

@Override
public Map<String, String> start() {

try {
tcpServer = Server.createTcpServer("-ifNotExists");
tcpServer.start();
System.out.println("[INFO] H2 database started in TCP server mode; server status: " + tcpServer.getStatus());
} catch (SQLException e) {
throw new RuntimeException(e);
}

Map<String, String> properties = new HashMap<>(initProperties);
properties.put("quarkus.datasource.h2.jdbc.url", "jdbc:h2:tcp://localhost/mem:test");
properties.put("quarkus.hibernate-orm.h2.database.generation", "drop-and-create");
properties.put("quarkus.hibernate-orm.postgresql.active", "false");
properties.put("quarkus.hibernate-orm.oracle.active", "false");
properties.put("quarkus.hibernate-orm.mariadb.active", "false");
properties.put("quarkus.hibernate-orm.db2.active", "false");

return properties;
}

@Override
public synchronized void stop() {
if (tcpServer != null) {
tcpServer.stop();
System.out.println("[INFO] H2 database was shut down; server status: " + tcpServer.getStatus());
tcpServer = null;
}
}
}
Loading

0 comments on commit a978058

Please sign in to comment.