views:

70

answers:

2

Here is the problem: I want to add row indexer (row number or iterator) to each row in log file. I don't need it to be unique for the whole log file, but only for the "application session" (i. e. each time Win32 application started, we begin our countdown: 1, 2, 3 and so on)

Is where any built-in way (conversionpattern tag syntax) or some custom extension?

Thanks a lot!

A: 

i'd do the following:

First, define some logging helper

public class WebLoggingHelper
{
    public static CurrentLineHelper CurrentLine = new CurrentLineHelper();

    public class CurrentLineHelper
    {
        private long line = 1;

        public override string ToString()
        {
            string result = this.line.ToString();
            this.line += 1;
            return result;
        }
    }
}

Then wire the logging helper to the log4net properties in the place where you initialize your logger

public void ConfigureLog4Net()
{
    XmlConfigurator.Configure();
    GlobalContext.Properties["CurrentLine"] = WebLoggingHelper.CurrentLine;
}

Profit! or more seriously, now you can user the property directly in your log4net formatting by using %property{CurrentLine}

<conversionPattern value="%property{CurrentLine}- %date - %identity - %property{current_request_id} - %m%n"/>

I use this method to log lots of stuff that needs to be calculated and application specific. You may want to add some logic to use the long number for very long periods, and some formatting to the line numbering (padding with zeroes on the left for example, etc)...

Good logging!


EDIT: The solution i present here must be used only for one logging file at a time. I you use this pattern in many log files, you'd have a unique line number in each if you add protection against race conditions (just add a synclock in the tostring method of the helper object) To manage multiple loggers with line number, another method should be used

samy
+3  A: 

My solution only works for one appender only and the counter will be reset every time you start the application.

You could use a pattern converter:

public sealed class LineCounterPatternConverter : PatternLayoutConverter
{       
    private static int counter = 0;

    protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
    {
        LineCounterPatternConverter.counter++;
        writer.Write(LineCounterPatternConverter.counter.ToString());
    }
}

then you configure it like this:

<layout type="log4net.Layout.PatternLayout">
  <conversionPattern value="[%LC] %message%newline" />
  <converter>
    <name value="LC" />
    <type value="YourNameSpace.LineCounterPatternConverter" />
  </converter>
</layout>

The [] brackets are of course optional. You could also do something like this %6LC which would pad the line with spaces so that you get the message aligned nicely.

Stefan Egli