logginglog4netlog4net-appender

How to log the level as a single letter in log4net?


Is there a way to change this configuration:

<appender name="appender" type="log4net.Appender.RollingFileAppender">
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] [%-5level] %logger - %message%newline" />
  </layout>
</appender>

... to log the log-level as a single letter like this:

DEBUG -> D
INFO  -> I
WARN  -> W
ERROR -> E
FATAL -> F

I tried %-1level but the number only controlls the number of characters to which to fill up with spaces. ([%-5level] means [INFO ] instead of [INFO]) So [%-1level] gave me [INFO] instead of the expected [I].

My ideas so far:

Variante 1

I could configure a separate appender for each level where the level letter is set fixed for each level, all logging to the same file:

<appender name="info-appender" type="log4net.Appender.RollingFileAppender">
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
  <file value="logfile.log" />
  <filter type="log4net.Filter.LevelMatchFilter">
    <levelToMatch value="INFO" />
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] [I] %logger - %message%newline" />
  </layout>
</appender>
<appender name="warn-appender" type="log4net.Appender.RollingFileAppender">
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
  <file value="logfile.log" />
  <filter type="log4net.Filter.LevelMatchFilter">
    <levelToMatch value="WARN" />
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] [W] %logger - %message%newline" />
  </layout>
</appender>
.
.
<root>
  <level value="ALL" />
  <appender-ref ref="debug-appender" />
  <appender-ref ref="info-appender" />
  <appender-ref ref="warn-appender" />
  <appender-ref ref="error-appender" />
  <appender-ref ref="fatal-appender" />
</root>

Variante 2

I guess one could extend the log4net.Appender.RollingFileAppender and override the render method or if possible some other internal method which renders the level. (have not checked if thats really possible)

Question:

Is there an easier way to achive this? (just with configuration)


Solution

  • Simplest solution, using the truncation format: %.1level instead of %-5level should truncate the output, as shown here

    Alas, I didn't have time to test it live. Please see my initial answer below if it doesn't work.

    EDIT: I didn't read the description of truncation correctly:

    If the data item is longer than the maximum field, then the extra characters are removed from the beginning of the data item and not from the end

    which doesn't match what you need. Please have a look at writing a custom PatternLayoutConverter


    Every pattern element is parsed based on a collection of PatternLayoutConverter that are used to process the pattern desired by the user. Your best bet would be to create a specific PatternLayoutConverter that would log the level formatted as you wish. Here is an example where I explain the same principle to use a specific datetime format.

    In your case it could be as simple as this:

    public class MyLevelPatternConverter : PatternLayoutConverter
    {
        protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            writer.Write(loggingEvent.Level.DisplayName.Substring(0, 1));
        }
    }