NLog 4.4 is live!
14 Dec 2016NLog 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!
Example
<target type='WebService'
name='ws'
url='http://localhost:1234/logme'
protocol='JsonPost'
encoding='UTF-8' >
<parameter name='param1' type='System.String' layout='${message}'/>
<parameter name='param2' type='System.String' layout='${level}'/>
</target>
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
Example:
<layout xsi:type="JsonLayout" includeAllProperties="true" excludeProperties="BadPropertyName1, BadProperty2">
<field name="message" layout="My message for you is this ${message}" />
</layout>
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.
Examples
//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
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
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
fromstring
(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.
Examples:
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
Example:
<target name="file" xsi:type="AutoFlushWrapper" condition="level >= LogLevel.Error">
<target xsi:type="BufferingWrapper" ..>
<target name="gmail" xsi:type="Mail"
smtpServer="smtp.gmail.com"
smtpPort="587"
smtpAuthentication="Basic"
/>
</target>
</target>
LimitingTargetWrapper
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"
smtpServer="smtp.gmail.com"
smtpPort="587"
smtpAuthentication="Basic"
/>
</target>
WindowsMultiProcessFileAppender
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 forAggregateException
- 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
Bugfixes:
- Writing to the same file from multiple processes does not function when archiving with
concurrentWrites="true"
andkeepFileOpen="true"
- NLog throws ConfigurationErrorsException when appsettings has invalid XML.
Other:
- Improved
[Obsolete]
warnings - include the Nlog version when it became obsolete - FileTarget - Close stale file handles outside archive mutex lock #1513
THANKS!
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!