[英]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.