PostgreSQL Systemtap example : Customize probe connect and disconnect

1 minute read

背景

本文要讲一下PostgreSQL的定制化探针, 系统自带的探针以后再讲.  
源码下过来之后, 在编译前, 我们能看到数据库探针的定义文件在src/backend/utils/probes.d中.   
probes.h文件是编译时生成的, 所以要添加探针的话, 只需要修改probes.d文件, 本文添加的探针没有参数, 如果要添加参数, 请注意参数的类型, 如果没有合适的类型, 请先把类型定义写到probes.d中.  
使用探针的前提, 编译时使用了enable-dtrace选项.  
./configure --prefix=/home/pg93/pgsql9.3.1 --with-pgport=1999 --with-perl --with-tcl --with-python --with-openssl --with-pam --without-ldap --with-libxml --with-libxslt --enable-thread-safety --with-wal-blocksize=16 --enable-dtrace --enable-debug  
接下来是添加自定义探针的步骤如下 :   
例如我们要添加2个探针, 分别选择在连接数据库和断开连接时触发.  
修改probes.d, 添加探针.  
vi src/backend/utils/probes.d  
provider postgresql {  
// add by digoal  
        probe client_conn();  
        probe client_close();  
编译probes.d, 将在probes.h生成探针宏, 这个宏遵循 /usr/include/sys/sdt.h 标准 :   
[root@db-172-16-3-39 postgresql-9.3.1]# cd src/backend/utils/  
[root@db-172-16-3-39 utils]# make  
[root@db-172-16-3-39 utils]# less probes.h  
/* TRACE_POSTGRESQL_CLIENT_CONN () */  
#if defined STAP_SDT_V1  
#define TRACE_POSTGRESQL_CLIENT_CONN_ENABLED() __builtin_expect (client_conn_semaphore, 0)  
#define postgresql_client_conn_semaphore client_conn_semaphore  
#else  
#define TRACE_POSTGRESQL_CLIENT_CONN_ENABLED() __builtin_expect (postgresql_client_conn_semaphore, 0)  
#endif  
__extension__ extern unsigned short postgresql_client_conn_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));  
#define TRACE_POSTGRESQL_CLIENT_CONN() \  
DTRACE_PROBE(postgresql,client_conn)  
  
/* TRACE_POSTGRESQL_CLIENT_CLOSE () */  
#if defined STAP_SDT_V1  
#define TRACE_POSTGRESQL_CLIENT_CLOSE_ENABLED() __builtin_expect (client_close_semaphore, 0)  
#define postgresql_client_close_semaphore client_close_semaphore  
#else  
#define TRACE_POSTGRESQL_CLIENT_CLOSE_ENABLED() __builtin_expect (postgresql_client_close_semaphore, 0)  
#endif  
__extension__ extern unsigned short postgresql_client_close_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));  
#define TRACE_POSTGRESQL_CLIENT_CLOSE() \  
DTRACE_PROBE(postgresql,client_close)  
把刚才生成的宏TRACE_POSTGRESQL_CLIENT_CONN()以及TRACE_POSTGRESQL_CLIENT_CLOSE()添加到PostgreSQL相应的源码中.  
[root@db-172-16-3-39 utils]# cd /opt/soft_bak/postgresql-9.3.1/src/backend/libpq  
[root@db-172-16-3-39 libpq]# vi pqcomm.c  
// 所有加探针的源文件都必须包含pg_trace.h头, 以包含宏的定义  
// add by digoal  
#include "pg_trace.h"  
.... 略  
在pq_init函数开头加上宏TRACE_POSTGRESQL_CLIENT_CONN();  
/* --------------------------------  
 *              pq_init - initialize libpq at backend startup  
 * --------------------------------  
 */  
