How to write your own Layout Renderer

Why would I want to write a Layout Renderer?

Layout renderers are a way to enrich your debugging output by outputting environmental properties of your applications. NLog comes with Layout Renderers for most common tasks (like outputting environment variables, registry keys, thread ids, base directory, etc.), but you may want to develop your own Layout Renderer to provide information about your application or framework.

How to write a layout renderer?

It's really easy. Create a class that inherits from NLog.LayoutRenderer and override the Append() method. In the body of the method use the ApplyPadding() to get the output text formatted according to the common Layout Renderer parameters then send the text to the destination StringBuilder.

Example

This is a skeleton layout renderer that outputs current hour. Compile using:

csc.exe /t:library /out:MyAssembly.dll /r:NLog.dll MyFirstLayoutRenderer.cs

using System; 
using System.Text; 
 
using NLog; 
 
namespace MyNamespace 
{ 
    [LayoutRenderer("hour")] 
    public sealed class HourLayoutRenderer: LayoutRenderer 
    { 
        private bool _showMinutes = false; 
         
        // this is an example of a configurable parameter 
        public bool ShowMinutes 
        { 
            get { return _showMinutes; } 
            set { _showMinutes = value; } 
             
        } 
        protected override int GetEstimatedBufferSize(LogEventInfo ev) 
        { 
            // since hour is expressed by 2 digits we need at most 2-character 
            // buffer for it 
            return 2; 
        } 
 
        protected override void Append(StringBuilder builder, LogEventInfo ev) 
        { 
            // get current hour or minute, convert it to string, apply padding 
            // and append to the specified StringBuilder 
            if (ShowMinutes) 
            { 
                builder.Append(ApplyPadding(DateTime.Now.Minute.ToString())); 
            } 
            else 
            { 
                builder.Append(ApplyPadding(DateTime.Now.Hour.ToString())); 
            } 
        } 
    } 
}
How to use the newly created layout renderer?

It's easy. Just put the renderer in a DLL and reference it from the the config file using the <extensions /> clause as described here.

Configuration file example

This example causes all messages written to the console to be prepended with current hour. Simple isn't it?

<nlog> 
  <extensions> 
    <add assembly="MyAssembly"/> 
  </extensions> 
  <targets> 
    <target name="console" type="Console" 
            layout="${hour:showminutes=false} ${message}"/> 
  </targets> 
  <rules> 
    <logger name="*" minLevel="Info" appendTo="console"/> 
  </rules> 
</nlog> 
How to pass configuration options to the renderer?

Consider the above example. There's a property called "ShowMinutes" that does just that. Having a public property that sets the required configuration parameters is enough for NLog to use it. Parameters can be passed by separating them with colons. For example:

${hour:showminutes=true}

sets the ShowMinutes property to True during configuration. To pass more parameters, just use more colons:

${layoutrenderername:par1=value1:par2=value2:par3=value3:...:parN=valueN}

NLog takes care of the appropriate conversions necessary so that you can use integer, string, datetime, boolean parameters.

Do I really need to create a separate DLL?

Not really. You can use LayoutRendererFactory.AddLayoutRenderer() to register your layout renderer programmatically. Just be sure to to it at the very beginning of your program before any log messages are written. It should be possible to reference your EXE using the <extensions /> clause.

static void Main(string[] args) 
{ 
    LayoutRendererFactory.AddLayoutRenderer("hour", typeof(MyNamespace.MyFirstLayoutRenderer)); 
 
    // start logging here 
}