アプリケーションから発行されているSQLを取得したい


ちょっと訳ありで上記のようなことをおこないたいケースが出てきました。
大概はソースいじるなりなんなりすればいいのですが、
諸事情により残念ながらそのような選択肢がとれなかったので、
jarを入れ替えるなり、設定を追加するなりでできないかと調べていました。


やり方としてはJDBCのpreparedStatementにラッパーをかければよくて、
そのやり方ができるライブラリも幾つか転がっていたのですが、
使っているアプリケーションがDataSourceを使っており、
そこまで対応しているものが中々なくて色々と探し回っていました。


で、見つけたのが次。


http://code.google.com/p/jdbcdslog

インストール


jarなんで普通にlibフォルダにいれればOKです。
ただし、slf4jを使用しているので一緒にいれる必要があります。

設定方法


使うためにはJDBCドライバのクラスと接続するURLを変更する必要があります。


まずはJDBCドライバのクラスを変更します。
Oracleの場合は、oracle.jdbc.driver.OracleDriverになっているので、
それをorg.jdbcdslog.DriverLoggingProxyに変更します。

Class.forName("oracle.jdbc.driver.OracleDriver")
 ↓ 
Class.forName("org.jdbcdslog.DriverLoggingProxy")


もう一つ、接続先を次のように変更します。

jdbc:oracle:thin:@XXX.XXX.XXX.XXX:1521:XX
 ↓
jdbc:jdbcdslog:oracle:thin:@XXX.XXX.XXX.XXX:1521:XX;targetDriver=oracle.jdbc.driver.OracleDriver

ログの出力


ログは次の3種類でます。

  • DBに接続したログ
56 [main] INFO org.jdbcdslog.ConnectionLogger - connect to URL jdbc:hsqldb:. with properties: {user=sa} 
  • SQLを実行したログ
62627 [http-8080-1] INFO org.jdbcdslog.StatementLogger - java.sql.PreparedStatement.executeQuery select id, email from user where username = ? parameters: {'admin'} 12ms. 
  • SQLの結果のログ
62118 [http-8080-2] INFO org.jdbcdslog.ResultSetLogger - java.sql.ResultSet.next {1234, 'root@a.com'} 


SQLだけ取得したい場合はorg.jdbcdslog.StatementLoggerだけを取得するように出力すればOKですね。

DataSourceを使うときには


DataSourceを使うときには次のように設定します。


DataSourceでのドライバクラスは次のように設定します。

oracle.jdbc.xa.client.OracleXADataSource
 ↓
org.jdbcdslog.ConnectionPoolXADataSourceProxy


もう一つ接続先は次のようにします。

jdbc:oracle:thin:@XXX.XXX.XXX.XXX:1521:XX
 ↓
jdbc:oracle:thin:@XXX.XXX.XXX.XXX:1521:XX;targetDS=oracle.jdbc.xa.client.OracleXADataSource


これでログを仕込むことができます。


通常、永続化ライブラリを使用している場合は、
そのライブラリ内でSQLを出力する機構を持っていると思うので、
これが必要になる機会があるかという話がありますが、一応記しておきます。