views:

38

answers:

3

Hi! I have appender like this.

<appender name="Action.FileAppender" class="ch.qos.logback.core.FileAppender">
<file>logs\\${date}\\${thread}.log</file>
<encoder>
<pattern>%level - %msg%n</pattern>
</encoder>
</appender>

And i want to ${date} and ${thread} be current date and current thread name. How i can do it?

A: 

Do you mean you want to set the output filename dynamically during runtime? AFAIK it is not possible straight via configuration. You have two workarounds:

  • set the output filename dynamically from code, or
  • use a Mapped Diagnostic Context, to prepend your log messages with thread-specific data within the same log file.

The first way would be rather tedious and wasteful, since you would need instance-specific loggers and appenders for classes where different instances can be called from different threads. And even then, what if the same object is shared between multiple threads?

The second one is more natural and simple. Moreover, with a bit of postprocessing using e.g. a simple shell script, you can even filter out logs belonging to different threads into distinct log files.

Péter Török
Thanks! Can you help me with example of the first way?
sfireman
@sfireman, sorry, I can't. It's apparently different from Log4J in this respect. [The manual](http://logback.qos.ch/manual/configuration.html) mentions that it is possible, but gives no examples.
Péter Török
A: 

SiftingAppender might be what you need. It is designed to separate logging events according to "discriminators", which would be date and thread name in your case.

dogbane
Possible this is a way, but this way use MDC. How will work MDC in multithreaded application?
sfireman
A: 

Hmm... I write this code in Scala.

  class ThreadedFileAppender[E] extends FileAppender[E]{
     private val appenders = Map[String,FileAppender[E]]()

     override def start = {
      started=true
     }

     override def subAppend(event:E) = {
      val key = Thread.currentThread.getName
      (if (appenders.isDefinedAt(key))
       appenders(key)
      else {
       import java.text.SimpleDateFormat, java.util.Calendar
       val appender = new FileAppender[E]
       appender.setAppend(append)
       appender.setContext(context)
       appender.setEncoder(getEncoder)
       appender.setFile(rawFileProperty
        .replaceAll("%thread",Thread.currentThread.getName)
        .replaceAll("%date",(new SimpleDateFormat("yyyy.MM.dd")).format(Calendar.getInstance.getTime)))
       appender.setName(name)
       appender.setPrudent(isPrudent)
       appender.start
       appenders(key) = appender
       appender
      }).doAppend(event)
     }
    }

But!... this don't work as expected :( LogBack writes in separate files, but messages are "randomly" mixed :( Where is my mistake?

sfireman