log4j:ERROR Attempted to append to closed appender named [*]
8785 단어 appender
During system running, sometimes we can see the error message from log4j log:
log4j:ERROR Attempted to append to closed appender named [*].
Here I would like to talk about one use case which could cause this problem.
Most of the components in our project could use log4j, and some of them could have duplicated log4j configuration file:
Here is a log4j.xml demo for my test:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- Main log file for general output from SSP server. -->
<appender name="SYSTEM"
class="com.gemalto.util.log4j.DailyMaxRollingFileAppender">
<param name="File" value="logs/logFromlog4jXMLAppender.log" />
<param name="Append" value="true" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="maxNumberOfDays" value="7" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [GTO] [%c] %X{MSISDN} %X{IMEI} %m%n" />
</layout>
</appender>
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<param name="Threshold" value="INFO" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" />
</layout>
</appender>
<category name="com.test" additivity="true">
<priority value="DEBUG" />
<appender-ref ref="SYSTEM" />
</category>
<root>
<priority value="INFO" />
<appender-ref ref="SYSTEM" />
<appender-ref ref="CONSOLE" />
</root>
</log4j:configuration>
Also, there is a log4j.properties in same location as log4j.xml:
log4j.rootCategory=DEBUG, stdout
log4j.logger.com=DEBUG, smsdriver
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.smsdriver=com.gemalto.util.log4j.DailyMaxRollingFileAppender
log4j.appender.smsdriver.file=logs/logFromlog4jPropertiesAppender.log
log4j.appender.smsdriver.append=true
log4j.appender.smsdriver.layout=org.apache.log4j.PatternLayout
log4j.appender.smsdriver.layout.ConversionPattern=%d %p [%c] - <%m> %F %n
During our test, we will load log4j.xml first to configure Logger Hierarchy, and then load log4j.properties to configure Logger Hierarchy. We will see what happen according to logs.
Here is the test code on log4j configuration:
@Test
public void testlog4jConfigurator() throws Exception {
System.setProperty("log4j.debug", "true");
Logger logger = org.apache.log4j.Logger
.getLogger("com.DOMConfigurator");
logger.info("Logger before DOMConfigurator."); //#1
System.setProperty("log4j.defaultInitOverride", "true");
URL log4jXml = TempTest.class.getResource("/log4j.xml");
URL log4jProperties = TempTest.class.getResource("/log4j.properties");
DOMConfigurator.configure(log4jXml);
Logger loggerDOMConfigurator = org.apache.log4j.Logger
.getLogger("com.DOMConfigurator");
loggerDOMConfigurator.info("Logger loggerDOMConfigurator.");//#2
// assertEquals(logger, loggerDOMConfigurator);
Logger loggerDOMConfigurator2 = org.apache.log4j.Logger
.getLogger("com.test.2");
Logger loggerDOMConfigurator3 = org.apache.log4j.Logger
.getLogger("com.test.3");
PropertyConfigurator.configureAndWatch(getFilePath(log4jProperties));
loggerDOMConfigurator.info("Logger loggerPropertyConfigurator."); //#3
// assertEquals(loggerPropertyConfigurator, loggerDOMConfigurator);
loggerDOMConfigurator2.info("Logger loggerDOMConfigurator2."); //#4
loggerDOMConfigurator3.info("Logger loggerDOMConfigurator3."); //#5
}
By default, org.apache.log4j.LogManager will load "log4j.xml", so we can see #1 and #2 output into file: logs/logFromlog4jXMLAppender.log:
2011-12-22 10:17:52,669 INFO [GTO] [com.DOMConfigurator] Logger before DOMConfigurator.
2011-12-22 10:17:52,669 INFO [GTO] [com.DOMConfigurator] Logger loggerDOMConfigurator.
#3 will output into file: logs/logFromlog4jPropertiesAppender.log:
2011-12-22 10:17:52,684 INFO [com.DOMConfigurator] -
#4 and #5 will be log into file logs/logFromlog4jPropertiesAppender.log because we configure a Category: log4j.logger.com. BUT we cannot see any log in logs/logFromlog4jXMLAppender.log. AND we will see the following errors in console:
log4j:ERROR Attempted to append to closed appender named [SYSTEM].
log4j:ERROR Attempted to append to closed appender named [SYSTEM].
Why this situation comes? See
log4j source code analyze. Here I will list some solutions to solve this problem.
Solutions
Here I would like to list some workaround.
1: Remove APPENDER ref from root category
We can remove the appender-ref to "SYSTEM"in log4j.xml/root like following:
<category name="com.test" additivity="true">
<priority value="DEBUG" />
<appender-ref ref="SYSTEM" />
</category>
<root>
<priority value="INFO" />
<!--appender-ref ref="SYSTEM" /-->
<appender-ref ref="DMCONSOLE" />
</root>
There won't be any error message refer to appender closed. In this case, we can see #4 and #5 logs in both files.
(Please be aware of that #2 won't be logged in this case.)
2: Remvoe APPENDER ref in specific Category
We can also remove the appender-ref to "SYSTEM"in log4j.xml/Category/com.test like following:
<category name="com.test" additivity="true">
<priority value="DEBUG" />
<!--appender-ref ref="SYSTEM" /-->
</category>
<root>
<priority value="INFO" />
<appender-ref ref="SYSTEM" />
<appender-ref ref="DMCONSOLE" />
</root>
In this case, there also won't be any error message refer to "appender closed". But #4 and #5 will only be logged in file: logs/logFromlog4jPropertiesAppender.log.
Conclusion
As descript in log4j , there will be only one Logger instance with specific name. Log4j allows logging requests to print to multiple destinations. In log4j speak, an output destination is called an appender. Currently, appenders exist for the console, files, GUI components, remote socket servers, JMS, NT Event Loggers, and remote UNIX Syslog daemons. It is also possible to log asynchronously.
More than one appender can be attached to a logger.
The addAppender method adds an appender to a given logger. Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy.
As we can see, Appender related to logger could be modified during second Configurator. So the error comes.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
log4net 사용자 정의 Appender최근에 로그를 기록하고 서버에 데이터를 저장하기 위해log4net을 사용해야 한다는 요구가 있습니다.처음에는 윈도우즈 서비스를 써서 정기적으로 로그를 올릴 계획이다. 나중에 일부 장면에서 적응하지 못하기 때문에 메모...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.