Druid 本身不直接支持分布式链路追踪,但可通过集成 SkyWalking、OpenTelemetry 等框架,在 JDBC 执行前经自定义 Filter 将 TraceId 注入 MDC 或 SQL 日志,并配合日志配置实现透传与记录。

Druid 本身不直接支持分布式链路追踪(如 TraceId 注入),但它作为数据库连接池,可以通过与主流链路追踪框架(如 SkyWalking、Pinpoint、OpenTelemetry 或 Sleuth+Zipkin)集成,在 SQL 执行阶段透传和记录 TraceId。关键在于:在 JDBC 执行前将当前线程的 TraceId 注入到 Druid 的 Filter 或 Statement 中,并让日志/监控组件能识别它。
1. 确保链路追踪上下文已就绪
TraceId 必须已在当前线程中存在(例如由 Web 层通过 ServletFilter 或 Spring MVC 拦截器注入)。常见方式:
- 使用 Spring Cloud Sleuth:自动注入
traceId到 MDC,且提供Tracer.currentSpan()获取上下文 - 使用 OpenTelemetry Java SDK:通过
OpenTelemetry.getGlobalTracer().currentSpan()获取活跃 Span,再提取 traceId - 使用 SkyWalking Agent:无需手动注入,Agent 自动增强 Servlet 和 JDBC,但需确保 Druid 被正确插桩(默认支持)
2. 通过 Druid Filter 注入 TraceId 到 SQL 日志或扩展属性
Druid 提供 Filter 接口,可在 SQL 执行前后插入逻辑。推荐自定义 StatementFilter,将 TraceId 添加到 SQL 日志或 JDBC 扩展字段中:
public class TraceIdFilter extends FilterEventAdapter {
@Override
public void dataSource_connectBefore(FilterChain chain, Properties info) {
// 可选:在连接获取时记录 traceId(如用于连接池监控)
String traceId = getCurrentTraceId();
if (traceId != null) {
info.put("traceId", traceId);
}
}
<pre class="brush:php;toolbar:false;">@Override
public void statement_executeBefore(FilterChain chain, PreparedStatement preparedStatement, String sql) {
String traceId = getCurrentTraceId();
if (traceId != null) {
// 方式一:写入 MDC,让 logback/log4j 日志自动携带(推荐)
MDC.put("traceId", traceId);
// 方式二:修改 SQL 注释(仅限调试,生产慎用)
// String tracedSql = "/* traceId=" + traceId + " */ " + sql;
// chain.statement_execute(preparedStatement, tracedSql);
}
}
private String getCurrentTraceId() {
// Sleuth 示例
CurrentTraceContext currentTraceContext = Tracing.current().currentTraceContext();
Span currentSpan = currentTraceContext.get();
return currentSpan != null ? currentSpan.context().traceId() : null;
// OpenTelemetry 示例:
// return Span.current().getSpanContext().getTraceId();
}}
然后在 Spring Boot 中注册该 Filter:
@Bean
public Filter traceIdFilter() {
return new TraceIdFilter();
}
<p>@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
// ... 其他配置
dataSource.setProxyFilters(Arrays.asList(traceIdFilter()));
return dataSource;
}</p>
3. 配合日志框架输出 TraceId(关键落地环节)
仅注入还不够,必须让数据库操作日志带上 TraceId。以 Logback 为例,在 logback-spring.xml 中配置 pattern:
<pattern>%d{HH:mm:ss.SSS} [%thread] [%X{traceId:-}] %-5level %logger{36} - %msg%n</pattern>
这样 Druid 的慢 SQL 日志、执行日志(开启 druid.stat.logSlowSql=true)就会自动包含 TraceId。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
注意:%X{traceId:-} 表示从 MDC 取值,缺失时显示空字符串;务必在 Filter 中调用 MDC.put("traceId", ...),并在执行后清理(可重写 statement_executeAfter 清理 MDC,避免线程复用污染)。
4. 使用 SkyWalking Agent(零代码侵入方案)
如果你用 SkyWalking,最简单的方式是:不改代码,只加 JVM 参数启动 Agent:
-javaagent:/path/to/skywalking-agent.jar -Dskywalking.agent.service_name=your-service -Dskywalking.collector.backend_service=your-oap:11800
SkyWalking Agent 已内置对 Druid 1.1.10+ 的支持,会自动:
- 捕获 SQL 执行耗时、参数、异常
- 关联上游 HTTP 请求的 TraceId
- 在 SkyWalking UI 中展示「DB 拓扑」和「Trace 详情」中的 Druid 节点
无需额外 Filter,但需确认 Druid 版本兼容性(建议 ≥ 1.2.16),并启用 druid.stat.mergeSql=true 提升聚合效果。
本质上,Druid 是“被动承载者”,TraceId 注入靠的是上下文传播 + Filter 增强 + 日志/Monitor 集成。选型优先级建议:已有 SkyWalking → 直接用 Agent;已用 Sleuth → 复用 MDC + 自定义 Filter;新项目推荐 OpenTelemetry + 自动 Instrumentation。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










