Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

log4net - Multiple colors in one line

Tags:

c#

log4net

I would like to do some info logging with log4net on console and use multiple colors in each line. This is my current simplified configuration:

...
<appender name="ConsoleDebug" type="log4net.Appender.ColoredConsoleAppender">
  <filter type="log4net.Filter.LevelRangeFilter">
    <levelMin value="INFO" />
  </filter>
  <mapping>
    <level value="INFO" />
    <foreColor value="Green, HighIntensity" />
  </mapping>
  ...
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%logger{1} %message%newline" />
  </layout>
</appender>
...

This outputs all my logging messages as green text. Is it possible to output %logger as white text and %message as green?

like image 975
Michael Hilus Avatar asked Aug 20 '14 09:08

Michael Hilus


1 Answers

I thought for a moment that ANSI escape codes could have worked but apparently it is not possible anymore in latest OSes. Any other solution I see would have you do some non trivial amount of work.

To handle switching colors in the layout of your message you could do the following:

  • write a custom PatternLayoutConverter that lets you declare what color you want. Change the colors through the Console.ForegroundColor and Console.BackgroundColor properties.
  • write a custom PatternLayout that would add the layout converter above to its list of converters.
  • write a custom Appender that does not process the pattern layout before writing it. Rather write the layout in chunks, processing each chunk then writing it to the output. This preserve the color switching capabilities of your layout converter.

That's a lot of code to write to get custom colors "done right" (ie your layout is independent from the appender it's working with).


There is a way to cheat a bit, if you consider that only a Console appender uses your layout:

  • create a custom appender inheriting from a Console appender and override the Append method.
  • In the Append method split along markers that tell you what color you want and process them chunk by chunk to get the color swaps you want.

This could be a quick and dirty solution but the layout will be only usable with this appender. If you need to switch appenders you would have to override it again. Here is an example of such an appender:

public class ConsoleAppenderWithColorSwitching : ConsoleAppender
{
    // forfeits the auto switch from Console.Error to Console.Out 
    // of the original appender :/
    protected override void Append(LoggingEvent loggingEvent)
    {
        var regex = new Regex(@"(\|\w+\|)");
        var renderedLayout = base.RenderLoggingEvent(loggingEvent);
        var chunks = regex.Split(renderedLayout);
        foreach (var chunk in chunks)
        {
            if (chunk.StartsWith("|") && chunk.EndsWith("|"))
            {
                var consoleColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), chunk.Substring(1, chunk.Length - 2));
                Console.ForegroundColor = consoleColor;
            }
            else
            {
                Console.Write(chunk);
            }
        }
    }
}

This lets you change the foreground color in the layout with the following syntax: |Green| %logger{1} |Red|%message%newline. This is really a proof of concept but feel free to experiment with it...


All in all I wouldn't recommend you go down this path. It is definitely possible but it may be more work than you are comfortable investing in dynamic color switches.

like image 64
samy Avatar answered Sep 27 '22 19:09

samy