Serilog.Formatting.Log4Net
1.0.1
See the version list below for details.
dotnet add package Serilog.Formatting.Log4Net --version 1.0.1
NuGet\Install-Package Serilog.Formatting.Log4Net -Version 1.0.1
<PackageReference Include="Serilog.Formatting.Log4Net" Version="1.0.1" />
paket add Serilog.Formatting.Log4Net --version 1.0.1
#r "nuget: Serilog.Formatting.Log4Net, 1.0.1"
// Install Serilog.Formatting.Log4Net as a Cake Addin #addin nuget:?package=Serilog.Formatting.Log4Net&version=1.0.1 // Install Serilog.Formatting.Log4Net as a Cake Tool #tool nuget:?package=Serilog.Formatting.Log4Net&version=1.0.1
Serilog.Formatting.Log4Net is an add-on for Serilog to format log events as log4net or log4j compatible XML format.
You can use Log4View to look at log files produced with this formatter.
Getting started
Add the Serilog.Formatting.Log4Net NuGet package to your project using the NuGet Package Manager or run the following command:
dotnet add package Serilog.Formatting.Log4Net
Serilog.Formatting.Log4Net provides the Log4NetTextFormatter
class which implements Serilog's ITextFormatter interface.
Here's how to use it with a file sink in a simple Hello World app:
using System;
using Serilog;
using Serilog.Formatting.Log4Net;
static class Program
{
static void Main(string[] args)
{
var logger = new LoggerConfiguration()
.Enrich.WithProperty("AppName", "Program")
.WriteTo.File(new Log4NetTextFormatter(c => c.UseCDataMode(CDataMode.Never)), "logs.xml")
.CreateLogger();
logger.Information("Start app with {Args}", args);
Console.WriteLine("Hello World!");
logger.Information("Stop app");
}
}
Running this app writes the following XML events into the logs.xml
file in the current working directory:
<log4net:event timestamp="2021-02-24T18:23:40.4496605+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
<log4net:properties>
<log4net:data name="Args[0]" value="--first-argument" />
<log4net:data name="Args[1]" value="--second-argument" />
<log4net:data name="AppName" value="Program" />
</log4net:properties>
<log4net:message>Start app with ["--first-argument", "--second-argument"]</log4net:message>
</log4net:event>
<log4net:event timestamp="2021-02-24T18:23:40.5086666+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
<log4net:properties>
<log4net:data name="AppName" value="Program" />
</log4net:properties>
<log4net:message>Stop app</log4net:message>
</log4net:event>
Configuration
You can configure Log4NetTextFormatter
in multiple ways, the fluent options builder will help you discover all the possibilities.
Exception formatting
By default, Log4NetTextFormatter formats exception by calling ToString(). You can customise this behaviour by setting your own formatting delegate. For example, you could use Ben.Demystifier like this:
new Log4NetTextFormatter(c => c.UseExceptionFormatter(exception => exception.ToStringDemystified()))
CDATA
By default, Log4NetTextFormatter writes all messages and exceptions with a CDATA section. It is possible to configure it to use CDATA sections only when the message or exception contain &
, <
or >
by using CDataMode.IfNeeded
or to never write CDATA sections by using CDataMode.Never
:
new Log4NetTextFormatter(c => c.UseCDataMode(CDataMode.Never))
XML Namespace
You can remove the log4net
XML namespace by calling UseNoXmlNamespace()
on the options builder. This is useful if you want to spare some bytes and your log reader supports log4net XML events without namespace, like Log4View does.
new Log4NetTextFormatter(c => c.UseNoXmlNamespace())
Line ending
By default, Log4NetTextFormatter uses the line feed (LF) character for line ending between XML elements. You can choose to use CRLF if you need to:
new Log4NetTextFormatter(c => c.UseLineEnding(LineEnding.CarriageReturn | LineEnding.LineFeed))
Indentation
By default, Log4NetTextFormatter indents XML elements with two spaces. You can configure it to use either spaces or tabs. For example, indent XML elements with one tab:
new Log4NetTextFormatter(c => c.UseIndentationSettings(new IndentationSettings(Indentation.Tab, 1)))
Or you can use no indentation at all, having log4net events written on a single line:
new Log4NetTextFormatter(c => c.UseNoIndentation())
Format provider
By default, Log4NetTextFormatter uses the invariant culture (Serilog's default) when formatting Serilog properties that implement the IFormattable
interface. It can be configured to use culture-specific formatting information. For example, to use the Swiss French culture:
new Log4NetTextFormatter(c => c.UseFormatProvider(CultureInfo.GetCultureInfo("fr-CH")))
Property filter
By default, Log4NetTextFormatter serializes all Serilog properties. You can filter out some properties by configuring a custom property filter delegate:
new Log4NetTextFormatter(c => c.UsePropertyFilter((_, name) => name != "MySecretProperty"))
Log4j compatibility mode
The formatter also supports a log4j compatibility mode. Log4Net and Log4j XML formats are very similar but have a few key differences.
- The
event
elements are in different XML namespaces - The
timestamp
attribute is a number of milliseconds (log4j) vs an ISO 8061 formatted date (log4net) - Exception elements are named
throwable
vsexception
In order to enable the compatibility mode, call UseLog4JCompatibility()
:
new Log4NetTextFormatter(c => c.UseLog4JCompatibility())
Note that unlike other fluent configuration methods, this one can not be chained because you should not change options after enabling the log4j compatibility mode.
Combining options
You can also combine options, for example, using Ben.Demystifier for exception formatting, filtering properties and using the log4j compatibility mode. This sample configuration sends logs as UDP packages over the network with Serilog.Sinks.Udp and are viewable with Loginator:
var appFileName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
var processId = Process.GetCurrentProcess().Id;
var formatter = new Log4NetTextFormatter(c => c
.UseExceptionFormatter(exception => exception.ToStringDemystified())
.UsePropertyFilter((_, name) => name.StartsWith("log4j"))
.UseLog4JCompatibility()
);
Log.Logger = new LoggerConfiguration()
.Enrich.WithProperty("log4japp", $"{appFileName}({processId})")
.Enrich.WithProperty("log4jmachinename", Environment.MachineName)
.Enrich.WithThreadId()
.WriteTo.Udp("localhost", 7071, AddressFamily.InterNetwork, formatter)
.CreateLogger();
Enrichers
The log4Net XML format defines some special attributes which are not included by default in Serilog events. They can be added by using the appropriate Serilog enrichers.
Thread Id
Include the thread id in log4net events by using Serilog.Enrichers.Thread:
var loggerConfiguration = new LoggerConfiguration().Enrich.WithThreadId();
Domain and User Name
Include the domain and user name in log4net events by using Serilog.Enrichers.Environment:
var loggerConfiguration = new LoggerConfiguration().Enrich.WithEnvironmentUserName();
Machine Name
Include the machine name in log4net events by using Serilog.Enrichers.Environment:
var loggerConfiguration = new LoggerConfiguration().Enrich.WithMachineName();
Combining these three enrichers will produce a log event including thread
, domain
and username
attributes plus a log4net:HostName
property containing the machine name:
<event timestamp="2020-06-28T10:07:33.314159+02:00" level="INFO" thread="1" domain="TheDomainName" username="TheUserName">
<properties>
<data name="log4net:HostName" value="TheMachineName" />
</properties>
<message>The message</message>
</event>
Related projects
The Serilog.Sinks.Log4Net project is similar but depends on the log4net NuGet package whereas Serilog.Formatting.Log4Net does not. Also, Serilog.Sinks.Log4Net is a sink so you have to configure log4net in addition to configuring Serilog.
The Serilog.Sinks.Udp project also provides a Log4Net formatter but it writes XML manually (without using an XmlWriter), completely ignores Serilog properties, is not configurable at all (indentation, newlines, namespaces etc.) and is not documented.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
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 |
---|---|---|
1.2.0 | 1,739 | 9/10/2024 |
1.1.0 | 7,663 | 5/1/2023 |
1.0.2 | 7,172 | 2/11/2023 |
1.0.1 | 447 | 1/17/2023 |
1.0.0 | 5,613 | 3/8/2022 |
1.0.0-rc.4 | 215 | 11/2/2021 |
1.0.0-rc.3 | 204 | 10/24/2021 |
1.0.0-rc.2 | 312 | 4/1/2021 |
1.0.0-rc.1 | 204 | 2/5/2021 |
1.0.0-alpha.0.110 | 162 | 2/4/2021 |
1.0.0-alpha.0.104 | 162 | 2/3/2021 |
1.0.0-alpha.0.103 | 161 | 2/3/2021 |
1.0.0-alpha.0.97.5 | 162 | 2/3/2021 |