Skip to content

How to write a custom layout renderer

Julian Verdurmen edited this page Jun 23, 2019 · 17 revisions

Since NLog 4.4 there are two ways to create a custom layout renderer.

You could write a custom layout with one lambda function - it will be registered intermediately, or you could write a class which is easier to share across projects and could have options.

Lambda Function

Introduced in NLog 4.4

For simple cases, you could create a layout renderer with a lambda.

The lambda function will accept 1 or 2 parameters and should return a string.

  • 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.Message.Length);

//Using config, ${targetCount}
LayoutRenderer.Register("targetCount",(logEvent, config) => config.AllTargets.Count);

Class

Create a class that inherits from NLog.LayoutRenderers.LayoutRenderer, set the [LayoutRenderer("your-name")] on the class and override the Append(StringBuilder builder, LogEventInfo logEvent) method. Invoke in this method builder.Append(..) to render your custom layout renderer.

Don't forget to register your custom component!

Example

We create a ${hello-world} layout renderer, which renders..."hello world!".

[LayoutRenderer("hello-world")]
public class HelloWorldLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append("hello world!");
    }
}

How to pass configuration options to the layout render?

Just create public properties on the Layout Renderer. The properties could be decorated with the [RequiredParameter] and [DefaultParameter] attributes. The [DefaultParameter] can be passed to the layout renderer without using the name.

for example:

[LayoutRenderer("hello-world")]
public class HelloWorldLayoutRenderer : LayoutRenderer
{
        /// <summary>
        /// I'm not required or default
        /// </summary>
        public string Config1 { get; set; }

        /// <summary>
        /// I'm required
        /// </summary>
        [RequiredParameter]
        public string Config2 { get; set; }

        /// <summary>
        /// I'm the default parameter. You can set me as required also.
        /// </summary>
        [DefaultParameter]
        public bool Caps {get;set;}

Example usages

  • ${hello-world} - raises exception: required parameter Config2 isn't set
  • ${hello-world:Config2=abc} - OK, Config2 property set
  • ${hello-world:true:config2=abc} - default parameter (Caps) set to true
  • ${hello-world:true:config2=abc:config1=yes} - all the three properties set
Clone this wiki locally
You can’t perform that action at this time.