我正在使用 p6spy 记录我的程序生成的 sql 语句。输出的 spy.log 文件的格式如下所示:
current time|execution time|category|statement SQL String|effective SQL string
我只是想知道是否有人知道是否有办法改变 spy.properties 文件并且只有最后一列,有效的 SQL 字符串,输出到 spy.log 文件?我查看了属性文件,但没有找到任何似乎支持这一点的东西。
谢谢!
在 spy.properties 中有一个名为的属性logMessageFormat
,您可以将其设置为MessageFormattingStrategy
. 这适用于任何类型的记录器(即文件、slf4j 等)。
例如
logMessageFormat=my.custom.PrettySqlFormat
使用 Hibernate 的漂亮打印 SQL 格式化程序的示例:
package my.custom;
import org.hibernate.jdbc.util.BasicFormatterImpl;
import org.hibernate.jdbc.util.Formatter;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
public class PrettySqlFormat implements MessageFormattingStrategy {
private final Formatter formatter = new BasicFormatterImpl();
@Override
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql) {
return formatter.format(sql);
}
}
目前还没有提供这样的选项来通过配置来实现它。我认为您在这里有两个选择:
对于后一种选择,我相信您可以通过自己的类来实现它(取决于您使用的记录器,假设您使用 Log4jLogger)。
好吧,如果您检查 Log4jLogger github的相关部分以及sourceforge版本,您的实现应该相当简单:
间谍属性:
appender=com.EffectiveSQLLog4jLogger
实现本身可能如下所示:
package com;
import com.p6spy.engine.logging.appender.Log4jLogger;
public class EffectiveSQLLog4jLogger extends Log4jLogger {
public void logText(String text) {
super.logText(getEffectiveSQL(text));
}
private String getEffectiveSQL(String text) {
if (null == text) {
return null;
}
final int idx = text.lastIndexOf("|");
// non-perfect detection of the exception logged case
if (-1 == idx) {
return text;
}
return text.substring(idx + 1); // not sure about + 1, but check and see :)
}
}
请注意,实施应涵盖 github(新项目主页,尚未发布版本)以及 sourceforge(原始项目主页,已发布 1.3 版本)。
请注意:我自己没有测试该提案,但这可能是一个很好的起点,从代码审查本身来看,我会说它可以工作。
我同意@boberj,我们习惯于使用 Hibernate 格式化程序来记录日志,但不要忘记批处理,这就是我建议使用的原因:
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;
import org.hibernate.engine.jdbc.internal.Formatter;
/**
* Created by Igor Dmitriev on 1/3/16
*/
public class HibernateSqlFormatter implements MessageFormattingStrategy {
private final Formatter formatter = new BasicFormatterImpl();
@Override
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql) {
if (sql.isEmpty()) {
return "";
}
String template = "Hibernate: %s %s {elapsed: %sms}";
String batch = "batch".equals(category) ? ((elapsed == 0) ? "add batch" : "execute batch") : "";
return String.format(template, batch, formatter.format(sql), elapsed);
}
}
您可以像这样修补com.p6spy.engine.spy.appender.SingleLineFormat.java
删除准备好的元素和对 P6Util 的任何引用:
package com.p6spy.engine.spy.appender;
public class SingleLineFormat implements MessageFormattingStrategy {
@Override
public String formatMessage(final int connectionId, final String now, final long elapsed, final String category, final String prepared, final String sql) {
return now + "|" + elapsed + "|" + category + "|connection " + connectionId + "|" + sql;
}
}
然后只编译文件
javac com.p6spy.engine.spy.appender.SingleLineFormat.java
并用新的替换 p6spy.jar 中现有的类文件。
在 p6Spy 3.9 中,这可以很简单地实现。在spy.properties
集合
customLogMessageFormat=%(effectiveSql)