Anixe.IO.NLog.Extensions 4.0.1

dotnet add package Anixe.IO.NLog.Extensions --version 4.0.1
NuGet\Install-Package Anixe.IO.NLog.Extensions -Version 4.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Anixe.IO.NLog.Extensions" Version="4.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Anixe.IO.NLog.Extensions --version 4.0.1
#r "nuget: Anixe.IO.NLog.Extensions, 4.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Anixe.IO.NLog.Extensions as a Cake Addin
#addin nuget:?package=Anixe.IO.NLog.Extensions&version=4.0.1

// Install Anixe.IO.NLog.Extensions as a Cake Tool
#tool nuget:?package=Anixe.IO.NLog.Extensions&version=4.0.1

Anixe.IO.NLog.Extensions

The motivation to create this assembly is a need for logging large streams. The NLog itself is dependent on layout renderers system which always produces a string. In consequences, it makes the whole system prone to memory leaks. This assembly intruduces layour formatters system which depends only on stream provided by NLog target.

Layout Formatters

  • ILayoutFormatter - the main interface which allows to build custom formatter
  • LayoutFormatterBase - the abstract which provides only initialization and disposal routines. Useful to reduce some code.
  • ExceptionJsonFormatter - the formatter serializes exception taken from LogEventInfo.Exception into target stream in JSON format.
  • StreamFormatter - the formatter copies stream from provided property into the target stream
  • TransactionLayoutFormatter - the formatter serializes log message into structured, delimited, one liner message (like CSV) and copies it into stream, it has configuration:
    • Autoflush - FLush after each log entry, default: true
    • LogAllFields - Log into the stream all fields from 'Fields' property regardless if field's value in present in logEvent, default: true
    • Delimiter - Delimit fields with this sign, default: '|'
    • BufferSize - Used in copy data from log into the target stream, default: 4096
    • Encoding - Text encoding used in stream writer initialization, default: utf-8
    • Field - Define which fields must be logged from LogEventInfo.Properties, comma delimited values.

StreamFormatter and TransactionLayoutFormatter formatters expect log message to have everything put in LogEventInfo.Properties and configuration can be provided via the formatter properties

Targets

The assembly contains also predefined targets which works with layout formatters, but you can write your own.

TargetWrappers

The wrappers allows you to modify log stream on-the-fly during copy into the target's stream. It is handled by target wrapper for sake of separation of concerns and SPR.

  • StreamModifierWrapper - a wrapping target, modifies the message stream according to the set up modifier_attribute collection
    • FieldName - defines the key in LogEventInfo.Properties under which the stream will be present.
    • OneLiner - removed newline char from the stream. Useful when one log entry must fit into single line.
    • Base64 - If true then stream will be encoded into base64 ASCII (default: false).
    • Compress - If true then stream will be compressed (default: false). It has no side effect if the stream is already compressed.
    • CompressionThreshold - all logs below that threshold won't be compressed (default: 1024).
    • Decompress - If true then stream will be decompressed (default: false). It has no side effect if the stream is already decompressed.

It works in sequence oneliner->compress/decompress->encodebase64

Logger Metrics

Internal logger activity is exposed to the application via LoggingMetrics class which provides the following metrics:

  • LogsReceived - Incremented by one if AsyncFormattedLogFileTarget or AsyncConsoleTargetEx received any log to write
  • LogsWritten - Incremented by one if AsyncFormattedLogFileTarget or AsyncConsoleTargetEx managed to write any bytes
  • BytesWritten - Incremented by number of bytes written if AsyncFormattedLogFileTarget or AsyncConsoleTargetEx managed to write any bytes

Configuration

Everything can be configured in XML config.

  1. The example configures target to file with TransactionLayoutFormatter configured to format rid,mid,tid,Content-Type,Content-Encoding,data fields with LogTimestamp at first column delimited by | into the target's stream (file in this case). The StreamModifierWrapper will provide the data field (which is expected to be stream) as compressed, base64 encoded message.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true" autoReload="false">

  <extensions>
    <add assembly="Anixe.IO.NLog.Extensions"/>
  </extensions>

  <targets>
    <target type="StreamModifierWrapper" name="formatted_console">
      <modifier_attribute FieldName="data" Base64="true" Compress="true" />
      <target xsi:type="AsyncFormattedLogFileTarget" FileName="/var/log/transaction_logs.dat" FormatterType="Anixe.IO.NLog.Extensions.Formatters.TransactionLayoutFormatter">
        <formatter_attribute name="Fields" values="rid,mid,tid,Content-Type,Content-Encoding,data"/>
        <formatter_attribute name="Encoding" value="utf-8" />
        <formatter_attribute name="BufferSize" value="32000" />
        <formatter_attribute name="Delimiter" value="|" />
        <formatter_attribute name="LogTimestamp" value="true" />
      </target>
    </target>
  </targets>

  <rules>
    <logger name="System.Net.Http.HttpRequestMessage" minlevel="Debug" writeTo="formatted_console" />
    <logger name="System.Net.Http.HttpResponseMessage" minlevel="Debug" writeTo="formatted_console" />
  </rules>
