p6spyのバージョンは1.3。
Mavenで設定する場合は、次のとおり。
<dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId> <version>1.3</version> </dependency>
1.3ではロガーにバグがあるらしく、フォーマットやカテゴリを指定しても、その設定でログ出力されない。
なので、ロガーを作成する。
import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Properties; import com.p6spy.engine.common.P6SpyProperties; import com.p6spy.engine.logging.appender.Log4jLogger; /* * p6spyでのデバッグ用ロガー。 * * <p> * p6spyが提供するLog4jのロガーにバグがあるため。 * */ public class P6spyLog4jLogger extends Log4jLogger { private static final String LINE_SEPARATOR = System.getProperty("line.separator"); private boolean initialized = false; private List<String> categories = new ArrayList<String>(); private boolean preparedEnabled = false; private boolean sqlEnabled = true; private String format = "%ct %c: %e[ms] %s"; public void intialize() { if (!initialized) { doInitialize(); } } protected void doInitialize() { P6SpyProperties p6SpyProperties = new P6SpyProperties(); Properties properties = p6SpyProperties.forceReadProperties(); String enableCategory = properties.getProperty("P6spyLog4jLogger.enable.category"); String enableSqlLevel = properties.getProperty("P6spyLog4jLogger.enable.sql.level"); String format = properties.getProperty("P6spyLog4jLogger.format"); if (!isNullString(enableCategory)) { for (String category : enableCategory.trim().split(",")) { this.categories.add(category.trim()); } } else { categories.add("statement"); categories.add("resultset"); categories.add("commit"); categories.add("rollback"); } if (!isNullString(enableSqlLevel)) { enableSqlLevel = enableSqlLevel.trim(); if (enableSqlLevel.equals("all")) { this.preparedEnabled = true; this.sqlEnabled = true; } else if (enableSqlLevel.equals("prepare")) { this.preparedEnabled = true; this.sqlEnabled = false; } else { this.preparedEnabled = false; this.sqlEnabled = true; } } if (!isNullString(format)) { this.format = format; } initialized = true; } private boolean isNullString(String string) { return string == null || string.trim().length() == 0; } private String replace(int connectionId, String now, long elapsed, String category, String statement) { return this.format .replace("%ct", String.valueOf(category)) .replace("%c", String.valueOf(connectionId)) .replace("%e", new DecimalFormat("00000").format(elapsed)) .replace("%n", LINE_SEPARATOR) .replace("%t", " ") .replace("%s", statement); } @Override public void logSQL(int connectionId, String now, long elapsed, String category, String prepared, String sql) { intialize(); if (categories.contains(category)) { if (preparedEnabled) { logText(replace(connectionId, now, elapsed, category, prepared)); } if (sqlEnabled) { logText(replace(connectionId, now, elapsed, category, sql)); } } } }
このロガーを利用するように、p6spyの設定ファイルに記述する。
設定ファイルは「classpath:spy.properties」。
appender=net.kronos.p6spy.P6spyLog4jLogger #出力するカテゴリを複数指定 P6spyLog4jLogger.enable.category=statement #prepareStatmementを出すかどうか。allは全部出す P6spyLog4jLogger.enable.sql=sql #ログフォーマット P6spyLog4jLogger.format=[%ct][%ems]%n%t%s
Log4jの設定ファイルにロガーを記述する。
<logger name="p6spy" additivity="false"> <level value="INFO" /> <appender-ref ref="STDOUT" /> </logger>
Springで利用する場合は、P6DataSourceでデータソースをラップする。
<bean id="dataSource" class="com.p6spy.engine.spy.P6DataSource"> <constructor-arg> <ref local="dataSourceTarget" /> </constructor-arg> </bean>
以上でこんなフォーマットでSQLをログに出力する。
[INFO ]11/09/30 00:00:32,397 - [statement][00002ms] SELECT ...