7

My application uses several threads with well-defined names (i.e. not a thread pool with 'anonymous' threads). Right now, all of these threads send their log messages to one file - and although the thread ID is part of the log line, this makes it very hard to analyse the application behaviour. Thus, I want each thread to log into its own log file.

It seems that Log4Net offers no built-in option to choose an appender based on the thread. Does anyone know of a solution to this? Note that I obviously would prefer to not switch to another logging library.

Jens Bannmann
  • 4,845
  • 5
  • 49
  • 76
  • What did you end up doing with this? I have the exact same requirement except the number of threads and the names of the threads are not known or set until runtime. – goku_da_master Mar 08 '12 at 17:49
  • I didn't solve the problem because I got a new job. Anyway, Peter's solution would have worked for me, and I imagine creating the appender config via the API works for you. – Jens Bannmann Mar 10 '12 at 07:41
  • If anyone else requires a simple solution to this see the answer here http://stackoverflow.com/questions/6956064/logging-to-an-individual-log-file-for-each-individual-thread – Oli B Jun 03 '14 at 13:34

1 Answers1

4

The log4net way of "choosing" appenders is through filtering. In your scenario you would need a way of setting up a number of appenders, each representing a well-defined thread, and have filters in each appender passing through messages only from their respective thread.

Since thread ID is not deterministic you will need something else to do your filtering on. I assume you are controlling the creation of these threads yourself and suggests that each thread registers an identifier in a property in the ThreadContext. Next you can then use the PropertyFilter to filter messages based on the identifiers.

Here's a sample config setup that have two appenders, each appending messages where the current value of property threadId matches a given identifier.

<appender name="x">
    <filter type="log4net.Filter.Property">
        <key value="threadId" />
        <stringToMatch value="threadX" />
    </filter>
    <filter type="log4net.Filter.DenyAllFilter" />
    ...
</appender>

<appender name="y">
    <filter type="log4net.Filter.Property">
        <key value="threadId" />
        <stringToMatch value="threadY" />
    </filter>
    <filter type="log4net.Filter.DenyAllFilter" />
    ...
</appender>

<root>
    <appender-ref name="x" />
    <appender-ref name="y" />
</root>
Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131
  • 1
    How would you do this if the number of threads and their names were not know until runtime? – goku_da_master Mar 08 '12 at 17:48
  • 2
    @goku_da_master you can build up the appender configuration in code, that could be one approach, at least if you are in control of thread creation. If not, I would say the best option is to log to a common source (e.g. a database) that can more easily be queried based on the thread id. – Peter Lillevold Mar 09 '12 at 08:10