NLog 4.4 is live!

14 Dec 2016

NLog 4.4 contains new features, performance improvements and makes it easier to write custom components (e.g. targets, layout renderers) for NLog!

A lot of stuff has been contributed by the community! Thanks for making NLog great!

Main features

WebServiceTarget support for JSON & XML

The WebServiceTarget was always a bit odd as it was posting the data Form-encoded (application/x-www-form-urlencoded). This has now been fixed with the support for JSON and XML, just pick one!


<target type='WebService'
        encoding='UTF-8'   >
    <parameter name='param1' type='System.String' layout='${message}'/> 
    <parameter name='param2' type='System.String' layout='${level}'/>

Injecting JSON serializer into NLog

With the support of JSON in the WebServiceTarget, it can be important to give the opportunity to choose your JSON serializer implementation. This implementation will be also used for all other JSON serialization in NLog, like the JsonLayout.

We really like JSON.NET, but we don’t like to depend on it! It’s a great library, but it can lead to issues with strong names and other versions in your project. See also the statement of RestSharp library (which is also a great library)

So we now have our own implementation, which is sufficient for most cases.

Do you like to choose your implementation? Implement SerializeObject(..) in IJsonSerializer and set it to ConfigurationItemFactory.JsonSerializer.

JSON layout support for all-event-properties

The JsonLayout has two new properties which will help you creating better JSON documents:

  • includeAllProperties: Include all events properties of a logevent? default: false. Introduced in NLog 4.4
  • excludeProperties: comma separated string with names which properties to exclude. Only used when includeAllProperties is true. Case sensitive. Default empty When a name contains a comma, single quote the value. E.g. ‘value,withquote’,value2. Introduced in NLog 4.4


<layout xsi:type="JsonLayout" includeAllProperties="true" excludeProperties="BadPropertyName1, BadProperty2">
    <field name="message" layout="My message for you is this ${message}" />

Don’t stop logging when there is something wrong in the layout

Previously, if you made an error in a layout, e.g. typos:

 <target name="file" xsi:type="File"
            layout="${message} ${oops-I-made-a-typo}" >

or just using a layout renderer from a non-included package, nothing got logged!

This is unneccesary and we are skipping the invalid parts now. The invalid parts are replaced with an empty string.

NB: If throwExceptions or throwConfigExceptions is true, there will be still an error thrown

Lamba Function layout renderers

Layout renders (those things between ${}) can help you writing context information.

Since NLog 4.4 there is a new way to create a custom layout renderer, which can be written on one line!

The new LayoutRenderer.Register accepts a lamba function, which accepts 1 or 2 parameters and should return a string.

  • 1 parameter: the logEventInfo.
  • 2 parameters: logEventInfo and the current NLog config.


//register ${text-fixed}
LayoutRenderer.Register("test-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);

See the wiki

Make it easier to register custom layout / target / layoutrendeners

There is a new syntax introduced so it’s easier to register your custom extensions:

Target.Register<MyNamespace.MyFirstTarget>("MyFirst"); //generic
Target.Register("MyFirst", typeof(MyNamespace.MyFirstTarget)); //OR, dynamic

//layout renderer
LayoutRenderer.Register<MyNamespace.MyFirstLayoutRenderer>("MyFirst"); //generic
LayoutRenderer.Register("MyFirst", typeof(MyNamespace.MyFirstLayoutRenderer)); //dynamic

Layout.Register<MyNamespace.CsvLayout>("csv"); //generic
Layout.Register("csv", typeof(MyNamespace.CsvLayout)); //dynamic

For more info, see the wiki

Collection types for custom extensions

Custom Targets, layout etc. can have properties. There are only limitations if you’d like to set them from the XML config.

The following types are supported:

Allowed types

Allowed types for Targets, Layouts and Layout renderers.

  • C# types: e.g. bool, char, decimal, double, float, int, uint, etc.
  • Enums (use short name)
  • Encoding
  • CultureInfo
  • Type
  • LineEndingMode
  • Uri
  • NLog types: Layout, SimpleLayout & ConditionExpression
  • Types which has an implicit conversion from string
  • Types which are using TypeDescriptor from string (not Silverlight)
  • Collections, introduced in NLog 4.4. See section Collection types

Collection types

Introduced in NLog 4.4, the following collection types can be used.

Usage in XML: comma separated string. If the value contains a comma, single quote the whole value.


  • value="one arg"
  • value="1,2"
  • value="value1,'value2, with comma'"

Collections of type:

  • IList<T> / IList
  • IEnumerable<T> / IEnumerable
  • ISet<T> / HashSet<T>

with the following types:

  • C# built in types (string, int, double, object)
  • enum (use short name)
  • culture, encoding, Type
  • not supported: Layout

Not supported:

  • Arrays
  • Non-generic List
  • Non-gereric IList
  • Custom class implementing/inheriting from the collection classes/interfaces. (because of performance)

PS: .NET 3.5 has HashSet but no ISet

Added condition to AutoFlushWrappper

Something you would like to flush in special cases only, e.g. sending a mail when there is an error. Of course you would like to have the trace logs in your mail too, as that can help identifying the problem!

This is now possible by using the Condition property on AutoFlushWrappper


<target name="file" xsi:type="AutoFlushWrapper" condition="level >= LogLevel.Error">
  <target xsi:type="BufferingWrapper" ..>
    <target name="gmail" xsi:type="Mail"


Like sending mail but not every 10 seconds? With the LimitingTargetWrapper you can control the maximum events per interval.

Example, max 5 messages per 10 minutes

<target name='limiting' type='LimitingWrapper' messagelimit='5' interval='0:10:00'>
 <target name="gmail" xsi:type="Mail"


In Windows there is a new file writing implementation. From tests we have 10-40% performance increase!

WebServiceTarget & ${UrlEncode} - Added standard support for UTF8 encoding, added support for RFC2396 & RFC3986

The URL encoding for the WebServiceTarget was not behaving to any RFC as far as we know. This has been changed!

For the WebServiceTarget & ${UrlEncode}, NLog will by default encode parameters as UTF8 and escape special characters according to Rfc2396.

Also the following properties have been added to WebServiceTarget & ${UrlEncode}

  • escapeDataRfc3986 - To escape data according to standard Rc3986, set this option to true
  • escapeDataNLogLegacy - To escape data according to the old non-standard NLog style, set this option to true

Other additions and changes

  • ${exception} - Added support for AggregateException
  • Keeping variables during configuration reload (optional)
  • Layout processinfo with support for custom Format-string
  • DetectConsoleAvailable on (colored)Console disabled by default
  • Callsite: added includeNamespace option


  • Writing to the same file from multiple processes does not function when archiving with concurrentWrites="true" and keepFileOpen="true"
  • NLog throws ConfigurationErrorsException when appsettings has invalid XML.


  • Improved [Obsolete] warnings - include the Nlog version when it became obsolete
  • FileTarget - Close stale file handles outside archive mutex lock #1513


Thanks for the contributions!

  • @aireq
  • @AndreGleichner
  • @ie-zero
  • @Jeinhaus
  • @nazim9214
  • @snakefoot
  • @tetrodoxin

What’s up Next?

Structural logging!

We could use your help to introduce this feature soon!

Like to help with coding or testing? Please let us know!