Post ที่แล้วเขียนเกี่ยวกับการ trace SQL บน FreeBSD ไป ในครั้งนี้เราลองมาใช้ SystemTap ที่เป็นญาติของ DTrace ทางฝั่ง Linux กันบ้าง

ก่อนอื่นเราต้องเริ่มจากการ complile PostgreSQL Server เพื่อให้รองรับการใช้งาน SystemTap เสียก่อน

Install dependencies
yum install automake autoconf gcc gcc-c++ git bison libstdc++-devel cscope doxygen ctags libtool elfutils-devel libebl-dev libdw-dev kernel-headers-devel

Install Debuginfo

debuginfo-install kernel-`uname -r`

Compile SystemTap ขั้นตอนนี้ต้องทำก่อนการ compile postgres ไม่งั้นจะไม่สามารถ config ให้ผ่านได้ เนื่องจากหา dtrace/systemtap ไม่เจอ

tar -xvf systemtap-2.7.tar-gz
cd systemtap-2.7
./configure
make
make install

Compile PostgreSQL with Dtrace Enabled จะเห็นว่า option นั้นเป็น –enable-dtrace แต่ก็สามารถใช้กับ systemtap ได้เช่นกัน

./configure --enable-dtrace


Make
make world
Make install
make install world

Initialize DB

mkdir /usr/local/pgsql/data
#สร้าง user postgres
chown postgres:postgres /usr/local/pgsql/data
su - postgres
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data/

Start Postgres DB (as postgres)

pg_ctl -D /usr/local/postgres/data -l /usr/local/postgres/server.log start

 

หลังจากนั้นเราก็ต้องทดลองเขียน script systemtap กัน
ส่วนที่น่าสนใจคือ probe เราจะต้องแทนค่า – ด้วย __
timest เป็นตัวแปรแบบ global ชนิด associative array โดยมี 2 index คือ thread ID และ arg1 ซึ่งเป็น address ของ argument ใน probe
user_string เป็น function ในการอ่านค่าจาก address แล้วแปลงให้เป็น string

global timest

probe process("/usr/local/pgsql/bin/postgres").mark("query__start")
{
timest[tid(),$arg1] = gettimeofday_us();
}

probe process("/usr/local/pgsql/bin/postgres").mark("query__done")
{
p = tid()
t = timest[p,$arg1];
printf("Transaction start : %s %d\n", user_string($arg1), (gettimeofday_us() - t));
}


**ควรจะต้องมีการลบค่าออกจาก array ด้วยคำสั่ง delete timest

[root@localhost ~]# stap -v query.d
Pass 1: parsed user script and 106 library script(s) using 157688virt/33132res/2144shr/31752data kb, in 100usr/70sys/179real ms.
Pass 2: analyzed script: 2 probe(s), 6 function(s), 4 embed(s), 1 global(s) using 159384virt/35832res/3156shr/33448data kb, in 10usr/90sys/156real ms.
Pass 3: translated to C into "/tmp/stap5aKlk2/stap_d18cebcf997e51e7dda96029c70e63ca_4020_src.c" using 159384virt/36168res/3488shr/33448data kb, in 10usr/50sys/66real ms.
Pass 4: compiled C into "stap_d18cebcf997e51e7dda96029c70e63ca_4020.ko" in 780usr/3480sys/5570real ms.
Pass 5: starting run.
Transaction start : select * from information_schema.tables; 22587
^CPass 5: run completed in 0usr/40sys/3509real ms.