4

I created my own Appender with log4net,

 public class TextBoxAppender : AppenderSkeleton
{
      ...(constructor and other stuff omitted)...

        protected override void Append(log4net.Core.LoggingEvent loggingEvent)
        {
              var msg = string.Concat(loggingEvent.RenderedMessage, "\r\n");

              _textBox.AppendText(s);

        }

}

My App.config has a PatternLayout which I would like to use,

 <appender name="TextBoxAppender" type="log4netAppender.TextBoxAppender">
      <root>
        <level value="DEBUG">
          <appender-ref ref="TextBoxAppender">
          </appender-ref>
        </level>
      </root>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{dd MMM yyyy HH:mm:ss} %level - %message%newline%exception%newline" />
      </layout>
    </appender>

loggingEvent.RenderedMessage doesn't give me the string formatted with PatternLayout.

I saw AppendSkeleton has this signature

public virtual ILayout Layout { get; set; }

but I don't want to write my own Layout, i would like to use the "standard" one which other Appenders use...

Any idea anyone? Thanks a lot

TIP: maybe this way we can access the renderer of other existing loggers?

var hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.RendererMap .....

SOLUTION

in Append(), right before RenderLoggingEvent, set the Layout, which otherwise is null.

this.Layout = new log4net.Layout.PatternLayout("%date{dd MMM yyyy HH:mm:ss} %level - %message");
string msg = base.RenderLoggingEvent(loggingEvent);
Pep
  • 152
  • 1
  • 8

2 Answers2

4

Call the base method RenderLoggingEvent to write your event according yo tour layout. For example here is the Append method in the TraceAppender

// log4net.Appender.TraceAppender
protected override void Append(LoggingEvent loggingEvent)
{
    Trace.Write(base.RenderLoggingEvent(loggingEvent), this.m_category.Format(loggingEvent));
    if (this.m_immediateFlush)
    {
        Trace.Flush();
    }
}

so in your case:

public class TextBoxAppender : AppenderSkeleton
{
    ...(constructor and other stuff omitted)...
    protected override void Append(log4net.Core.LoggingEvent loggingEvent)
    {
        // format your message in the layout, not here
        // var msg = string.Concat(loggingEvent.RenderedMessage, "\r\n");
        _textBox.AppendText(base.RenderLoggingEvent(loggingEvent));
    }
}
samy
  • 14,832
  • 2
  • 54
  • 82
  • well, although this helps me somehow, RenderLoggingEvent() throws an exception "A layout must be set", which is back to the problem I have. Do I need to code that %newline is write("\n") and so on...? – Pep Mar 23 '15 at 13:00
  • This is the first check in the RenderLoggingEvent method. Do you initialize your layout in the constructor? – samy Mar 23 '15 at 14:06
  • no, i am not initializing any layout. I want to re-use a layout from another appender. Cause i don't want to do something special, just the typical PatternLayout with %date %level %exception ... – Pep Mar 23 '15 at 16:19
  • 1
    Could you try assigning the Layout to new Layout in the constructor? Apparently that is recommended for other appenders – samy Mar 24 '15 at 07:28
0

You should use textBox.BeginInvoke instead of textBox.Invoke or textBox.AppendText for threadsafe.

zony
  • 1
  • 1