簡體   English   中英

Log4j 配置過濾日志到多個文件

[英]Log4j config to filter logs to multiple files

我正在嘗試在 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

我最終為控制台和日志創建了自定義過濾器,以根據 MDC 映射值轉移日志流,這解決了過濾問題。 這個想法來自這篇文章的@KC Baltz。

我的 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;
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM