最近做的一个项目中,生产环境上交易量比较大,一般是每日10000笔。原来记录日志方式的结果是多个线程交织在一起,大大的影响了日志的可读性,给分析问题带来了很大的障碍。
上网搜了相关资料,得出了一个解决方案,如下:
1.在web.xml中更改启动的拦截器
<filter>
<filter-name>Struts2</filter-name>
<filter-class>cn.com.nantian.epayment.core.StrutsFilter</filter-class>
</filter>
2.新建拦截器 StrutsFilter.java
package cn.com.nantian.epayment.core;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.log4j.MDC;
import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
public class StrutsFilter extends StrutsPrepareAndExecuteFilter {
private static final SimpleDateFormat sdf = new SimpleDateFormat("mmssSSS");
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
long threadId = Thread.currentThread().getId();
String timestamp = sdf.format(new Date());
MDC.put("REQ_ID", "REQ"+timestamp +"-"+ threadId);
super.doFilter(req, res, chain);
}
}
3.log4j的配置
#core logger set
log4j.rootLogger=INFO,CONSOLE
#app logger set
log4j.logger.ECCommonLogger=DEBUG,ECCOM_LOG_FILE
log4j.additivity.ECCommonLogger=true
log4j.logger.ECPayLogger=DEBUG,ECPAY_LOG_FILE
log4j.additivity.ECPayLogger=true
log4j.logger.ECRspLogger=DEBUG,ECRSP_LOG_FILE
log4j.additivity.ECRspLogger=true
log4j.logger.ECReFundLogger=DEBUG,REFUND_LOG_FILE
log4j.additivity.ECReFundLogger=true
log4j.logger.ECRFDCheckLogger=DEBUG,ECRFDCHECK_LOG_FILE
log4j.additivity.ECRFDCheckLogger=true
log4j.logger.ECPayCheckLogger=DEBUG,ECPAYCHECK_LOG_FILE
log4j.additivity.ECPayCheckLogger=true
log4j.additivity.org=false
log4j.appender.Threshold=warn
#
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] -[%X{REQ_ID}] - %F %L - %m%n
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[thread] n%c[CATEGORY]%n%m[MESSAGE]%n%n
# Use this layout for LogFactor 5 analysis
log4j.appender.ECCOM_LOG_FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ECCOM_LOG_FILE.File=../logs/common/ecpay-common.log
log4j.appender.ECCOM_LOG_FILE.encoding=UTF-8
log4j.appender.ECCOM_LOG_FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.ECCOM_LOG_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ECCOM_LOG_FILE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] -[%X{REQ_ID}] - %F %L - %m%n
#payment file log
log4j.appender.ECPAY_LOG_FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ECPAY_LOG_FILE.File=../logs/payment/ecpay-pay.log
log4j.appender.ECPAY_LOG_FILE.encoding=UTF-8
log4j.appender.ECPAY_LOG_FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.ECPAY_LOG_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ECPAY_LOG_FILE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] -[%X{REQ_ID}] - %F %L - %m%n
#callback file log
log4j.appender.ECRSP_LOG_FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ECRSP_LOG_FILE.File=../logs/rspment/ecpay-rsp.log
log4j.appender.ECRSP_LOG_FILE.encoding=UTF-8
log4j.appender.ECRSP_LOG_FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.ECRSP_LOG_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ECRSP_LOG_FILE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] -[%X{REQ_ID}] - %F %L - %m%n
#refund file log
log4j.appender.REFUND_LOG_FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.REFUND_LOG_FILE.File=../logs/refund/ecpay-refund.log
log4j.appender.REFUND_LOG_FILE.encoding=UTF-8
log4j.appender.REFUND_LOG_FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.REFUND_LOG_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.REFUND_LOG_FILE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] -[%X{REQ_ID}] - %F %L - %m%n
#refund check file log
log4j.appender.ECRFDCHECK_LOG_FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ECRFDCHECK_LOG_FILE.File=../logs/refcheck/ecpay-refundcheck.log
log4j.appender.ECRFDCHECK_LOG_FILE.Append=true
log4j.appender.ECRFDCHECK_LOG_FILE.encoding=UTF-8
log4j.appender.ECRFDCHECK_LOG_FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.ECRFDCHECK_LOG_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ECRFDCHECK_LOG_FILE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] - %F %L - %m%n
#pay check file log
log4j.appender.ECPAYCHECK_LOG_FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ECPAYCHECK_LOG_FILE.File=../logs/paycheck/ecpay-paycheck.log
log4j.appender.ECPAYCHECK_LOG_FILE.Append=true
log4j.appender.ECPAYCHECK_LOG_FILE.encoding=UTF-8
log4j.appender.ECPAYCHECK_LOG_FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.ECPAYCHECK_LOG_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ECPAYCHECK_LOG_FILE.layout.ConversionPattern=[ElecChnlPay-app] [%d] [%-5p] - %F %L - %m%n
4.记录日志分流
package cn.com.nantian.epayment.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @beused 日志工具类
* @version v0.1
* @created Dec 27, 2011 12:03:01 PM
* @editime Dec 27, 2011 12:03:01 PM
* @company 重庆南天数据资讯服务有限公司
*/
public class LogUtils {
private static ThreadLocal<Log> loggerThdLocalMap=new ThreadLocal<Log>();//私有静态变量
//业务日志记录器
private static Log paymentlogger = LogFactory.getLog("ECPayLogger");
private static Log rspmentlogger = LogFactory.getLog("ECRspLogger");
private static Log refundlogger = LogFactory.getLog("ECReFundLogger");
private static Log refundChecklogger = LogFactory.getLog("ECRFDCheckLogger");
private static Log payChecklogger = LogFactory.getLog("ECPayCheckLogger");
//通用日志记录器
private static Log commonlogger = LogFactory.getLog("ECCommonLogger");
/**
* 支付业务日志记录器
*/
public static void buildPaymentlogger() {
loggerThdLocalMap.set(paymentlogger);
}
/**
* 支付业务回调日志记录器
*/
public static void buildRspmentlogger() {
loggerThdLocalMap.set(rspmentlogger);
}
/**
* 退款业务日志记录器
*/
public static void buildRefundlogger() {
loggerThdLocalMap.set(refundlogger);
}
/**
* 支付对账业务日志记录器
*/
public static void buildPayCheckLogger(){
loggerThdLocalMap.set(payChecklogger);
}
/**
* tu对账业务日志记录器
*/
public static void buildRefundCheckLogger(){
loggerThdLocalMap.set(refundChecklogger);
}
public static Log getLogger(){
Log log = (Log)loggerThdLocalMap.get();
if(log==null){
return commonlogger;
}else{
return log;
}
}
}
5.不同的业务调用不同的日志分流
如
LogUtils.buildPaymentlogger();
LogUtils.getLogger().info("========支付开始========");
LogUtils.getLogger().debug("【isRunning】状态值:" + isRunning);
LogUtils.getLogger().debug("【PartnerID】:" + PartnerID);
LogUtils.getLogger().info("【解密前PayReqObj】:" + PayReqObj);