Skip to content

Commit a937691

Browse files
authored
NLog v6 - Preview1 (#258)
1 parent aa756d7 commit a937691

File tree

4 files changed

+318
-7
lines changed

4 files changed

+318
-7
lines changed

_posts/2015-06-30-extending-nlog-is-easy.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ title: Extending NLog is... easy!
77

88
Not everyone knows NLog is easy to extend to your own wishes.
99
There can be various reasons for wanting to extend NLog.
10-
For example when you want to write your log messages to a custom output or you would like to use your own `${}` macros.
10+
For example when you want to write your log messages to a custom output target, or include additional details in the output with own custom `${layout-renderer}`.
1111

1212
With some attributes you can create your own custom target, layout or layout renderer with ease.
1313
Also creating your own conditions for filter messages is possible!
@@ -78,7 +78,7 @@ Example usages:
7878

7979

8080
## How to write a custom target?
81-
Creating a custom target is almost identical to creating a custom layout renderer.
81+
Creating a custom target is very similar to creating a custom layout renderer.
8282

8383
The created class should now inherit from `NLog.Targets.TargetWithLayout` and override the `Write()` method. In the body of the method invoke `this.Layout.Render()` to render the message text.
8484

@@ -96,13 +96,14 @@ public sealed class MyFirstTarget: TargetWithLayout
9696
}
9797

9898
[RequiredParameter]
99-
public string Host { get; set; }
99+
public Layout Host { get; set; }
100100

101101
protected override void Write(LogEventInfo logEvent)
102102
{
103103
string logMessage = this.Layout.Render(logEvent);
104+
string hostName = this.Host.Render(logEvent);
104105

105-
SendTheMessageToRemoteHost(this.Host, logMessage);
106+
SendTheMessageToRemoteHost(hostName, logMessage);
106107
}
107108

108109
private void SendTheMessageToRemoteHost(string host, string message)
@@ -144,7 +145,7 @@ Configuration file example:
144145

145146

146147
### Do I really need to create a separate assembly?
147-
Not really. You should then register your target programmatically. Just make sure to register your stuff at the very beginning of your program, before any log messages are written.
148+
Not really. You should then register your target programmatically. Just make sure to register your stuff at the very beginning of your program, before the loading of NLog config and actual logging.
148149
{% highlight csharp %}
149150
static void Main(string[] args)
150151
{
@@ -156,7 +157,7 @@ static void Main(string[] args)
156157
ConfigurationItemFactory.Default.Targets
157158
.RegisterDefinition("MyFirst", typeof(MyNamespace.MyFirstTarget));
158159

159-
// start logging here
160+
// start loading NLog config and logging here
160161
}
161162
{% endhighlight %}
162163

_posts/2022-05-16-nlog-5-0-finally-ready.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ NLog 5.0 has completed preview testing, and is ready for release.
1919
- Parsing of type-alias will now ignore dashes (-)
2020
- NLog v5.1 enables support for ISpanFormattable in FormattedMessage and serializing JSON.
2121
- NLog v5.2 includes annotations for application trimming without build warnings.
22+
- NLog v5.3 introduces support for `Layout.FromMethod` for typed Layout
2223