void  
pq_init(void)  
{  
        // add by digoal  
TRACE_POSTGRESQL_CLIENT_CONN();  
.... 略  
在pq_close函数开头加上宏TRACE_POSTGRESQL_CLIENT_CLOSE();  
/* --------------------------------  
 *              pq_close - shutdown libpq at backend exit  
 *  
 * Note: in a standalone backend MyProcPort will be null,  
 * don't crash during exit...  
 * --------------------------------  
 */  
static void  
pq_close(int code, Datum arg)  
{  
// add by digoal  
TRACE_POSTGRESQL_CLIENT_CLOSE();  
重新编译PostgreSQL  
[root@db-172-16-3-39 libpq]# cd /opt/soft_bak/postgresql-9.3.1  
[root@db-172-16-3-39 postgresql-9.3.1]# gmake && gmake install  
重启数据库  
[root@db-172-16-3-39 postgresql-9.3.1]# su - pg93  
pg93@db-172-16-3-39-> pg_ctl restart -m fast  
  
测试新增的两个探针 :   
[root@db-172-16-3-39 postgresql-9.3.1]# stap -e 'probe process("/home/pg93/pgsql9.3.1/bin/postgres").mark("client_conn"),process("/home/pg93/pgsql9.3.1/bin/postgres").mark("client_close") {printdln("---",pn(),execname(),cmdline_str(),pid())}'  
  
在其他会话中连接和断开数据库  
pg93@db-172-16-3-39-> psql  
psql (9.3.1)  
Type "help" for help.  
digoal=# select pg_backend_pid();  
 pg_backend_pid   
----------------  
          11436  
(1 row)  
digoal=# \q  
  
在stap中可以看到输出 :   
process("/home/pg93/pgsql9.3.1/bin/postgres").mark("client_conn")---postgres---/home/pg93/pgsql9.3.1/bin/postgres---11436  
process("/home/pg93/pgsql9.3.1/bin/postgres").mark("client_close")---postgres---postgres: postgres digoal [local] idle---11436  
  
自定义探针步骤  
1. 在源码中找到想要放探针的位置, 以及是否需要捕捉变量值  
2. 修改probes.d, 新增类型定义(可选)  
3. 修probes.d, 新增探针  
4. 生成probes.h  
5. 在源码相应位置插入探针  
6. 在插入探针的源码中添加pg_trace.h头文件  
7. 重新编译PostgreSQL  
8. 重启数据库  
9. 测试探针  
  
  
[其他]  
1. 如果在数据库的配置文件中配置了记录连接和断开连接的log, 那么可以从日志中看到类似如下信息 :   
2013-10-11 14:34:24.066 CST,,,10880,"",52579bf0.2a80,1,"",2013-10-11 14:34:24 CST,,0,LOG,00000,"connection received: host=[local]",,,,,,,,"BackendInitialize, postmaster.c:3857",""  
2013-10-11 14:34:24.067 CST,"postgres","digoal",10880,"[local]",52579bf0.2a80,2,"authentication",2013-10-11 14:34:24 CST,2/1,0,LOG,00000,"connection authorized: user=postgres database=digoal",,,,,,,,"PerformAuthentication, postinit.c:239",""  
2013-10-11 14:34:25.202 CST,"postgres","digoal",10880,"[local]",52579bf0.2a80,3,"idle",2013-10-11 14:34:24 CST,,0,LOG,00000,"disconnection: session time: 0:00:01.135 user=postgres database=digoal host=[local]",,,,,,,,"log_disconnections, postgres.c:4429","psql"  
所以在放连接和断开连接的探针时, 也可以选择以上几个代码的位置.  

参考

1. http://www.postgresql.org/docs/9.3/static/dynamic-trace.html

2. http://blog.163.com/digoal@126/blog/static/163877040201383044341926/

3. src/backend/utils/probes.d

4. src/include/pg_trace.h

5. src/backend/utils/probes.h

6. src/backend/libpq/pqcomm.c

7. /usr/include/sys/sdt.h

Flag Counter

digoal’s 大量PostgreSQL文章入口