让log4j通过判断日志消息的内容后再进行日志的输出。
如果我们要在一个有成百上千个用户的系统中通过日志信息来判断某一个用户的行为是否正确的话,可以想象会有多大的难度。(要从成百上千个用户产生的日志中准确的定位到某一个用户几乎是不可能的)所以这就产生了一个新的需求,log4j不仅可以配置级别,同时他应该还可以配置输出那个设备的日志,也就是日志是否输出不仅要根据级别,还要根据日志和业务的关系。
实现的原理
Logger对象中debug方法的参数类型是java.long.Object类型,平时我们都是直接将想要输出的日志以java.long.String类型传给debug方法,现在我们将会以一个大小是2的String[]类型作为参数,String[0]中存放和这条日志相关联的业务信息,String[1]中存放要输出的日志信息。其他的info error 等方法都采用相同的办法。
现在就是要解决Appender问题了。最简单的办法是自己创建一个Appende类,让这个类去继承我们以前用的Appender类,并重写doAppend(LoggingEvent event)方法就可以了。
实例代码:
PurposefulConsoleAppender.java
package com.kun.appender;
import org.apache.log4j.ConsoleAppender; import org.apache.log4j.spi.LoggingEvent;
public class PurposefulConsoleAppender extends ConsoleAppender { public static final String PURPOSE_ALL = "ALL";
protected String purpose = PURPOSE_ALL;
public String getPurpose() { return purpose; }
public void setPurpose(String purpose) { this.purpose = purpose; }
@Override public synchronized void doAppend(LoggingEvent event) { if (event.getMessage() instanceof String[]) { String[] message = (String[]) event.getMessage(); if (getPurpose().equalsIgnoreCase(PURPOSE_ALL) || PURPOSE_ALL.equalsIgnoreCase(message[0]) || getPurpose().equals(message[0])) { Throwable throwable = null; if (event.getThrowableInformation() != null) { throwable = event.getThrowableInformation().getThrowable(); } LoggingEvent newEvent = new LoggingEvent( event.fqnOfCategoryClass, event.getLogger(), event.timeStamp, event.getLevel(), message[1], throwable); super.doAppend(newEvent); } } else { super.doAppend(event); }
} }
|
TestLog4jPurposeful.java
package com.kun;
import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator;
public class TestLog4jPurposeful { public static Logger logger = Logger.getLogger(TestLog4jPurposeful.class);
public static void printLog() { if (logger.isDebugEnabled()) { logger.debug(new String[]{"11","debug!!"}); } if (logger.isInfoEnabled()) { logger.info(new String[]{"22","info!!"}); } logger.error(new String[]{"11","error!!"}); }
public static void main(String[] args) { PropertyConfigurator.configure("./log4j.properties");
while (!Thread.interrupted()) { TestLog4jPurposeful.printLog();
try { Thread.sleep(1000); } catch (InterruptedException e) { } } } }
|
log4j.properties (log4j的配置文件)
#-----------------------------------------------------------------------------! # Global configuration for log4j #-----------------------------------------------------------------------------! # Do use default configuration. #----------------------------------------------------------------------------! #Configure categories (loggers) #----------------------------------------------------------------------------! #ROOT CATEGORY (Usually sufficient to set this one only) log4j.rootCategory=debug,PURPOSEFULCONSOLE # YOUR CATEGORIES (to customize logging per class/pkg/project/etc) #----------------------------------------------------------------------------! #Configure appenders (log destinations/targets) and their options ! #----------------------------------------------------------------------------! #WRITE TO CONSOLE (stdout or stderr): log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.ImmediateFlush=true log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm}] (%F:%M:%L) - %m%n
#WRITE TO PURPOSEFULCONSOLE (stdout or stderr): log4j.appender.PURPOSEFULCONSOLE=com.kun.appender.PurposefulConsoleAppender log4j.appender.PURPOSEFULCONSOLE.ImmediateFlush=true log4j.appender.PURPOSEFULCONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.PURPOSEFULCONSOLE.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm}] (%F:%M:%L) - %m%n log4j.appender.PURPOSEFULCONSOLE.Purpose=22 |