现在的位置: 首页 > 综合 > 正文

Log4j简介(三)

2013年10月06日 ⁄ 综合 ⁄ 共 3424字 ⁄ 字号 评论关闭

今天具体说说log4j的控制日志输入和涉及的两个概念:level和filter。

 

首先来看level和filter的定义,接着看它们是如何在配置文件中使用的。

 

level:

level就是记log时的severity级别。在之前的blog中已经做了介绍。现在看一个自定义的gmiLevel class的例子:

public class GMILevel extends Level {

//用于自定义level时用。toLevel可直接将这个int转换成对应的level。

public static final int GMI_UNKNOWN_INT = 1000;

//自定义level。

public static final GMILevel GMI_UNKNOWN = new GMILevel(GMI_UNKNOWN_INT,
            GMIMessageConstants.Severity.UNKNOWN.toString(), 7);

protected GMILevel(final int level, final String levelStr, final int syslogEquivalent) {
        super(level, levelStr, syslogEquivalent);

//Level(int level, String levelStr, int syslogEquivalent) 注意通过level的构造函数我们//可以知道每个level有自己的level int和syslogEquivalent(1,2,3等等)。
    }

public static boolean isGMILevel(final int i) {
        switch (i) {
        case GMI_UNKNOWN_INT:
            return true;

(这里还有很多其它的GMI_HARMLESS,GMI_CRITICAL等。这个方法用于在别的class中判断是否是gmiLevel)

        default:
            return false;
        }
    }

//这个是实现的level的方法。将一个传入的string转换成上面定义好的某种gmiLevel。

public static Level toLevel(final String sArg) {
        if (sArg == null) {
            return GMI_UNKNOWN;
        }

if (sArg.equalsIgnoreCase(GMIMessageConstants.Severity.UNKNOWN.toString())) {
            return GMI_UNKNOWN;
        } else if (sArg.equalsIgnoreCase(GMIMessageConstants.Severity.INFORMATION.toString())) {
            return GMI_INFORMATION;
        }

return Level.toLevel(sArg, GMI_UNKNOWN);

}

}

下面可以看到上面定义的level是怎么在filter中使用的。

Filter:

Users should extend this class to implement customized logging event filtering. Note that Category and AppenderSkeleton, the parent class of all standard appenders, have built-in filtering rules. It is suggested that you first use and understand the built-in rules before rushing to write your own custom filters.
This abstract class assumes and also imposes that filters be organized in a linear chain.
也就是说,所有的filters组成了一个chain。每个filter都有一个decide方法,返回一个int,表示DENY, NEUTRAL or ACCEPT, 来决定是否再进行下一个filter的判断。

//下面的代码仅对是否是gmilevel进行了控制,其实还可以控制的更细。比如如果是不重要的GMI_HARMLESS,
//则被filter out。
 public int decide(final LoggingEvent loggingEvent) {
        final int level = loggingEvent.getLevel().toInt();
        if (gmi && !isGMILevel(level)) {
            return -1;
        } else if (!gmi && isGMILevel(level)) {
            return -1;
        } else {
            return 1;
        }
    }
于是,我们就实现了通过自定义的level和filter来共同控制log4j是否记gmi log。

 

所以gmi log输出有三级控制:

 

1,使用在配置文件中定义要输出的所有类型的gmi message。同时在程序代码中调用gmi.log(message)方法。当调用语句中的message和配置文件中的message相吻合时,就准备输出gmi log.

 

2,而真正输出gmi log的是log4j。所以在log4j还可以实现一级控制:

 

<logger name="com.reuters.controller">
        <level value="GMI_INFORMATION"
               class="com.reuters.controller.common.logging.gmi.GMILevel"/>
        <appender-ref ref="localgmilogfile_arch"/>
</logger>

这是log4j-config.xml中的一段内容。

 

A log request of level lR on a logger with effective level lE, passes the logger-
level filter if and only if lR ≥ lE. The request is disabled (and dropped)
otherwise.

这段的意思是:如果一个要求记日志的请求的level是lR,而一个logger的level是lE。当lR ≥ lE的时候,lR的请求就不会被写入log。所以这里很重要的一点就是,越重要的事件的level级别应该越低。0是fatal,level越大的越不重要。

 

所以上面这段配置的意思是:

在com.reuters.controller下的所有类输出的gmi log,如果level级别大于等于GMI_INFORMATION,都不会被archive(<appender-ref ref="localgmilogfile_arch"/> 这个appender执行的是归档任务)。

 

3,而在appender一级还可以用filter加入控制

 

<appender name="localgmilogfile_arch" class="**.ArchiveRollingFileAppender">
        <param name="LogDirPath" value="${app.folder}/log"/>

        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%m%n"/>
        </layout>

        <filter class="com.reuters.controller.common.logging.gmi.GMIFilter">
            <param name="gmi" value="true"/>
        </filter>
    </appender>

这里可以再次过滤掉不感兴趣的log。

抱歉!评论已关闭.