最近的一个需求,需要记录接口访问的详情,如请求入参、出参、请求上下文、路径、消耗时间以及成功失败等信息,将这些信息以结构化的形式输出到单独的日志文件中,方便以后入库到elasticsearch中做分析。
百度搜索自定义日志级别的文章一大把,基本上都是使用Filter和xml配置的方式,这种方式能行,但我感觉写的代码略多,而且我的工程中用的properties的方式配置的,个人也比较懒也就不想改动,就没有采用这种方式。
log4j中每个appenders都有一个threshold,这个值默认是null
,它对应的是配置文件中log4j.appender.errorfile.Threshold = debug|info|error|...
项,如果不配置,会将所有级别日志打印到这个appender中,如果是debug则会将debug及以上的级别日志打印到这个appender中。
在类AppenderSkeleton
中有一个很重要的方法,它的默认实现如下
1 2 3
| public boolean isAsSevereAsThreshold(Priority priority) { return ((threshold == null) || priority.isGreaterOrEqual(threshold)); }
|
所以,很重要的一点就是自定义一个appender然后重写这个方法,修改判断逻辑,只是将等于自定义级别的日志打印到appender中。详细代码如下
1 2 3 4 5 6
| public class ConsumeLogLevel extends Level { public final static int CONSUME_INT = Priority.DEBUG_INT+50; public ConsumeLogLevel(int level, String levelStr, int syslogEquivalent) { super(level, levelStr, syslogEquivalent); } }
|
自定义日志级别类,我设置了一个比debug级别高一点的级别consume。这样的好处是不会将consume的日志打印到info中(如果设置了Threshold=info的appender)。
1 2 3 4 5 6 7
| public class ConsumeLog { private static Logger logger = Logger.getLogger(ConsumeLog.class); protected static final Level consumeLevel = new ConsumeLogLevel(ConsumeLogLevel.CONSUME_INT,"CONSUME", 7); public static void logConsumeInfo(Object objLogInfo){ logger.log(consumeLevel, objLogInfo); } }
|
定义一个类用于打印日志,创建一个日志级别实例consumeLevel,调用logger打印。
1 2 3 4 5 6 7 8 9 10
| public class ConsumeAppender extends DailyRollingFileAppender { @Override public Priority getThreshold() { return ConsumeLog.consumeLevel; } @Override public boolean isAsSevereAsThreshold(Priority priority) { return this.getThreshold().equals(priority); } }
|
自定义appender,这个例子中继承自DailyRollingFileAppender
,实际以需求而定可以继承自其它appender,重写两个方法,在isAsSevereAsThreshold
方法中修改判断逻辑,只有等于自定义级别的日志才打印。其中getThreshold()
方法写死返回consumeLevel。
1 2 3 4 5 6 7
| log4j.rootLogger=debug,consume log4j.appender.consume=com.xxx.log.ConsumeAppender log4j.appender.consume.File=../logs/bss-intf-cpct-consume-log.log log4j.appender.consume.DatePattern='.'yyyy-MM-dd log4j.appender.consume.append=true log4j.appender.consume.layout=org.apache.log4j.PatternLayout log4j.appender.consume.layout.ConversionPattern=xxx %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
|
log4j.properties配置如上,需要修改appender类名为自定义appender。
实际使用
1
| ConsumeLog.logConsumeInfo(xxx);
|
在实际中可以根据需求在ConsumeLogLevel
中定义多种级别,ConsumeLog
中实例化多个ConsumeLogLevel级别,针对每个级别创建一个自定义appender就可以实现多个自定义日志级别打印日志到多个文件中了。