GuanceCloud / dd-trace-java

Datadog APM client for Java
https://docs.datadoghq.com/tracing/languages/java
Apache License 2.0
9 stars 3 forks source link

数据库SQL 解除脱敏配置需要支持 PostgreSQL 和 oracle #7

Closed lrwh closed 1 year ago

lrwh commented 1 year ago

目前数据库SQL 脱敏开关配置只支持MySQL,需要对 PostgreSQL 和 Oracle 都支持这种开关配置。

songlonqi-java commented 1 year ago

oracle 脱敏问题其实并不是oracle的问题 在mysql中也会出现。这是代码的写法问题。 比如 :

    ps = conn.prepareStatement("SELECT name,password,id FROM student where name=? and password=?");
    ps.setString(1,username);   -- set   替换第一个?
    ps.setString(2,pw);        ----  替换第二个?

这是jdbc的写法,与库无关(oracle和mysql都是这么写的)。

这种写法 ddtrace拿到的就是 两个 ? 的 resource。

另一种写法

    ps = conn.prepareStatement("SELECT name,password,id FROM student where name='guance' and password='123456'");
   // ps.setString(1,username);  不再使用 set
   // ps.setString(2,pw);

这时候 ddtrace 拿到的就是 不带问号的sql语句。

究其原因,是因为 ddtrace的探针 是在函数 prepareStatement 上。

总结:代码写法不同,拿到的 sql 语句就会不同。与数据库无关

lrwh commented 1 year ago

是否可以针对set这种方式也做下集成,探究下可行性方案

songlonqi-java commented 1 year ago

说明

通过启动参数开启该功能:

 -Ddd.jdbc.sql.obfuscation=true

目前探针的位置在 java.sql.PreparedStatement set(two args), 这里有两个参数,启动第一个是整型,第二个为 Object 类型,在调用 set 方法之后,会将 Object 类型 toString() 之后放到 map中。

在sql最终被执行的方法中,将 map 放置 span 中。

最终的 span 数据格式:

"meta": {
"component":
"java-jdbc-prepared_statement",

"db.instance":"tmalldemodb",
"db.operation":"INSERT",
"db.sql.origin":"INSERT product (product_id,product_name,product_title,product_price,product_sale_price,product_create_date,product_isEnabled,product_category_id) VALUES( null, ?, ?, ?, ?, ?, ?, ?)",
"db.type":"mysql",
"db.user":"root",
"env":"test",
"peer.hostname":"49.232.153.84",
"span.kind":"client",
"sql.params.index_1":"图书",
"sql.params.index_2":"十万个为什么",
"sql.params.index_3":"100.0",
"sql.params.index_4":"99.0",
"sql.params.index_5":"2022-11-10 14:08:21",
"sql.params.index_6":"0",
"sql.params.index_7":"16",
"thread.name":
"http-nio-8080-exec-6"

}

q1: 为什么没有放在原始 sql 中,而是使用 sql.params.index_x :

在调用 set* 时插入的值并不是有序的, 参数 index 是从1开始的而不是0。所以需要先存入map, 再插入span时 进行排序、替换等操作。并且无法保证所有的问号完美对应值。 所以单独的使用 k:v 形式,