Log4j JDBCAppender用于记录stacktraces

时间:2011-07-18 13:57:38

标签: jdbc log4j stack-trace

使用org.apache.log4j.jdbc.JDBCAppender,如何将warnerror的跟踪记录记录到PatternLayout

我正在记录

logger.warn("warning description", e);
logger.error("error description", e);

我将String描述放入表中,但是Throwable的堆栈跟踪现在在哪里。是否有其他参数可以通过PatternLayout访问。目前我正在使用

"INSERT INTO app_logs (app, log_date, log_level, location, loc, message) VALUES ('my-apps-name', '%d{ISO8601}','%p', '%C.java', '%C{1}.java:%L', '%m')" 

进入表格

TABLE `app_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app` varchar(255) DEFAULT NULL,
  `log_date` varchar(255) DEFAULT NULL,
  `log_level` varchar(255) DEFAULT NULL,
  `location` varchar(255) DEFAULT NULL,
  `loc` varchar(255) DEFAULT NULL,
  `message` text, 
  PRIMARY KEY (`id`)
)

4 个答案:

答案 0 :(得分:11)

我找到了解决方案。

PatternLayout类替换为EnhancedPatternLayout类。

org.apache.log4j.EnhancedPatternLayout

您还需要添加apache-log4j-extra dependency

include it in your pom

<dependency>
  <groupId>log4j</groupId>
  <artifactId>apache-log4j-extras</artifactId>
  <version>1.1</version>
</dependency>

您现在可以访问%throwable

  

%throwable{short}%throwable{1}将输出第一行堆栈   跟踪。 throwable{none}throwable{0}将抑制堆栈跟踪。   如果是正整数,%throwable{n}将输出n行堆栈跟踪   如果是负整数,则省略最后的-n行。

我加入了我的桌子,

TABLE `app_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app` varchar(255) DEFAULT NULL,
  `log_date` varchar(255) DEFAULT NULL,
  `log_level` varchar(255) DEFAULT NULL,
  `location` varchar(255) DEFAULT NULL,
  `loc` varchar(255) DEFAULT NULL,
  `message` text,
  `throwable` text,
  `stacktrace` text,
  PRIMARY KEY (`id`)
)

并更新了我的模式以填充这些列。

"INSERT INTO app_logs (app, log_date, log_level, location, loc, message, throwable, stacktrace) VALUES ('my-apps-name', '%d{ISO8601}','%p', '%C.java', '%C{1}.java:%L', '%m', '%throwable{short}', '%throwable{100}')"

答案 1 :(得分:3)

解决方案是我们需要使用EnhancedPattern Layout,通过使用它,我们可以将整个堆栈跟踪记录到DB中。但是如果我们使用这个问题,如果Stacktrace包含逗号(,),则消息将不会被记录。我已经通过编写getLogStatement()来解决这个问题,这可以在JDBC appender中找到源代码

按照以下步骤

  1. 下载Log4j1.2.17。 增强的patternlayout可从log41.2.16 ver

  2. 获得
  3. 编辑log4j属性文件

    log4j.rootLogger = WARN, DB
    log4j.appender.DB=abc.xyz.MyJdbcAppender
    log4j.appender.DB.URL=jdbc:mysql://localhost/DBNAME
    log4j.appender.DB.driver=com.mysql.jdbc.Driver
    log4j.appender.DB.user=user_name
    log4j.appender.DB.password=password
    log4j.appender.DB.layout=org.apache.log4j.EnhancedPatternLayout
    log4j.appender.DB.conversionPattern=Insert into MylogFile(logid,loglevel,logcriteria,message,stacktrace,date) values (mysequence.nextval,’%p’,’%c’,
    ‘%m’,’%throwable{40},’%d{ABSOLUTE}’)
    
  4. 现在创建一个新类,它将扩展JDBCappender并覆盖getLogStatement()

    Public MyJdbcAppender extends JDBCAppender{
    protected String getLogStatement(LoggingEvent event) {
    if(null!=event.getThrowableInformation() && event.getThrowableInformation().getThrowable() instance of SQLException){
    SQLException myexce= new SQLException(event.
    getThrowableInformation().getThrowable().getMessage().
    replaceAll(“’”,” “),event.getThrowableInformation().getThrowable());
      LoggingEvent clone = new LoggingEvent(
        event.fqnOfCategoryClass,
        LogManager.getLogger(event.getLoggerName()),
        event.getLevel(),
    event.getLevel(),event.getMessage(),myexce); 
     return getLayout().format(clone);
    }
    return getLayout().format(event)
    }
    }
    

答案 2 :(得分:3)

为了扩展MikeNereson的答案,这里有一个有效的log4j.properties:

log4j.rootLogger=DEBUG,DB
log4j.appender.DB.driver=com.mysql.jdbc.Driver
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:mysql://server/db
log4j.appender.DB.user=user
log4j.appender.DB.password=pwd
log4j.appender.DB.layout.ConversionPattern=INSERT INTO app_logs (app, log_date, log_level, location, loc, message, throwable, stacktrace) VALUES ('appname', '%d{ISO8601}','%p', '%C.java', '%C{1}.java:%L', '%m', '%throwable{short}', '%throwable{100}')
log4j.appender.DB.layout=org.apache.log4j.EnhancedPatternLayout
log4j.category.ke.co=ERROR
log4j.category.ke.co.appender-ref=DB

答案 3 :(得分:2)

log4j 1.2.16+的EnhancedPatternLayout不起作用!因为它扩展了org.apache.log4j.Layout而不是org.apache.log4j.PatternLayout,但是在JDBCAppender中:

public void setSql(String s) {
    sqlStatement = s;
    if (getLayout() == null) {
        this.setLayout(new PatternLayout(s));
    }
    else {
        ((PatternLayout)getLayout()).setConversionPattern(s);  //Point1
    }
}

所以如果你像这样使用JDBCAppender:

log4j.appender.JDBC=org.apache.log4j.jdbc.JDBCAppender    
log4j.appender.JDBC.layout=org.apache.log4j.EnhancedPatternLayout
log4j.appender.JDBC.sql=INSERT INTO email_send_error(insert_date, level, location, message, stacktrace) VALUES (now(), '%p', '%C,%L', '%m', '%throwable{short}')

将在Point1中抛出ClassCastException:

  

引起:java.lang.ClassCastException:org.apache.log4j.EnhancedPatternLayout无法强制转换为org.apache.log4j.PatternLayout
      在org.apache.log4j.jdbc.JDBCAppender.setSql(JDBCAppender.java:330)



编辑(深入研究后):
使用 log4j.appender.JDBC.layout.ConversionPattern 而不是 log4j.appender.JDBC.sql ,将避免上面的ClassCastException:

 log4j.appender.JDBC.layout.ConversionPattern=INSERT INTO email_send_error(insert_date, level, location, message, stacktrace) VALUES (now(), '%p', '%C,%L', '%m', '%throwable{short}')

并且不要忘记将抛出的异常记录到记录器:

logger.error(String errorMsg, Throwabe e); // Dont forget e