- Notifications
You must be signed in to change notification settings - Fork1.4k
How to write a custom target for structured logging
Introduced with NLog 4.5
It is really easy:
- Create a class that inherits from
NLog.Targets.TargetWithContext - Override the
Write(LogEventInfo logEvent)method. - In the body of this method invoke
this.RenderLogEvent(this.Layout, logEvent)to get the message text, and invokethis.GetAllProperties(logEvent)to getstructured properties.
See also the updatedHow to write a custom async target
usingNLog;usingNLog.Config;usingNLog.Targets;namespaceMyNamespace{[Target("MyFirst")]publicsealedclassMyFirstTarget:TargetWithContext{publicMyFirstTarget(){this.IncludeEventProperties=true;// Include LogEvent Properties by default}publicLayoutHost{get;set;}="localhost";protectedoverridevoidWrite(LogEventInfologEvent){stringlogMessage=this.RenderLogEvent(this.Layout,logEvent);stringhostName=this.RenderLogEvent(this.Host,logEvent);IDictionary<string,object>logProperties=this.GetAllProperties(logEvent);SendTheMessageToRemoteHost(hostName,logMessage,logProperties);}privatevoidSendTheMessageToRemoteHost(stringhostName,stringmessage,IDictionary<string,object>properties){// TODO - write me}}}
Users can easily configure additional context information:
<targettype="MyFirst"name="first"> <contextpropertyname="MachineName"layout="${machinename}" /> <contextpropertyname="ThreadId"layout="${threadid}" /></target>
Without needing to inject the details upfront when doing the logging. It is automatically captured by the NLog engine.
ScopeContext Properties can be used to provide context-specific details (Ex. request-correlationid fromILogger.BeginScope).
To automatically capture properties injected into ScopeContext (Before NLog 5.0 it was calledIncludeMDLC)
<targettype="MyFirst"name="first"includeScopeProperties="true"> ...</target>
TargetWithContext will by default ensure that all captured property-values are included in output, and will automatically generate new unique key-name when name-collission. If wanting to merge properties, so one context can override another context, then one can do it like this:
<targettype="MyFirst"excludeProperties="RequestId"> <contextpropertyname="RequestId"layout="${event-properties:RequestId:whenEmpty=${scope-property=RequestId:whenEmpty=DefaultValue}}" /></sometarget>
Instead ofDefaultValue then you could also use one of theNLog LayoutRenderers available. Ex.${aspnet-TraceIdentifier} or${activity:property=TraceId}. Or alternative skipwhenEmpty=DefaultValue and rely onIncludeEmptyValue="false" (default).
-Troubleshooting Guide - See available NLog Targets and Layouts:https://nlog-project.org/config
- All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json