仅显示有效的SQL字符串 P6Spy

6
我正在使用p6spy记录程序生成的SQL语句。输出的spy.log文件格式如下:
current time|execution time|category|statement SQL String|effective SQL string

我想知道是否有一种方法可以修改spy.properties文件,并仅将最后一列有效的SQL字符串输出到spy.log文件中?我已经查看了属性文件,但没有找到支持此功能的内容。
谢谢!
5个回答

15
在 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); 
    }

}

更新:在 p6Spy 3.9 中,formatMessage 方法有一个额外的 String url 参数。自从 Hibernate 4.0 开始,BasicFormatterImpl 现在是 org.hibernate.engine.jdbc.internal.BasicFormatterImpl - Marduk

1
目前还没有提供这样的选项,只能通过配置实现。我认为你有2个选择

对于后一种选择,我相信你可以通过自己的类来实现(取决于你使用的日志记录器,假设你使用Log4jLogger)。

如果你查看Log4jLogger githubsourceforge 版本的相关部分,你的实现应该非常简单:

spy.properties:

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 版本)。
请注意:我自己没有测试这个建议,但它可能是一个很好的起点,并且从代码审查本身来看,我认为它可能有效。

1

我同意@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);
    }
}

1
在p6Spy 3.9中,这可以很简单地实现。在spy.properties中设置即可。
customLogMessageFormat=%(effectiveSql)

0

您可以修补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中的现有类文件。


这看起来像是一个过度解决的方案。 - Stephan
是的,我也不开心。也许我应该提交一个拉取请求,使其成为一个选项。但目前,由于它是硬编码的,没有其他解决方案。 - Ray Hulha
提出一个新的格式,可以直接从spy.log文件中读取自己的格式。 - Stephan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接