PostgreSQL Systemtap example : Customize probe connect and disconnect
背景
本文要讲一下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