-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Custom extension of Logger interface
There can be different reasons for extending the NLog logging interface:
- Extend logging interface to automatically add relevant context when logging.
- Create an abstract interface to avoid direct NLog dependency in source-code.
There already exists several libraries that provides an abstract interface:
- Microsoft.System.Diagnostics.Trace (Setup NLogTraceListener)
- Common Logging (But seems obsolete)
- LibLog - Useful for shared libraries (But have become obsolete)
- Microsoft.Extensions.Logging
There are two ways to extend the NLog Logger.
- Inherit from the NLog Logger and add your own custom extensions.
- Create a custom wrapper around the NLog Logger and forward the logevents to the NLog Logger.
NLog has a special Callsite feature, that allows it to automatically capture the location in source code that performed the logging. This feature has a huge overhead (logging becomes 20 times slower, together with lots of bonus allocations), because the capture of StackTrace and scanning for source location is expensive.
When creating a custom wrapper around the NLog Logger-interface (or extension methods), then the callsite logic will think the custom wrapper is the origin of the log-statement. This can be solved by using Logger.Log(Type wrapperType, LogEventInfo logEvent)
-method when writing the LogEvent, and providing the typeof(MyCustomWrapper)
as first parameter.
public class MyLogger
{
private readonly NLog.Logger Logger;
public MyLogger(string name)
{
Logger = NLog.LogManager.GetLogger(name);
}
public void WriteMessage(string message)
{
NLog.LogEventInfo logEvent = NLog.LogEventInfo.Create(NLog.LogLevel.Info, null, message);
Logger.Log(typeof(MyLogger), logEvent);
}
}
When the custom wrapper provides its own Type as wrapperType, then the callsite logic will not see the custom wrapper as being the origin of the log-statement. If extending the NLog Logger-interface without providing the correct wrapperType
, then Callsite will stop working.
Note NLog 5.0 adds full support for using Caller Information-attributes that was introduced with .NET 4.5. When having called LogEventInfo.SetCallerInfo(...)
then StackTrace capture is not needed for the Callsite feature.
public class MyLogger
{
private readonly NLog.Logger Logger;
public MyLogger(string name)
{
Logger = NLog.LogManager.GetLogger(name);
}
public void WriteMessage(string message,
[CallerMemberName] string callerMemberName = "",
[CallerFilePath] string callerFilePath = "",
[CallerLineNumber] int callerLineNumber = 0)
{
NLog.LogEventInfo logEvent = NLog.LogEventInfo.Create(NLog.LogLevel.Info, null, message);
logEvent.SetCallerInfo(null, callerMemberName, callerFilePath, callerLineNumber);
Logger.Log(typeof(MyLogger), logEvent);
}
}
- Troubleshooting Guide - See available NLog Targets and Layouts: https://nlog-project.org/config
- Getting started
- How to use structured logging
- Troubleshooting
- FAQ
- Articles about NLog
-
All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json