Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

log4net - Custom property logging

I got use the following class to print out messages using log4net:

public class Message
{
    public String Text { get; set; }
    public int Id { get; set; }
    public override string ToString()
    {
        return Text;
    }
}

I use Logger.Info(MessageInstance), so log4net just invokes the ToString method and prints out the message. I would like to also log the Id property of the message object, but I cannot figure out how to achive this.

My conversion pattern looks similiar to this:

<conversionPattern value="%date %-5level %message%newline" />

I tried adding %message{Id} but that would just print the whole message twice.

Any Suggestions?

like image 677
Jaster Avatar asked Apr 04 '13 09:04

Jaster


2 Answers

I just wrote a custom pattern, which allows to read properies of the message object.

public class ReflectionReader : PatternLayoutConverter
{
    public ReflectionReader()
    {
        _getValue = GetValueFirstTime;
    }

    protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
    {
        writer.Write(_getValue(loggingEvent.MessageObject));
    }

    private Func<object, String> _getValue;
    private string GetValueFirstTime(object source)
    {
        _targetProperty = source.GetType().GetProperty(Option);
        if (_targetProperty == null)
        {
            _getValue = x => "<NULL>";
        }
        else
        {
            _getValue = x => String.Format("{0}", _targetProperty.GetValue(x, null));
        }
        return _getValue(source);
    }

    private PropertyInfo _targetProperty;
}

Combine with this:

public class ReflectionLayoutPattern : PatternLayout
{
    public ReflectionLayoutPattern()
    {
        this.AddConverter("item", typeof(ReflectionReader));
    }
}

Config looks like this:

<layout type="MyAssembly.MyNamespace.ReflectionLayoutPattern, MyAssembly">
  <conversionPattern value="[%item{Id}]&#9;%message%newline" />
</layout>
like image 72
Jaster Avatar answered Nov 14 '22 19:11

Jaster


You can use a CustomXmlLayout class that derives from XmlLayoutBase and override the FormatXml method. This method takes a LoggingEvent object as parameter which will contain the MessageObject that was passed to the log method.

public class SpecialXmlLayout : XmlLayoutBase
{
    protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent)
    {
        Message message = loggingEvent.MessageObject as Message;
        writer.WriteStartElement("LoggingEvent");
        writer.WriteElementString("Message", GetMessage(message));
        // ... write other things
        writer.WriteEndElement();
    }
}

Inside the GetMessaage method create your string as you would like from the message.

Then use this layout class in log4net config:

<log4net>
    <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
      <applicationName value="My Application" />
      <layout type="Namespace.SpecialXmlLayout">
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="ERROR" />
        <param name="LevelMax" value="FATAL" />
      </filter>
    </appender>
</log4net>

This is the idea. For more specific details you will have to consult the log4Net SDK documentation.

like image 21
softveda Avatar answered Nov 14 '22 20:11

softveda