2324
See details [here](https://nlog-project.org/2021/08/25/nlog-5-0-preview1-ready.html)
2425

_posts/2024-10-01-nlog-6-0-goals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ NLog v6.0 has the following goals:
1717
- Extract NLog.Targets.NetworkTarget to its own nuget-package
1818
- Extract NLog.Targets.MailTarget to its own nuget-package
1919
- Extract NLog.Targets.FileTarget to its own nuget-package NLog.Targets.ConcurrentFileTarget
20-
- NLog will instead have a simple FileTarget without ConcurrentWrites-support but only KeepFileOpen = false
20+
- NLog will instead have a simple FileTarget without ConcurrentWrites-support, but still supports KeepFileOpen true / false
2121

2222
The overall goal for NLog v6.0 is to continue being a fully working logging-library in a single nuget-package.
2323
The NLog-package will out of the box only handle file- and console-output, which will probably cover 90 pct.
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
---
2+
layout: post
3+
title: NLog 6.0 - List of major changes
4+
---
5+
6+
NLog 6.0 is a major version release, and introduces breaking changes to support AOT-builds by splitting into multiple nuget packages.
7+
8+
## Major changes
9+
10+
### NLog supports AOT
11+
12+
NLog has traditionally relied on reflection to dynamically discover requirements for target output.
13+
But reflection does not always work well with build trimming, and before NLog marked itself to be excluded from trimming.
14+
15+
NLog includes many features, and each feature often introduces additional dependencies on the .NET library.
16+
This can lead to overhead for AOT builds, as it must include and compile all the relevant source code.
17+
18+
NLog v6 attempts to reduce its footprint by extracting several features into separate nuget-packages:
19+
20+
- NLog.RegEx - Depends on System.Text.RegularExpressions which is a huge dependency for a logging library.
21+
- NLog.Targets.ConcurrentFile - ConcurrentWrites using global mutex from operating system API.
22+
- NLog.Targets.AtomicFile - ConcurrentWrites using atomic file-append from operating system API.
23+
- NLog.Targets.GZipFile - EnableArchiveFileCompression using GZipStream for writing GZip compressed log-files.
24+
- NLog.Targets.Mail - Depends on System.Net.Mail.SmtpClient.
25+
- NLog.Targets.Network - Depends on TCP and UDP Network Socket, and adds support for Syslog and Graylog.
26+
- NLog.Targets.Trace - Depends on System.Diagnostics.TraceListener.
27+
- NLog.Targets.WebService - Depends on System.Net.Http.HttpClient.
28+
29+
NLog v6 also no longer depends on `System.Xml.XmlReader`, but now includes its own basic XmlParser for loading `NLog.config` files.
30+
31+
NLog v6 still introduces an overhead when compared with just using `Console.WriteLine`,
32+
but now reduced to 5 MByte in comparison to 14 MBytes with NLog v5.
33+
34+
If the `NLog.config`-file had to be explicitly loaded, then the AOT-build could trim much more,
35+
since right now the AOT-build cannot predict what types will be required by the `NLog.config`-file.
36+
But disabling automatic loading of the `NLog.config`-file is a huge breaking change,
37+
and would hurt lots of existing applications.
38+
39+
### NLog FileTarget without ConcurrentWrites
40+
41+
NLog FileTarget no longer uses `File.Move` by default, but instead rolls to the next filename.
42+
This is to prevent file-locking issues with other background-applications, or if the log-file is
43+
held open by file-viewer.
44+
45+
The new archive-logic:
46+
47+
- LogFile.txt (Oldest file)
48+
- LogFile_1.txt
49+
- LogFile_2.txt (Newest file)
50+
51+
The old archive-logic:
52+
53+
- LogFile.txt (Newest file)
54+
- LogFile.1.txt (Oldest file)
55+
- LogFile.2.txt
56+
57+
NLog FileTarget still support static archive logic with `File.Move`, but it must be explictly activated
58+
by specifying `ArchiveFileName`. If not using `ArchiveFileName` but want to revert to old archive-logic
59+
with `File.Move` then just ensure to assign `ArchiveFileName="..."` with the same value as `FileName="..."`.
60+
61+
NLog FileTarget no longer has the following options:
62+
63+
- ConcurrentWrites - Removed because of dependency on global mutex and exotic file-locks.
64+
- EnableArchiveFileCompression - Removed because of dependency on compression-libraries.
65+
- CleanupFileName - Removed because it is now implicit.
66+
- FileNameKind - Removed because it is now implicit.
67+
- ArchiveFileKind - Removed because it is now implicit.
68+
- FileAttributes - Removed because of dependency on Windows-only API.
69+
- ForceManaged - Removed because of dependency on Windows-only API.
70+
- ConcurrentWriteAttempts - Removed together with ConcurrentWrites.
71+
- ConcurrentWriteAttemptDelay - Removed together with ConcurrentWrites.
72+
- ForceMutexConcurrentWrites - Removed together with ConcurrentWrites.
73+
- NetworkWrites - Replaced by KeepFileOpen.
74+
- ArchiveOldFileOnStartupAboveSize - Instead use ArchiveAboveSize / ArchiveOldFileOnStartup.
75+
- ArchiveDateFormat - Marked as obsolete. Instead use new ArchiveSuffixFormat
76+
- ArchiveNumbering - Marked as obsolete. Instead use new ArchiveSuffixFormat (Rolling is unsupported).
77+
78+
If one still requires these options, then one can use the new NLog.Targets.ConcurrentFile-nuget-package.
79+
NLog.Targets.ConcurrentFile-nuget-package is the original NLog FileTarget with all its features and complexity.
80+
The goal is that NLog.Targets.ConcurrentFile-nuget-package should become legacy, but it might help some when upgrading to NLog v6.
81+
82+
Alternative options for replacing `ConcurrentWrites = true`:
83+
- Use the new nuget-package NLog.Targets.AtomicFile where AtomicFileTarget uses atomic file-appends and supports Windows / Linux with NET8.
84+
- Change to use `KeepFileOpen = false` where file is opened / closed when writing LogEvents. Recommended to use `<targets async="true">`.
85+
86+
Alternative options for replacing `EnableArchiveFileCompression = true`:
87+
- Activate NTFS compression for the logging-folder.
88+
- Setup cron-job / scheduled-task that performs ZIP-compression and cleanup of the logging-folder.
89+
- Implement background task in the application, which monitors the logging-folder and performs ZIP-compression and cleanup.
90+
- Use the new nuget-package NLog.Targets.GZipFile where GZipFileTarget writes directly to a compressed log-file using GZipStream.
91+
92+
### NLog AtomicFileTarget without mutex
93+
94+
New AtomicFileTarget has been introduced, that supports atomic file-append with help from the operating system,
95+
and supports both Windows and Linux (with help from Mono Posix) for NET8 (and newer).
96+
97+
Extends the standard FileTarget and adds support for `ConcurrentWrites = true`, but without using global mutex.
98+
99+
Linux users must use `dotnet publish` with `--configuration release --runtime linux-x64` to ensure
100+
correct publish of the `Mono.Posix.NETStandard`-nuget-package dependency.
101+
102+
### NLog GZipFileTarget with GZipStream
103+
104+
New GZipFileTarget has been introduced, that writes directly to a compressed log-file using GZipStream.
105+
106+
Extends the standard FileTarget and adds support for `EnableArchiveFileCompression = true`, but only supports
107+
GZip file compression.
108+
109+
The GZip File compression doesn't allow appending to existing GZip Archive without rewriting the entire GZip Archive.
110+
Therefore these options are set by default `KeepFileOpen = true` and `ArchiveOldFileOnStartup = true`.
111+
112+
The GZip File compression has better handling of large log-files compared to the old `EnableArchiveFileCompression = true`,
113+
where the old ZIP compression would stall the file-logging until completed.
114+
115+
### NLog LogFactory FlushAsync
116+
117+
NLog LogFactory `Flush()` and `Shutdown()` are synchronous API methods, that schedules background worker-threads
118+
to execute NLog Target Flush. This doesn't work well on platforms that simulates worker-threads,
119+
by running everything on main thread.
120+
121+
Instead NLog LogFactory `FlushAsync`-method has been introduced that will support multi-threaded flush.
122+
123+
The NLog LogFactory now also implements `IDisposableAsync` which includes `FlushAsync` before closing. This allows the following:
124+
```
125+
await using var logFactory = NLog.LogManager.Setup().LoadConfigurationFromFile().LogFactory; // Automatic Shutdown()
126+
```
127+
128+
The NLog LogFactory `Dispose()`-method has been changed to skip flush with help from worker-threads,
129+
but will only perform synchronous NLog Target Close.
130+
131+
### NLog GelfTarget and GelfLayout
132+
133+
The NLog.Targets.NetworkTarget nuget-package also includes support for the Graylog Extended Log Format (GELF).
134+
135+
The `GelfTarget` extends the standard `NetworkTarget` with the new `GelfLayout`.
136+
137+
It depends on the builtin NLog JSON serializer, but follows the 'standard' of prefixing all
138+
custom property-names with underscore `_`.
139+
140+
## NLog SyslogTarget and SyslogLayout
141+
142+
The NLog.Targets.NetworkTarget nuget-package also includes support for the Syslog Output Format.
143+
144+
The `SyslogTarget` extends the standard `NetworkTarget` with the new `SyslogLayout`.
145+
146+
The `SyslogLayout` supports both RFC-3164 (simple) + RFC-5424 (structured) logging output.
147+
148+
### NLog NetworkTarget with NoDelay = true
149+
150+
The NLog.Targets.NetworkTarget nuget-package includes support for configuring TCP_NODELAY.
151+
The `NetworkTarget` will by default use `NoDelay = true` to turn off delayed ACK,
152+
to avoid delays of 200ms because of nagle-algorithm.
153+
154+
Believe most users will not notice the overhead of additional ACK-packages, but will notice
155+
a delay of 200ms.
156+
157+
### NLog NetworkTarget with SendTimeoutSeconds = 100
158+
159+
The NLog.Targets.NetworkTarget nuget-package changes the default value of TCP SendTimeout
160+
from waiting forever to 100 secs.
161+
162+
The `NetworkTarget` should now react to the network-cable being unplugged and the TCP send-window being filled.
163+
164+
The `NetworkTarget` should now automatically attempt to reconnect when the endpoint suddenly becomes unresponsive.
165+
166+
### NLog NetworkTarget with SslCertificateFile
167+
168+
The NLog.Targets.NetworkTarget nuget-package introduces the ability to specify custom SSL certificate from file.
169+
170+
The `NetworkTarget` now recognizes these new settings:
171+
- `Layout SslCertificateFile`
172+
- `Layout SslCertificatePassword`
173+
174+
The `NetworkTarget` can now perform SSL handshake with custom SSL certificate from file, without needing to register the certificate in the global operating-system cache.
175+
176+
## Breaking changes
177+
178+
### Removed legacy Target-Frameworks
179+
NetStandard 1.3 and NetStandard 1.5 has now been removed, since less relevant as most have moved to NetStandard 2.0 (or newer).
180+
181+
Removes platform support for:
182+
183+
- NET CoreApp 1.0 + 1.1
184+
- UAP + UAP10.0 (UWP ver. 1)
185+
- Tizen30
186+
187+
Considering to also remove NET35 + NET45, since those Target-Frameworks requires extra effort to build when using Visual Studio 2022.
188+
Removing old Target-Frameworks will also reduce the file-size of the NLog-nuget-package.
189+
If this will break your entire eco-system then [Please tell](https://github.com/NLog/NLog/issues/4931).
190+
191+
### NLog Structured Message formatting without quotes
192+
193+
NLog v4.5 introduced support for message-templates, where it followed the Serilog approach by adding quotes around string-values:
194+
```csharp
195+
Logger.Info("Hello {World}", "Earth"); // Outputs Hello "Earth" with NLog v4.5
196+
```
197+
198+
Microsoft Extension Logging decided not to implement that behavior, and now NLog also changes to not using quotes by default. Thus avoiding surprises when using NLog Logger directly instead as LoggingProvider for Microsoft Extension Logging.
199+
200+
To apply string-quotes for a single value:
201+
```csharp
202+
Logger.Info("Hello {@World}", "Earth"); // Outputs Hello "Earth" with NLog v6
203+
```
204+
205+
It is possible to globally revert to old behavior:
206+
```csharp
207+
LogManager.Setup().SetupSerialization(s => s.RegisterValueFormatterWithStringQuotes());
208+
```
209+
210+
### NLog JsonLayout EscapeForwardSlash obsolete
211+
212+
NLog v5 changed `JsonLayout` to have the default value `EscapeForwardSlash = false`, and now NLog v6
213+
marks the NLog `JsonLayout` `EscapeForwardSlash` as completely obsolete and no longer having any effect.
214+
215+
### NLog JsonLayout SuppressSpaces default true
216+
217+
The `JsonLayout` now have the new default value `SuppressSpaces = true`,
218+
since log-file-size / network-traffic-usage doesn't benefit from the extra spaces.
219+
220+
If the output from `JsonLayout` needs to be more human readable, then one can explictly assign
221+
`SuppressSpaces = false` or `IndentJson = true`.
222+
223+
### NLog ColoredConsoleTarget with Errors in red
224+
225+
NLog `ColoredConsoleTarget` used the color Yellow for Errors and Magenta for Warnings.
226+
This has now been changed to color Red for Errors and Yellow for Warnings.
227+
228+
This is to align with the normal color standards that most other systems seems to be using.
229+
230+
### NLog ColoredConsoleTarget without RegEx
231+
232+
RegularExpressions (RegEx) is a huge API, and a big dependency for a logging library,
233+
so to reduce the footprint of NLog then RegEx support have been removed.
234+
235+
This means word-highlighting rules no longer can scan for word-matches using RegEx.
236+
But logic has been implemented to continue support `IgnoreCase` and `WholeWords`
237+
for the string-matching logic.
238+
239+
### NLog Replace LayoutRenderer without RegEx
240+
241+
RegularExpressions (RegEx) is a huge API, and a big dependency for a logging library,
242+
so to reduce the footprint of NLog then RegEx support have been removed.
243+
244+
Logic has been implemented to continue support `IgnoreCase` and `WholeWords`
245+
for the string-matching logic.
246+
247+
This means the following has been removed for the `${replace}` LayoutRenderer:
248+
- `bool RegEx`
249+
- `bool CompileRegex`
250+
- `string ReplaceGroupName`
251+
252+
If RegEx replace-logic is important then one can use the new nuget-package `NLog.RegEx`, which includes `${regex-replace}`.
253+
254+
### NLog InternalLogger without LogToTrace
255+
256+
NLog `InternalLogger.LogToTrace` has been remnoved. This reduces the NLog footprint by
257+
removing references to `System.Diagnostics.Trace` and `System.Diagnostics.TraceListener`.
258+
259+
If it is important to redirect NLog InternalLogger output to `System.Diagnostics.Trace`,
260+
then one can use NLog `InternalLogger.LogWriter` to assign a custom `StringWriter` that performs the forwarding.
261+
Alternative one can setup custom subscriber to NLog `InternalLogger.InternalEventOccurred` event handler.
262+
263+
### NLog XmlParser replaces XmlReader
264+
265+
The .NET `System.Xml.XmlReader` is a heavy dependency that both loads XML using HttpClient, and support
266+
code generation to optimize serialization for types. To reduce dependencies and minimize AOT-build-filesize,
267+
then NLog now includes its own XML-parser.
268+
269+
It could have been nice if Microsoft could refactor `System.Xml.XmlReader`,
270+
so it only introduced a minimal AOT-footprint, but that is probably too late.
271+
272+
The NLog XML-parser only provides basic XML support, but it should be able to load any XML file that was
273+
working with NLog v5.
274+
275+
### NLog EventLog with more Layout
276+
Use Layout for Log + MachineName + MaxMessageLength + MaxKilobytes
277+
278+
### NLog SimpleLayout Immutable
279+
NLog `SimpleLayout` have removed the setter-method for its `Text`-property, and is now a sealed class.
280+
281+
This is to simpilfy the NLog `SimpleLayout` API, and to make it clear that NLog will optimize based on the initial layout.
282+
283+
### Minimal Logger-API
284+
Not ready yet, and post-poned because major breaking change, which makes it harder to test first NLog v6-Preview.
285+
286+
### Logger API with string interpolation
287+
Not ready yet, and post-poned because waiting for minimal Logger-API
288+
289+
Idea is to skip string interpolation, when LogLevel is not enabled.
290+
291+
### Logger API with ReadOnlySpan params
292+
Not ready yet, and post-poned because waiting for minimal Logger-API
293+
294+
Idea is to skip params array-allocation, when LogLevel is not enabled.
295+
296+
And if structured-logging then skip params allocation, but only rely on properties-dictionary.
297+
298+
### NLog Nullable References
299+
Not ready yet, and post-poned because waiting for minimal Logger-API
300+
301+
## Many other improvements
302+
303+
For full list of all changes: [NLog 6.0 Pull Requests](https://github.com/NLog/NLog/pulls?q=is%3Apr+is%3Amerged+milestone:%226.0%22)
304+
305+
- [Breaking Changes](https://github.com/NLog/NLog/pulls?q=is%3Apr+label%3A%22breaking%20change%22+is%3Amerged+milestone:%226.0%22)
306+
- [Breaking Behavior Changes](https://github.com/NLog/NLog/pulls?q=is%3Apr+label%3A%22breaking%20behavior%20change%22+is%3Amerged+milestone:%226.0%22)
307+
- [Features](https://github.com/NLog/NLog/pulls?q=is%3Apr+label%3A%22Feature%22+is%3Amerged+milestone:%226.0%22)
308+
- [Improvements](https://github.com/NLog/NLog/pulls?q=is%3Apr+label%3A%22Enhancement%22+is%3Amerged+milestone:%226.0%22)
309+
- [Performance](https://github.com/NLog/NLog/pulls?q=is%3Apr+label%3A%22Performance%22+is%3Amerged+milestone:%226.0%22)

0 commit comments

Comments
 (0)