systemtap receive strings from address
背景
在PostgreSQL的一些探针中, 有一些是是有target variable的, 即探针触发时可以输出这些变量的值. 例如本文用到的query__done探针, 包含sql string的内存地址信息.
首先要获得target variable变量名, 有两种方法获得, 1是直接看postgresql probe的定义, 如下 :
变量名为arg1.
src/backend/utils/probes.h
/* TRACE_POSTGRESQL_QUERY_DONE ( const char *) */
#if defined STAP_SDT_V1
#define TRACE_POSTGRESQL_QUERY_DONE_ENABLED() __builtin_expect (query__done_semaphore, 0)
#define postgresql_query__done_semaphore query__done_semaphore
#else
#define TRACE_POSTGRESQL_QUERY_DONE_ENABLED() __builtin_expect (postgresql_query__done_semaphore, 0)
#endif
__extension__ extern unsigned short postgresql_query__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
#define TRACE_POSTGRESQL_QUERY_DONE(arg1) \
DTRACE_PROBE1(postgresql,query__done,arg1)
或者使用systemtap的$$vars来输出可用变量.
[root@db-172-16-3-39 ~]# cat test.stp
probe process("/home/pg94/pgsql9.4devel/bin/postgres").mark("query__done") {
printf("args:%s\n", $$vars)
printf("proc:%s, tid:%d, sql:%s\n", execname(), tid(), kernel_string($arg1))
}
开启stap :
[root@db-172-16-3-39 ~]# stap test.stp
在数据库中执行SQL :
digoal=# insert into t9 values (4,'test'),(3,'abc');
INSERT 0 2
stap将输出这个event对应的$$vars, 这里的$arg1就是我们要的 :
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:insert into t9 values (4,'test'),(3,'abc');
接下来要获取query_done这个事件中的target variable arg1的地址对应的string值.
也就是SQL.
[root@db-172-16-3-39 ~]# cat test.stp
probe process("/home/pg94/pgsql9.4devel/bin/postgres").mark("query__done") {
printf("proc:%s, tid:%d, sql:%s\n", execname(), tid(), kernel_string($arg1))
exit()
}
执行stap
[root@db-172-16-3-39 ~]# stap test.stp
执行sql :
pg94@db-172-16-3-39-> psql
psql (9.4devel)
Type "help" for help.
digoal=# drop table t9;
DROP TABLE
digoal=# create table t9(id int primary key, info text);
CREATE TABLE
digoal=# insert into t9 values (1,'test'),(2,'abc');
INSERT 0 2
digoal=# \q
stap输出 :
[root@db-172-16-3-39 ~]# stap test.stp
proc:postgres, tid:2244, sql:drop table t9;
proc:postgres, tid:2244, sql:create table t9(id int primary key, info text);
proc:postgres, tid:2244, sql:insert into t9 values (1,'test'),(2,'abc');
这里输出了arg1对应地址的字符串, 就是我们要的sql.
使用prepared statement.
digoal=# prepare p1 (int,text) as insert into t9 values ($1,$2);
PREPARE
digoal=# execute p1(100,'test');
INSERT 0 1
digoal=# execute p1(101,'test');
INSERT 0 1
digoal=# execute p1(102,'test');
INSERT 0 1
digoal=# execute p1(103,'test');
INSERT 0 1
digoal=# execute p1(104,'test');
INSERT 0 1
digoal=# execute p1(105,'test');
INSERT 0 1
digoal=# execute p1(106,'test');
INSERT 0 1
输出 :
[root@db-172-16-3-39 ~]# stap test.stp
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:prepare p1 (int,text) as insert into t9 values ($1,$2);
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(100,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(101,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(102,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(103,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(104,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(105,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:execute p1(106,'test');
虚拟内存地址未变.
digoal=# insert into t9 values (110,'test');
INSERT 0 1
digoal=# insert into t9 values (111,'test');
INSERT 0 1
digoal=# select * from t9 limit 1;
id | info
----+------
1 | test
(1 row)
stap输出 :
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:insert into t9 values (110,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:insert into t9 values (111,'test');
args:$arg1=0x144f3f60
proc:postgres, tid:2654, sql:select * from t9 limit 1;
参考
1. http://www.postgresql.org/docs/devel/static/dynamic-trace.html
2. https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/SystemTap_Tapset_Reference/conversions.stp.html#API-user-string
3. https://sourceware.org/systemtap/tutorial/Analysis.html