2

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.  

}

}

My log4j configuration:

<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!

user755806
  • 6,565
  • 27
  • 106
  • 153

2 Answers2

2

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.

Mike Monette
  • 630
  • 6
  • 6
0

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);
    }
    ...
  }
dcernahoschi
  • 14,968
  • 5
  • 37
  • 59
  • Thanks for your answer. If i want to continue the async thread execution even if main thread exits, what should i do? Please help me... – user755806 Oct 18 '13 at 07:35
  • This is really not possible. When the java main thread exists all its allocated resources are cleaned up. You should, before exiting the main thread, call `appender.close()` and main thread will not exit until all the logging is completed by the logging thread. – dcernahoschi Oct 18 '13 at 07:40
  • Thanks for ur reply. If main thread waits till logger completes its execution then do i really need to use AsyncAppender? Because it will become synchronous call right? Please correct me if my understanding is wrong..Thanks! – user755806 Oct 18 '13 at 07:42
  • It becomes synchronous only upon exiting. It depends on your application if it worth or not to use an `AsyncAppender`. If its a shortly lived script like program it might not. But if its a web application that runs continuously under heavy load it might be better for responsiveness to log asynchronously. – dcernahoschi Oct 18 '13 at 07:51
  • Please correct me if i am wrong...If we use AsyncAppender then both exeucting the main logic and logging logic will be called by two separate threads so performance is faster. If i dont use AsyncAppender then only main thread has to process both the logics right? Also, could you please tell me where to close the appender in my MyAppender class? Thanks! – user755806 Oct 18 '13 at 07:58
  • Yes, it's correct. The client code that use your appender should call `close` upon exiting the main thread. – dcernahoschi Oct 18 '13 at 08:00
  • Please suggest me where to call close method in MyAppender class? Also, my application will be deployed on tomcat. In that case do i still need to call close method ?Thanks! – user755806 Oct 18 '13 at 08:02
  • Don't override `close()` in `MyAppender`. You need to call `close` when shutting down tomcat if you don't want to lose log messages. You can do it in a `ServletContextListener`: http://stackoverflow.com/questions/1549924/shutdown-hook-for-java-web-application Thanks. – dcernahoschi Oct 18 '13 at 08:12
  • If my application is running on tomcat then logging thread completes its execution even if parent thread exits right? I mean in appserver environment i need not call close method right because i am not going to shut down tomcat ..Thanks! – user755806 Oct 18 '13 at 08:15