Reputation: 6815
I am using log4j AsyncAppender
. i wrote my own appender to customise the logger as below.
public class MyAppender extends AppenderSkeleton {
@Override
public void close() {
}
@Override
public boolean requiresLayout() {
return false;
}
@Override
protected void append(LoggingEvent event) {
//Here am doing some logic which will connect database and fetch some records.
}
}
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!-- Appenders -->
<appender name="stdout" class="com.sample.MyAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c] - %m%n"/>
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<param name="BufferSize" value="500"/>
<appender-ref ref="stdout"/>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="ASYNC" />
</root>
</log4j:configuration>
Now everything works fine. Im MyAppender
i will fire a Select
query and fetch some details from the table and send those details using java mail API. As i am using AsyncAppender
, it does not block existing running thread and the MyAppender logic is executed Asynchronously.My question is if the main thread completes its execution before MyAppender
logic gets completed then is there any guarantee that the logic in MyAppender
will be completed even if main thread completes its execution?
Thanks!
Upvotes: 2
Views: 5807
Reputation: 640
It's been a year, but I'll answer for the benefit of others after me. The proper way to safely close all appenders and ensure that your JVM doesn't shut down before logging is complete is to call LogManager.shutdown();
. I haven't confirmed, but this is apparently not necessary in Log4j 2, since it registers a shutdown hook with the JVM automatically.
Upvotes: 2
Reputation: 15230
Just thrown a quick look at the AsyncAppender
class source code. It seems that the thread that asynchronously process the logging events is set as a daemon thread. So when the main thread exits the logging thread exits too, possibly with unhandled logging requests in the queue.
There is also a comment above the setDaemon(true)
call: It is the user's responsibility to close appenders before exiting. (meaning that upon closing the logger thread will complete its queued logging events, see the close()
method code snippet)
public AsyncAppender() {
appenders = new AppenderAttachableImpl();
aai = appenders;
dispatcher = new Thread(new Dispatcher(this, buffer, discardMap, appenders));
// It is the user's responsibility to close appenders before
// exiting.
dispatcher.setDaemon(true);
// set the dispatcher priority to lowest possible value
// dispatcher.setPriority(Thread.MIN_PRIORITY);
dispatcher.setName("AsyncAppender-Dispatcher-" + dispatcher.getName());
dispatcher.start();
}
//Close this AsyncAppender by interrupting the dispatcher
//thread which will process all pending events before exiting.
public void close() {
...
try {
dispatcher.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
org.apache.log4j.helpers.LogLog.error(
"Got an InterruptedException while waiting for the "
+ "dispatcher to finish.", e);
}
...
}
Upvotes: 0