- Notifications
You must be signed in to change notification settings - Fork1.4k
How to write a custom layout renderer
Layout renderers can capture, format and output additional context details that can be used byNLog Layouts. There are 2 ways to create a custom layout renderer.
- Register custom lambda-delegate-function with a symbol-name (Introduced with NLog v4.4)
- Register custom class that inherits from
LayoutRenderer
that also supports additional configuration options.
NLog 4.7 introduces a fluent registration API usingLogManager.Setup()
, where you create a layout renderer with a lambda:
NLog.LogManager.Setup().SetupExtensions(s=>s.RegisterLayoutRenderer("trace_id",(logevent)=>CorrelationIdentifier.TraceId.ToString()));
NLog 4.4 was the first edition to support lambda function will accept 1 or 2 parameters and should return astring
.
- 1 parameter: the
logEventInfo
. - 2 parameters:
logEventInfo
and the current NLog config.
Examples
//register ${text-fixed}LayoutRenderer.Register("text-fixed",(logEvent)=>"2");//register ${trace-identifier}LayoutRenderer.Register("trace-identifier",(logEvent)=>HttpContext.Current.TraceIdentifier);//Using logEventInfo, ${message-length}LayoutRenderer.Register("message-length",(logEvent)=>logEvent.FormattedMessage.Length);//Using config, ${targetCount}LayoutRenderer.Register("targetCount",(logEvent,config)=>config.AllTargets.Count);
Need the HTTP-context (e.g. Request, Session etc) for ASP.NET or ASP.NET Core?
Include theNLog.Web (ASP.NET Classic) orNLog.Web.AspNetCore nuget-package.
And usage:
usingNLog.Web.LayoutRenderers;AspNetLayoutRendererBase.Register("SessionItem1",(logEventInfo,httpContext,loggingConfiguration)=>httpContext.Session["SessionItem"]);// usage ${SessionItem1}
Create a class that inherits fromNLog.LayoutRenderers.LayoutRenderer
, set the[LayoutRenderer("your-name")]
on the class and override theAppend(StringBuilder builder, LogEventInfo logEvent)
method.Invoke in this methodbuilder.Append(..)
to render your custom layout renderer.
We create a${hello-world}
layout renderer, which renders..."hello world!".
[LayoutRenderer("hello-world")]publicclassHelloWorldLayoutRenderer:LayoutRenderer{protectedoverridevoidAppend(StringBuilderbuilder,LogEventInfologEvent){builder.Append("hello world!");}}
Use public class-properties for configuring the LayoutRenderer:
[LayoutRenderer("hello-world")]publicclassHelloWorldLayoutRenderer:LayoutRenderer{/// <summary>/// New special option/// </summary>[DefaultParameter]publicstringSpecialOption{get;set;}/// <summary>/// New extra option/// </summary>publicboolExtraOption{get;set;}
The[DefaultParameter]
-attribute can only be assigned to one class-property, and gives the ability to assign the class-property-value without specifying the class-property-name.
Example usages:
${hello-world:Bonus}
- AssignsSpecialOption
=Bonus
.${hello-world:SpecialOption=Bonus}
- AssignsSpecialOption
=Bonus
.${hello-world:ExtraOption=true}
- AssignsExtraOption
=true
.${hello-world:Bonus:ExtraOption=true}
- AssignsSpecialOption
=Bonus
andExtraOption
=true
.
If additional option-validation are required, thenoverride void InitializeLayoutRenderer()
and implement the necessary validation, andthrow NLogConfigurationException("...")
when issues are detected.
NLog will automatically capture relevant context state, when usingAsyncWrapper-target to perform actual writing on background-thread (to avoid logging objects after they have been disposed). The following class-attributes can used for the LayoutRenderer that enables additional performance:
[ThreadAgnostic]
LayoutRenderer does not capture state from the application-thread logging. Ex.
${threadid}
cannot be[ThreadAgnostic]
.For LayoutRenderer marked as
[ThreadAgnostic]
then NLog can skip the overhead of capturing state.If just a single LayoutRenderer in a Layout is not marked as
[ThreadAgnostic]
, then NLog introduces the overhead of state capture.[ThreadSafe]
Introduced with NLog 4.5.3, and made obsolete with NLog 5.0 that expects all to be threadsafe.
LayoutRenderer will render correct output regardless of the number of application-threads running inside.
For LayoutRenderer marked as
[ThreadSafe]
then NLog will skip using "global" locks when capturing state, thus application-threads willnot experience lock-congestion inside NLog.If just a single LayoutRenderer in a Layout is not marked as
[ThreadSafe]
, then NLog introduces the overhead of "global" lock when doing state capture.
Example of class-attributes for LayoutRenderer:
usingNLog.Config;[LayoutRenderer("hello-world")][ThreadAgnostic]publicclassHelloWorldLayoutRenderer:LayoutRenderer{protectedoverridevoidAppend(StringBuilderbuilder,LogEventInfologEvent){builder.Append("hello world!");}}
NLog 5.0 enables you to have multiple type-aliases for a single class. Before one had to inherit from the same class to provide additional type-names.
[LayoutRenderer("hello-world")]// ${hello-world}[LayoutRenderer("hello-earth")]// ${hello-earth}publicclassHelloWorldLayoutRenderer:LayoutRenderer{
The type-alias can then be used when wanting to use the LayoutRenderer in NLog SimpleLayout.
Notice NLog 5.0 automatically ignores dashes-
in type-alias, so no extra alias is needed for this: Ex.${helloworld}
-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