EDIT 4: \"From\" seems to be a reserved word in NLog. Changing it \"FromID\" worked. this is an awesome way to pass variables to NLog and still keep your code clean !!!! TH
Event properties (used to be called event-context) would be the built-in way to do what you want. If you are using NLog 3.2+ you can use the fluent api, which may be a bit more appealing than creating LogEventInfo
objects. You can access this api by by using the namespace NLog.Fluent
.
Your layout would then be defined like this:
${event-properties:item=ID} ${date} ${Level} ${Message}
Then using the fluent api, log like this:
_logger.Debug()
.Message("My name is {0}", "Ed")
.Property("ID", 87)
.Write();
Other than setting properties per event as above, the only other option would be to set properties per thread using MDC or MDLS.
NLog dosen't have a way (that I have found) of setting per-logger properties. Internally, NLog caches Logger
instances by logger name, but does not guarantee that the same instance of Logger
will always be returned for a given logger name. So for example if you call LogManager.GetCurrentClassLogger()
in the constructor of your class, most of the time you will get back the same instance of Logger for all instances of your class. In which case, you would not be able to have separate values on your logger, per instance of your class.
Perhaps you could create a logging helper class that you can instantiate in your class. The helper class can be initialized with per-instance property values to be logged with every message. The helper class would also provide convenience methods to log messages as above, but with one line of code. Something like this:
// Example of a class that needs to use logging
public class MyClass
{
private LoggerHelper _logger;
public MyClass(int id)
{
_logger = new LoggerHelper(LogManager.GetCurrentClassLogger());
// Per-instance values
_logger.Set("ID", id);
}
public void DoStuff()
{
_logger.Debug("My name is {0}", "Ed");
}
}
// Example of a "stateful" logger
public class LoggerHelper
{
private Logger _logger;
private Dictionary _properties;
public LoggerHelper(Logger logger)
{
_logger = logger;
_properties = new Dictionary();
}
public void Set(string key, object value)
{
_properties.Add(key, value);
}
public void Debug(string format, params object[] args)
{
_logger.Debug()
.Message(format, args)
.Properties(_properties)
.Write();
}
}
This would work with the same layout as above.