1

For some troubleshooting reasons I'd like to log all past messages (for example last 20) on level from TRACE if there occurred an exception, but if code works well I'd like to log from INFO level to keep clear my log files from unnecessary log messages.

For example:

public void m( String arg ){
    log.trace( "arg value: " + arg );
    log.info( "Hi Bob!" );
    try{
        //code
    }catch( Exception e ){
         log.error( "error msg", e );
    }
}

I'd like to get in log something like:

*INFO* Hi Bob!

But if the error is occurred I'd like to get in log something like:

*TRACE* arg value: test
*INFO* Hi Bob!
*ERROR* error msg //and stacktrace

In other words I'd like to have a log message buffer that will cleared from low level messages if code runs well and pushed in log files in case of error. Can java logging framework do this from the box?

Yura
  • 1,733
  • 1
  • 20
  • 19

3 Answers3

2

I doubt you can do such thing with log4j, unfortunately. I think you can do two other things:

  1. Write the info you need in the error message (not always practical)

    log.error( "error with arg value " + arg, e );
    
  2. Configure log4j so that it prints up to level INFO in the console or your log file and print up to level TRACE in another file, called something "detailed.log", that you would look into only in case of an error. For details how to do that see this question.

Community
  • 1
  • 1
Cyrille Ka
  • 15,328
  • 5
  • 38
  • 58
1

I am guessing that there is no standard configuration for that and I would look over a custom appender overriding your favorite one with a sort of buffer and appending only elements in case of error.

In my opinion you might be better of logging an detailed error message than trying to log past things.

benzonico
  • 10,635
  • 5
  • 42
  • 50
1

UPDATE It is incorrect to say there is no way to do this. Look at log4j MappedDiagnosticContext, this seems a good instruction


There is no way to do this.

Consider that the current trace level is INFO and the code makes the following logging calls:

  1. TRACE
  2. INFO
  3. ERROR

At #1 there is no way for to know that the code is going to end up in ERROR downstream, so the only solution is to buffer it. Then at #2 the logging needs to occur because current level is INFO.

When at #3 the error occurs, the INFO log at #2 has already occurred. There is no way to roll that back and insert the #1 trace before #2.

Not logging at #2 and waiting for method/function execution to complete is generally a bad idea. It might work for you, but you may end up missing log lines and that is bad.

Your best option is to store in memory -- say in a thread local -- additional info to log in case of error. So the output would be:

10:15 INFO
10:20 ERROR
      10.10: TRACE

A big overhead of logging is to construct those strings to write from objects. So instead of buffering actual strings, you need to put some sayCallable or some such. And it all becomes pretty messy.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133