项目中要求把日志信息写到文件的同时也把其写入数据库中, log4j.properties版本log4j-1.2.17, 配置如下
log4j.rootLogger=INFO,wjc,wjf,wjj
#common
log4j.appender.wjc.Encoding=GB2312
log4j.appender.wjc=org.apache.log4j.ConsoleAppender
log4j.appender.wjc.layout=org.apache.log4j.PatternLayout
log4j.appender.wjc.layout.ConversionPattern=%d %5p (%F:%L) - %m%n
log4j.appender.wjf.Encoding=GB2312
log4j.appender.wjf=org.apache.log4j.DailyRollingFileAppender
log4j.appender.wjf.Append=true
log4j.appender.wjf.File.DatePattern='.'yyyy-MM-dd
log4j.appender.wjf.File=${catalina.base}/logs/jin.log
log4j.appender.wjf.layout=org.apache.log4j.PatternLayout
log4j.appender.wjf.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss } %t %p -%m%n
log4j.appender.wjj.Threshold=WARN
log4j.appender.wjj=com.common.component.syslog.Log4JdbcAppender
log4j.appender.wjj.layout=org.apache.log4j.PatternLayout
log4j.appender.wjj.sql=insert into cp_syslog(log_time, log_level, location, message) values ('%d{yyyyMMddHHmmss }', '%-5p', '%C,%L', '%m')
#special
log4j.logger.org.apache.cxf=WARN
在代码中调用log.warn("abcd");等就可以把信息写入数据库了.错误日志:
log4j:ERROR Failed to excute sql
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'classes/spring/spring'')' at line 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
at com.mysql.jdbc.Statement.executeUpdate(Statement.java:1316)
at com.mysql.jdbc.Statement.executeUpdate(Statement.java:1235)
at com.joysim.common.component.syslog.Log4JdbcAppender.execute(Log4JdbcAppender.java:52)
at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:289)
at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:186)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
经调试发现要执行的sql语句里面包含了单引号,而我们知道要插入数据库中单引号是要进行转义处理的.
从错误信息中跟进发现sql是在JDBCAppender.flushBuffer()方法中进行了处理, 源码如下:
public void flushBuffer() { //Do the actual logging removes.ensureCapacity(buffer.size()); for (Iterator i = buffer.iterator(); i.hasNext();) { LoggingEvent logEvent = (LoggingEvent)i.next(); try { String sql = getLogStatement(logEvent); execute(sql); } catch (SQLException e) { errorHandler.error("Failed to excute sql", e, ErrorCode.FLUSH_FAILURE); } finally { removes.add(logEvent); } }
打印发现是getLogStatement(logEvent)对sql进行了处理, 该方法的代码如下:
/** * By default getLogStatement sends the event to the required Layout object. * The layout will format the given pattern into a workable SQL string. * * Overriding this provides direct access to the LoggingEvent * when constructing the logging statement. * */ protected String getLogStatement(LoggingEvent event) { return getLayout().format(event); }