如何在Quarkus中用DataSource方式实现JDBC的OpenTelemetry埋点?
在Quarkus中通过DataSource方式实现OpenTelemetry JDBC埋点
步骤1:添加必要依赖
在项目的构建文件中引入OpenTelemetry JDBC instrumentation依赖:
- Maven(
pom.xml):
<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-jdbc</artifactId> <version>最新稳定版</version> </dependency>
- Gradle(
build.gradle):
implementation 'io.opentelemetry.instrumentation:opentelemetry-jdbc:最新稳定版'
步骤2:修改LiquibaseRunner代码
你当前的代码直接通过URL打开数据库连接,需要调整为先创建原生DataSource,再用OpenTelemetry包装,最后从包装后的数据源获取连接。修改后的完整代码如下:
package .....infrastructure.data; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.sql.DataSource; import io.quarkus.runtime.LaunchMode; import org.eclipse.microprofile.config.inject.ConfigProperty; import io.quarkus.runtime.StartupEvent; import io.quarkus.runtime.util.ExceptionUtil; import liquibase.Contexts; import liquibase.LabelExpression; import liquibase.Liquibase; import liquibase.database.DatabaseConnection; import liquibase.database.DatabaseFactory; import liquibase.exception.LiquibaseException; import liquibase.resource.ClassLoaderResourceAccessor; import liquibase.resource.ResourceAccessor; import io.quarkus.logging.Log; import io.opentelemetry.instrumentation.jdbc.datasource.OpenTelemetryDataSource; import com.zaxxer.hikari.HikariDataSource; @ApplicationScoped public class LiquibaseRunner { @ConfigProperty(name = "quarkus.datasource.jdbc.url") String datasourceUrl; @ConfigProperty(name = "quarkus.datasource.username") String datasourceUsername; @ConfigProperty(name = "quarkus.datasource.password") String datasourcePassword; @ConfigProperty(name = "quarkus.datasource.jdbc.driver") String datasourceDriver; @ConfigProperty(name = "quarkus.liquibase.change-log") String changeLogLocation; public void onApplicationStart(@Observes StartupEvent even) { LaunchMode mode = io.quarkus.runtime.LaunchMode.current(); if(mode != LaunchMode.TEST) { this.runMigration(); } else { Log.info("测试模式下跳过数据库迁移"); } } public void runMigration() { Log.info("开始迁移数据库:" + datasourceUrl); Liquibase liquibase = null; DataSource originalDataSource = null; DataSource otelDataSource = null; try { // 创建原生Hikari数据源(Quarkus默认连接池) originalDataSource = createOriginalDataSource(); // 用OpenTelemetry包装数据源,实现JDBC埋点 otelDataSource = new OpenTelemetryDataSource(originalDataSource); ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(Thread.currentThread().getContextClassLoader()); // 从包装后的数据源获取连接 DatabaseConnection conn = DatabaseFactory.getInstance().openConnection( otelDataSource.getConnection(), resourceAccessor ); liquibase = new Liquibase(changeLogLocation, resourceAccessor, conn); liquibase.update(new Contexts(), new LabelExpression()); Log.info("数据库迁移完成"); } catch (Exception e) { Log.error("Liquibase迁移异常:" + ExceptionUtil.generateStackTrace(e)); throw new RuntimeException("数据库迁移失败", e); } finally { // 依次关闭资源 if(liquibase != null) { try { liquibase.close(); } catch (LiquibaseException e) { Log.info("关闭Liquibase时出错:" + e.getMessage()); } } if(originalDataSource instanceof AutoCloseable) { try { ((AutoCloseable) originalDataSource).close(); } catch (Exception e) { Log.info("关闭数据源时出错:" + e.getMessage()); } } } } private DataSource createOriginalDataSource() { HikariDataSource hikariDataSource = new HikariDataSource(); hikariDataSource.setJdbcUrl(datasourceUrl); hikariDataSource.setUsername(datasourceUsername); hikariDataSource.setPassword(datasourcePassword); hikariDataSource.setDriverClassName(datasourceDriver); // 可根据需求添加连接池配置,如最大连接数、超时时间等 return hikariDataSource; } }
步骤3:配置与验证
- 驱动配置:确保
application.properties中存在quarkus.datasource.jdbc.driver配置,例如MySQL填com.mysql.cj.jdbc.Driver,PostgreSQL填org.postgresql.Driver。 - 自定义OpenTelemetry实例:如果项目需要自定义埋点规则(如自定义Tracer、导出器),可以手动创建OpenTelemetry实例并传入包装类:
OpenTelemetry customOtel = OpenTelemetrySdk.builder() .setTracerProvider(...) .buildAndRegisterGlobal(); otelDataSource = new OpenTelemetryDataSource(customOtel, originalDataSource);
- 验证埋点:启动应用执行数据库迁移,检查OpenTelemetry导出目标(如Jaeger、Zipkin)是否生成
jdbc.query类型的Span,包含SQL语句、连接信息等埋点数据。
内容的提问来源于stack exchange,提问作者Kavishka Madhushan
相关产品推荐
相关产品推荐