</nlog>
  1. The example prints the stream into the console. Is also decompress compressed messages.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true" autoReload="false">

  <extensions>
    <add assembly="Anixe.IO.NLog.Extensions"/>
  </extensions>

  <targets>
    <target type="StreamModifierWrapper" name="console">
      <modifier_attribute FieldName="data" Decompress="true" />
      <target xsi:type="AsyncConsoleTargetEx" name="console" FormatterType="Anixe.IO.NLog.Extensions.Formatters.StreamFormatter">
        <formatter_attribute name="Field" value="data"/>
        <formatter_attribute name="BufferSize" value="32000"/>
      </target>
    </target>
  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="console" final="true" />
  </rules>
</nlog>
  1. Write HTTP messages into the transaction_logs.dat and exceptions into the exception_logs.dat
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true" autoReload="false">

  <extensions>
    <add assembly="Anixe.IO.NLog.Extensions"/>
  </extensions>

  <targets>
    <target type="StreamModifierWrapper" name="transactions_target">
      <modifier_attribute FieldName="data" Base64="true" Compress="true" />
      <target xsi:type="AsyncFormattedLogFileTarget" FileName="/var/log/transaction_logs.dat" FormatterType="Anixe.IO.NLog.Extensions.Formatters.TransactionLayoutFormatter">
        <formatter_attribute name="Fields" values="rid,mid,tid,Content-Type,Content-Encoding,data"/>
        <formatter_attribute name="Encoding" value="utf-8" />
        <formatter_attribute name="BufferSize" value="32000" />
        <formatter_attribute name="Delimiter" value="|" />
        <formatter_attribute name="LogTimestamp" value="true" />
      </target>
    </target>


    <target xsi:type="AsyncFormattedLogFileTarget" name="exception_target" FileName="/var/log/exception_logs.dat" FormatterType="Anixe.IO.NLog.Extensions.Formatters.ExceptionJsonFormatter" />
  </targets>

  <rules>
    <logger name="System.Net.Http.HttpRequestMessage" minlevel="Debug" writeTo="transactions_target" />
    <logger name="System.Net.Http.HttpResponseMessage" minlevel="Debug" writeTo="transactions_target" />
    <logger name="*Exception*" minlevel="Debug" writeTo="exception_target" />
  </rules>
</nlog>

FormattersFactory

Its worth to mention about the factory pattern which is responsible for creating layout formatters for configured targets because these entities don't belong to NLog's world. Check the FormattersFactory for details. Please set FormattersFactory.CreateInstanceFunc custom function if you need to resolve layout formatters from own DI container.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
4.0.1 135 4/26/2024
4.0.0 2,730 1/8/2024
3.0.1 789 12/4/2023
3.0.0 6,985 10/24/2022
2.1.1 798 10/5/2022
2.1.0 524 9/26/2022
2.0.2 2,161 6/21/2022
2.0.1 384 6/20/2022
2.0.0 475 6/14/2022
1.0.18 451 6/8/2022
1.0.17 5,785 8/31/2021
1.0.16 2,265 7/8/2021
1.0.15 320 7/8/2021
1.0.14 660 6/22/2021
1.0.13 1,208 1/27/2021
1.0.11 437 12/8/2020
1.0.10 1,785 7/21/2020
1.0.9 1,935 6/23/2020
1.0.8 496 5/29/2020
1.0.7 782 5/25/2020
1.0.6 484 5/12/2020
1.0.5 476 5/7/2020
1.0.4 584 4/24/2020
1.0.3 1,001 2/14/2020
1.0.2 680 1/14/2020
1.0.1 549 12/31/2019
1.0.0 492 12/11/2019

# Anixe.IO.NLog.Extensions CHANGELOG

## 4.0.1 - 2024-04-26

- Fix NullReferenceException thrown in FormattedLogFileTarget in some cases

## 4.0.0 - 2024-01-03

- Updated Anixe.IO from v3.1.0 to v4.0.0
- Updated NLog from v5.0.4 to v5.2.8

## 3.0.1 - 2023-12-05

- Update Anixe.IO to 3.1.0

## 3.0.0 - 2022-10-13

- drop support of all .NET versions before .NET 6
- Fixed string payloads were written synchronously in async targets

## 2.1.1 - 2022-10-04

- Fixed exception when reading Fields attribute from nlog config

## 2.1.0 - 2022-09-26

- Added nullable annotations
- Added build for .NET 6

## 2.0.2 - 2022-06-21

- Added synchronous NLog targets and formatter methods

## 2.0.1 - 2022-06-20

- Added writing logging errors inside AsyncFormattedLogFileTarget via InternalLogger https://github.com/NLog/NLog/wiki/Internal-Logging

## 2.0.0 - 2022-06-13

- Updated NLog to 5.0.1
- Changed target from netstandard2.0 to netstandard2.1
- Added support for `ReadOnlyMemory<byte>` fields that can be formatted

## 1.0.18 - 2022-06-06

- Added LoggingMetrics to expose LogsReceived, LogsWritten, BytesWritten data

## 1.0.16 - 2021-08-31

- Updated NLog to 4.7.11
- Updated Anixe.IO to 2.1.0

## 1.0.16 - 2021-07-08

### Added

- String handling in StreamModifierWrapper for Nexus logging

## 1.0.15 - 2021-07-08

### Added

- License information in package metadata

## 1.0.14 - 2021-06-22

### Fixed

* Log event timestamp. Is must be in UTC in order to calculate proper log replication lag in external logging systems (log_forwarder)