Is it possible to create a log4net custom PatternLayoutConverter that allows an "index" value to be configured? I know about the "property" conversion string that allows you to write code like this:
ThreadContext.Properties["ID"] = yourID;
And specify like this:
%property{ID}
That the value should be included in the output.
What if the values I want to log are in some other "dictionary"? I suppose that I could write some logic to copy those values from the dictionary to one of the log4net contexts and then just use the built in %property
token. What if I want log4net to log the values directly from my own "dictionary" based on an index value specified in the config file?
Can I write my own PatternLayoutConverter that would allow me to configure something like this:
%myproperty{ID}
And then pull the corresponding "ID" value from my own "dictionary"?
For anyone that is interested, it is pretty easy to do the same thing with NLog:
[LayoutRenderer("MyGDC")]
class GdcLayoutRenderer : LayoutRenderer
{
[RequiredParameter]
[DefaultParameter]
public string Item { get; set; }
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
string msg = GDC.Get(this.Item);
builder.Append(msg);
}
protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
{
return 10;
}
}
And configured like this:
Tell NLog about any assemblies with extensions:
<extensions>
<add assembly="NLog.Extensions"/>
</extensions>
Use the "indexed" property in a layout:
<layout="${longdate} | ${MyGDC:item=name} | ${message}"/>
In this example I am actually using NLog's GDC object as my "dictionary", but I am demonstrating how I was able to write my own "indexable" LayoutRenderer (more or less equivalent to log4net's PatternLayoutConverter) to access a value indexed by a value in the config file.
[EDIT] I got the answer that I wanted. I have included the code for my sample PatternLayoutRenderer here. In my test, I have a static dictionary in my main form class where I could store "application settings". I have created a PatternLayoutConverter that can accept a key as a parameter so that the converter can lookup the correct value in the dictionary. I might be able to achieve the same functionality using the log4net (or NLog) context objects, but in our application we might have some settings or session info that the application will hold for other purposes and we want to be able to add that to the logging output. Since it will already be in a lookup structure, it would be nice to be able to reference the data directly rather than having to explicitly copy it to the log4net (or NLog context).
Anyway, here is the code:
namespace Log4NetTest
{
class KeyLookupPatternConverter : PatternLayoutConverter
{
protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
{
//Use the value in Option as a key into the "application settings" stored on the main form.
string setting;
if (Form1.AppSettings.TryGetValue(Option, out setting))
{
writer.Write(setting);
}
}
}
}
Layout configuration:
//Log the "sessionid" and "userid" values from our "application settings" object
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p [session = %KLPC{sessionid}] [user = %KLPC{userid}] %m%n"/>
<converter>
<name value="KLPC" />
<type value="Log4NetTest.KeyLookupPatternConverter" />
</converter>
</layout>