I have database maintenance in place using AdoNetAppender. What I would like to do is write a user id to each log statement. However, I do not want to use the standard log4net% identifier for two reasons:
- log4net warns that it is very slow as it should look for the context identifier.
- In some components of the service, standard authentication is a service account, but we have already fixed the user ID in a variable, and I would like to use this.
I saw code in which some people use log4net.ThreadContext to add additional properties, but I understand that this is βunsafeβ due to thread rotation (and this is also a performance leak).
My approach was to extend the AdoNetAppenderParameter class like this:
public class UserAdoNetAppenderParameter : AdoNetAppenderParameter { public UserAdoNetAppenderParameter() { DbType = DbType.String; PatternLayout layout = new PatternLayout(); Layout2RawLayoutAdapter converter = new Layout2RawLayoutAdapter(layout); Layout = converter; ParameterName = "@username"; Size = 255; } public override void Prepare(IDbCommand command) { command.Parameters.Add(this); } public override void FormatValue(IDbCommand command, LoggingEvent loggingEvent) { string[] data = loggingEvent.RenderedMessage.Split('~'); string username = data[0]; command.Parameters["@username"] = username; } }
and then programmatically add this to the current application like this:
ILog myLog = LogManager.GetLogger("ConnectionService"); IAppender[] appenders = myLog.Logger.Repository.GetAppenders(); AdoNetAppender appender = (AdoNetAppender)appenders[0]; appender.AddParameter(new UserAdoNetAppenderParameter()); myLog.InfoFormat("{0}~{1}~{2}~{3}", userName, "ClassName", "Class Method", "Message");
The goal is to use a standard format for messages and parse the first part of the string, which should always be the username. The FormatValue () method of the appender custom parameter must use only that part of the string so that it can be written to a separate field in the log database.
My problem is that no log statements are written to the database. Oddly enough, when debugging, the breakpoint in the FormatValue () method only hits when the service stops.
I made my way through many things related to this, but have not yet found the answers. Someone was able to do this, or I'm wrong. Postscript I also tried to extend AdoNetAppender, but it does not give you access to setting parameter values.