Log4j配置用于将日志过滤到多个文件

uidvcgyl  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(137)

我尝试在JDK1.6应用程序上使用Log4j 1.2.17,根据日志中的模式将特定日志路由到不同的文件。我发现在这里的帖子中提到的解决方案,这里说在log4j xml中完成的以下配置应该与MDC上下文沿着工作,但由于某种原因,它们对过滤器没有影响,日志最终被路由到控制台和文件。
我的java代码看起来如下:

@RequestMapping(value = "/fetchBookById",  method = RequestMethod.GET, produces="application/json")
public @ResponseBody Map<String,? extends Object> bookApi(ParamDTO params) throws InterruptedException {

    log.info("SimpleBookController.bookApi: THIS IS A COMMON LOG");
     Map<String,Object> rxdMap = null;
    try{
        //This below will put either ABCD or EFGH etc
        MDC.put("COMPANYNAME", companyMap.get(params.getCompanyOwnerId()));

        log.info("SimpleBookController.bookApi: THis is test with routing");
        log.info("SimpleBookController.bookApi: Payload: "+params.toString());

        //do something here
        log.info("SimpleBookController.bookApi API completed for :"+params.getCompanyOwnerId());

    } finally {
        MDC.clear();
    }
     return rxdMap;
}

Log4j.xml:

<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] COMPANYNAME:%X{COMPANYNAME} %-5p - %m%n" />
    </layout>
    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="COMPANYNAME:"/>
        <param name="AcceptOnMatch" value="false"/>
    </filter>
</appender>
<appender name="file" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="./logs/company.log" />
    <param name="Append" value="true" />
    <param name="ImmediateFlush" value="true" />
    <param name="MaxFileSize" value="10MB" />

    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] COMPANYNAME:%X{COMPANYNAME} %-5p - %m%n" />
    </layout>
    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="COMPANYNAME:ABCD"/>
        <param name="AcceptOnMatch" value="true"/>
    </filter>
    <filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>
 <root>
    <level value="info" />
    <appender-ref ref="file" />
    <appender-ref ref="console" />
</root>

在上面的配置中,我试图将没有“COMPANYNAME:“字符串的日志路由到控制台,而具有“COMPANYNAME:ABCD”字符串的日志应该路由到特定的文件。但是控制台和文件Appender最终都拥有所有的日志,而不考虑字符串模式。如果有人能给我指出正确的方向,我将不胜感激。
示例日志:

2022-07-11 21:29:44 [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] COMPANYNAME: INFO  - FrameworkServlet 'TestJDK6Logging': initialization completed in 423 ms
2022-07-11 21:29:56 [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] COMPANYNAME: INFO  - SimpleBookController.bookApi: THIS IS A COMMON LOG
2022-07-11 21:29:56 [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] COMPANYNAME:ABCD INFO  - SimpleBookController.bookApi: THis is test with routing
2022-07-11 21:29:56 [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] COMPANYNAME:ABCD INFO  - SimpleBookController.bookApi: Payload: ParamDTO [identifier=sdfdf, bookId=1, companyOwnerId=4]
2022-07-11 21:30:01 [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] COMPANYNAME:ABCD INFO  - SimpleBookController.bookApi API completed for :4
rxztt3cl

rxztt3cl1#

最后我创建了一个自定义的控制台和日志过滤器,根据MDCMap值来转移日志流,这样就解决了过滤问题。
我的log4j.xml如下所示:

<appender name="console" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
        </layout>

        <!-- This is custom console filter, modify decide() function accordingly -->
        <filter class="com.lumn.logtest.web.common.Log4JConsoleFilter">
            <param name="keyToMatch" value="COMPANYNAME" />
            <param name="valueToMatch" value="" />
            <param name="acceptOnMatch" value="false" />
        </filter>
    </appender>

    <appender name="LUMN" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="./logs/lumen.log" />
        <param name="Append" value="true" />
        <param name="ImmediateFlush" value="true" />
        <param name="MaxFileSize" value="10MB" />

        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
        </layout>

        <!-- This is custom company filter, modify decide() function accordingly -->
        <filter class="com.lumn.logtest.web.common.Log4JCompanyFilter">
            <param name="keyToMatch" value="COMPANYNAME" />
            <param name="valueToMatch" value="ABCD" />
            <param name="acceptOnMatch" value="true" />
        </filter>
    </appender>

我的自定义过滤器Log4JConsoleFilter和Log4JCompanyFilter如下所示:

public class Log4JConsoleFilter extends Filter {

private String keyToMatch;
private String valueToMatch;
private boolean acceptOnMatch = true;

@Override
public int decide(LoggingEvent event) {

    //Modify this condition based on the need, there is room for improvement to reduce number of conditions.
    if (keyToMatch == null || valueToMatch == null)
        return Filter.NEUTRAL;
    else {
        if(event.getMDC(keyToMatch) == null)
            return Filter.NEUTRAL;
        else{ 
            //MDC has value
            return acceptOnMatch ? Filter.ACCEPT: Filter.DENY;
        }
    }
}
public String getKeyToMatch() {
    return keyToMatch;
}

public void setKeyToMatch(String keyToMatch) {
    this.keyToMatch = keyToMatch;
}

public String getValueToMatch() {
    return valueToMatch;
}

public void setValueToMatch(String valueToMatch) {
    this.valueToMatch = valueToMatch;
}

public boolean isAcceptOnMatch() {
    return acceptOnMatch;
}

public void setAcceptOnMatch(boolean acceptOnMatch) {
    this.acceptOnMatch = acceptOnMatch;
}

}

public class Log4JCompanyFilter extends Filter {

private String keyToMatch;
private String valueToMatch;
private boolean acceptOnMatch = true;

@Override
public int decide(LoggingEvent event) {  
    if (keyToMatch == null || valueToMatch == null)
        return Filter.DENY;
    else {
        if (valueToMatch.equals(event.getMDC(keyToMatch)))
            return acceptOnMatch ? Filter.ACCEPT: Filter.DENY;
        else
            return Filter.DENY;             
    }
}

public String getKeyToMatch() {
    return keyToMatch;
}

public void setKeyToMatch(String keyToMatch) {
    this.keyToMatch = keyToMatch;
}

public String getValueToMatch() {
    return valueToMatch;
}

public void setValueToMatch(String valueToMatch) {
    this.valueToMatch = valueToMatch;
}

public boolean isAcceptOnMatch() {
    return acceptOnMatch;
}

public void setAcceptOnMatch(boolean acceptOnMatch) {
    this.acceptOnMatch = acceptOnMatch;
}

}

相关问题