Hi
I've made a couple of customizations to log4net and would like to hear
people's opinion on my solution.
When logging I've made extensive use of properties to put data in
specific database fields. These properties must (as far as I know) be
placed in GlobalContext, ThreadContext or LogicalThreadContext. This can
be a bit of a drag since the properties are still active after logging,
this results in code like
log4net.LogicalThreadContext.Properties["LogData"] = myData;
log4net.LogicalThreadContext.Properties["LogException"] = e.Message;
log.Error("An exception occured");
log4net.LogicalThreadContext.Properties.Remove("LogData");
log4net.LogicalThreadContext.Properties.Remove("LogException");
I got tired of this, so after picking up a few tips and tricks from
other threads in this mailing list I decided to make an attempt at
customizing Log4Net. I decided to make another overload for each of the
logging methods (log.Info, log.Debug etc), an overload that (in addition
to a message and an exception) takes in the names and values of the
desired properties, and adds them to the logging event itself, thus
making them unique for that perticular logging call. What I ended up
with was the following additions to LogImpl.cs:
virtual public void Error(object message, Exception exception,
string[] propertyNames, string[] propertyValues)
{
Logger.Log(CustomLoggingEvent(m_levelError, message, exception,
propertyNames, propertyValues));
}
private LoggingEvent CustomLoggingEvent(Level level, object message,
Exception exception, string[] propertyNames, string[] propertyValues)
{
LogLog.Debug("Creating custom logging event.");
log4net.Core.LoggingEvent loggingEvent = new
log4net.Core.LoggingEvent(ThisDeclaringType, Logger.Repository,
Logger.Name, level, message, exception);
try
{
// Ignore all properties if the two arrays are of different
lengths
if (propertyNames.Length == propertyValues.Length)
{
for (int i = 0; i < propertyNames.Length; i++)
{
if (propertyNames[i].Length > 0)
{
// Add the parameter to the LoggingEvent
loggingEvent.Properties[propertyNames[i]] =
propertyValues[i];
LogLog.Debug("Property " + propertyNames[i] + "
added to custom logging event, with a value of " + propertyValues[i]);
}
}
}
}
catch (Exception exc)
{
LogLog.Debug("Error creating custom logging event: " +
exc.Message);
}
return loggingEvent;
}
...and in ILog.cs, I added
void Error(object message, Exception exception, string[]
propertyNames, string[] propertyValues);
So, instead of the previous code where I added and then removed the
properties every time I needed them, I now use the following code to log
with properties:
log.Error("An exception occured", e, new string[]{"LogData",
"LogException"}, new string[]{myData, e.Message});
This makes logging with properties a lot easier to code, but is it a
good solution? I know it's somewhat limited with the arrays being of
type string and not Object, but I wanted to keep it simple as a start,
and it satisfies my (current) needs. But besides that? Are there any
other parts of Log4Net that needs to be altered because of this (it
works fine now though), is the way I've solved it good, is the code
good? Any advice or criticism (and even praise) would be apreciated.
Regards,
Frode