Search code examples
c#.netlogginglog4netlog4net-configuration

How to add processid to log4net layout?


I'm gonna use log4net in my wpf application. And I need messages in my log looks like this:

11/8/2018 10:49:38 AM   13 (5368)       properties disabled.

where 13 is processId which writes this message. So it's pretty easy. But unfortunately I can't achieve this. So I just need an appropriate pattern layout for my log4net logger.

I've found the following message in faq section of log4net official site:

The following example sets the file name for a FileAppender to include the current process id by specifying the %processid pattern in the File property.

<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
    <file type="log4net.Util.PatternString" value="log-file-[%processid].txt" />
    <layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
</appender>

So and it works but only for file name not for layout in my log file. And I need to put this %processid into my layout. And my current layout is:

<layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date{dd/MM/yyyy HH:mm:ss,fff tt} %processid (%thread) - %message%newline" />
</layout>

And my log just writes processid string to my log file.

22/11/2018 16:21:51,863 PM processid (1) - Exiting application.

I've also found a SO answer. And it works. But %processid property is initialized only once during startup. And in my app the writing proсes is often changes. So this solution is not suitable for me. And I guess it could be achieved by default log4net layout settings.

The other option is using type="log4net.Util.PatternString" as a type of my conversionPattern. But it is not suitable as well(if I use this type - type="log4net.Util.PatternString" - in conversionPattern then %threadId, %level and even %message will be printed as string constants).

23/11/2018 16:22:52,456 PM 31560 [thread] level - message

But I need both %threadId and %processid in log.


Solution

  • You can implement a custom PatternLayoutConverter which outputs the process Id.
    Doing so, you don't have to have to set and track the Id of the running process.

    namespace PFX
    {
        class ProcessIdPatternLayoutConverter : PatternLayoutConverter
        {
            protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
            {
                Int32 processId = Process.GetCurrentProcess().Id;
                writer.Write(processId);
            }
        }
    }
    

    You then reference this PatternLayoutConverterin your Log4netconfig via its fully qualified assembly name as below.

    <layout type="log4net.Layout.PatternLayout">                        
        <converter>
            <name value="processid" />
            <type value="PFX.ProcessIdPatternLayoutConverter, PFX.Lib" />
        </converter>            
        <conversionPattern value="%date{dd/MM/yyyy HH:mm:ss,fff tt} %processid (%thread) - %message%newline" />
    </layout>