Skip to content

Commit 105c323

Browse files
committed
[WIP] Constructor for Serilog.Settings.Configuration
1 parent e458529 commit 105c323

6 files changed

+178
-0
lines changed

src/Log4NetTextFormatter.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,40 @@ public Log4NetTextFormatter(Action<Log4NetTextFormatterOptionsBuilder>? configur
9393
_usesLog4JCompatibility = ReferenceEquals(Log4NetTextFormatterOptionsBuilder.Log4JXmlNamespace, _options.XmlNamespace);
9494
}
9595

96+
/// <summary>
97+
/// Do not use this constructor. It is only available for the Serilog.Settings.Configuration integration.
98+
/// </summary>
99+
[Obsolete("This constructor is only for use by the Serilog.Settings.Configuration package.", error: true)]
100+
[SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "Used by Serilog.Settings.Configuration through reflection.")]
101+
public Log4NetTextFormatter(
102+
IFormatProvider? formatProvider = null,
103+
CDataMode? cDataMode = null,
104+
string? nullText = null,
105+
bool noXmlNamespace = false,
106+
LineEnding? lineEnding = null,
107+
IndentationSettings? indentationSettings = null,
108+
bool noIndentation = false,
109+
PropertyFilter? propertyFilter = null,
110+
MessageFormatter? messageFormatter = null,
111+
ExceptionFormatter? exceptionFormatter = null,
112+
bool log4JCompatibility = false
113+
) : this(options =>
114+
{
115+
if (formatProvider != null) options.UseFormatProvider(formatProvider);
116+
if (cDataMode != null) options.UseCDataMode(cDataMode.Value);
117+
if (nullText != null) options.UseNullText(nullText);
118+
if (noXmlNamespace) options.UseNoXmlNamespace();
119+
if (lineEnding != null) options.UseLineEnding(lineEnding.Value);
120+
if (indentationSettings != null) options.UseIndentationSettings(indentationSettings);
121+
if (noIndentation) options.UseNoIndentation();
122+
if (propertyFilter != null) options.UsePropertyFilter(propertyFilter);
123+
if (messageFormatter != null) options.UseMessageFormatter(messageFormatter);
124+
if (exceptionFormatter != null) options.UseExceptionFormatter(exceptionFormatter);
125+
if (log4JCompatibility) options.UseLog4JCompatibility();
126+
})
127+
{
128+
}
129+
96130
/// <summary>
97131
/// Format the log event as log4net or log4j compatible XML format into the output.
98132
/// </summary>

tests/PublicApi.net6.0.verified.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class Log4NetTextFormatter : Serilog.Formatting.ITextFormatter
3131
{
3232
public Log4NetTextFormatter() { }
3333
public Log4NetTextFormatter(System.Action<Serilog.Formatting.Log4Net.Log4NetTextFormatterOptionsBuilder>? configureOptions) { }
34+
[System.Obsolete("This constructor is only for use by the Serilog.Settings.Configuration package.", true)]
35+
public Log4NetTextFormatter(System.IFormatProvider? formatProvider = null, Serilog.Formatting.Log4Net.CDataMode? cDataMode = default, string? nullText = null, bool noXmlNamespace = false, Serilog.Formatting.Log4Net.LineEnding? lineEnding = default, Serilog.Formatting.Log4Net.IndentationSettings? indentationSettings = null, bool noIndentation = false, Serilog.Formatting.Log4Net.PropertyFilter? propertyFilter = null, Serilog.Formatting.Log4Net.MessageFormatter? messageFormatter = null, Serilog.Formatting.Log4Net.ExceptionFormatter? exceptionFormatter = null, bool log4JCompatibility = false) { }
3436
public static Serilog.Formatting.Log4Net.Log4NetTextFormatter Log4JFormatter { get; }
3537
public void Format(Serilog.Events.LogEvent logEvent, System.IO.TextWriter output) { }
3638
}

tests/PublicApi.net8.0.verified.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public class Log4NetTextFormatter : Serilog.Formatting.ITextFormatter
3232
{
3333
public Log4NetTextFormatter() { }
3434
public Log4NetTextFormatter(System.Action<Serilog.Formatting.Log4Net.Log4NetTextFormatterOptionsBuilder>? configureOptions) { }
35+
[System.Obsolete("This constructor is only for use by the Serilog.Settings.Configuration package.", true)]
36+
public Log4NetTextFormatter(System.IFormatProvider? formatProvider = null, Serilog.Formatting.Log4Net.CDataMode? cDataMode = default, string? nullText = null, bool noXmlNamespace = false, Serilog.Formatting.Log4Net.LineEnding? lineEnding = default, Serilog.Formatting.Log4Net.IndentationSettings? indentationSettings = null, bool noIndentation = false, Serilog.Formatting.Log4Net.PropertyFilter? propertyFilter = null, Serilog.Formatting.Log4Net.MessageFormatter? messageFormatter = null, Serilog.Formatting.Log4Net.ExceptionFormatter? exceptionFormatter = null, bool log4JCompatibility = false) { }
3537
public static Serilog.Formatting.Log4Net.Log4NetTextFormatter Log4JFormatter { get; }
3638
public void Format(Serilog.Events.LogEvent logEvent, System.IO.TextWriter output) { }
3739
}

tests/PublicApi.netstandard2.0.verified.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class Log4NetTextFormatter : Serilog.Formatting.ITextFormatter
3131
{
3232
public Log4NetTextFormatter() { }
3333
public Log4NetTextFormatter(System.Action<Serilog.Formatting.Log4Net.Log4NetTextFormatterOptionsBuilder>? configureOptions) { }
34+
[System.Obsolete("This constructor is only for use by the Serilog.Settings.Configuration package.", true)]
35+
public Log4NetTextFormatter(System.IFormatProvider? formatProvider = null, Serilog.Formatting.Log4Net.CDataMode? cDataMode = default, string? nullText = null, bool noXmlNamespace = false, Serilog.Formatting.Log4Net.LineEnding? lineEnding = default, Serilog.Formatting.Log4Net.IndentationSettings? indentationSettings = null, bool noIndentation = false, Serilog.Formatting.Log4Net.PropertyFilter? propertyFilter = null, Serilog.Formatting.Log4Net.MessageFormatter? messageFormatter = null, Serilog.Formatting.Log4Net.ExceptionFormatter? exceptionFormatter = null, bool log4JCompatibility = false) { }
3436
public static Serilog.Formatting.Log4Net.Log4NetTextFormatter Log4JFormatter { get; }
3537
public void Format(Serilog.Events.LogEvent logEvent, System.IO.TextWriter output) { }
3638
}

tests/Serilog.Formatting.Log4Net.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
<ItemGroup>
99
<PackageReference Include="AwesomeAssertions" Version="9.1.0" />
1010
<PackageReference Include="coverlet.collector" Version="6.0.4" PrivateAssets="all" />
11+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.9" />
1112
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
1213
<PackageReference Include="PublicApiGenerator" Version="11.4.6" />
14+
<PackageReference Include="ReflectionMagic" Version="5.0.1" />
1315
<PackageReference Include="ReportGenerator" Version="5.4.13" PrivateAssets="all" />
1416
<PackageReference Include="Serilog" Version="4.3.0" />
1517
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
1618
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
19+
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
20+
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
1721
<PackageReference Include="Verify.Xunit" Version="30.17.0" />
1822
<PackageReference Include="xunit" Version="2.9.3" />
1923
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" PrivateAssets="all" />
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Text;
5+
using System.Xml;
6+
using AwesomeAssertions;
7+
using Microsoft.Extensions.Configuration;
8+
using ReflectionMagic;
9+
using Serilog.Core;
10+
using Serilog.Settings.Configuration;
11+
using Serilog.Sinks.File;
12+
using Xunit;
13+
14+
namespace Serilog.Formatting.Log4Net.Tests;
15+
16+
public class SerilogSettingsConfigurationTest
17+
{
18+
[Fact]
19+
public void ConfigureDefault()
20+
{
21+
// lang=json
22+
var config =
23+
"""
24+
{
25+
"Serilog": {
26+
"WriteTo:File": {
27+
"Name": "File",
28+
"Args": {
29+
"path": "logs.xml",
30+
"formatter": {
31+
"type": "Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net"
32+
}
33+
}
34+
}
35+
}
36+
}
37+
""";
38+
39+
var options = GetLog4NetTextFormatterOptions(config);
40+
IFormatProvider? formatProvider = GetFormatProvider(options);
41+
CDataMode cDataMode = GetCDataMode(options);
42+
string nullText = GetNullText(options);
43+
XmlQualifiedName? xmlNamespace = GetXmlNamespace(options);
44+
XmlWriterSettings xmlWriterSettings = GetXmlWriterSettings(options);
45+
PropertyFilter filterProperty = GetFilterProperty(options);
46+
MessageFormatter formatMessage = GetFormatMessage(options);
47+
ExceptionFormatter formatException = GetFormatException(options);
48+
49+
formatProvider.Should().BeNull();
50+
cDataMode.Should().Be(CDataMode.Always);
51+
nullText.Should().Be("(null)");
52+
xmlNamespace.Should().BeEquivalentTo(new XmlQualifiedName("log4net", "http://logging.apache.org/log4net/schemas/log4net-events-1.2/"));
53+
}
54+
55+
[Theory]
56+
[InlineData(CDataMode.Always)]
57+
[InlineData(CDataMode.Never)]
58+
[InlineData(CDataMode.IfNeeded)]
59+
public void ConfigureCDataMode(CDataMode inputCDataMode)
60+
{
61+
// lang=json
62+
var config =
63+
$$"""
64+
{
65+
"Serilog": {
66+
"WriteTo:File": {
67+
"Name": "File",
68+
"Args": {
69+
"path": "logs.xml",
70+
"formatter": {
71+
"type": "Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net",
72+
"cDataMode": "{{inputCDataMode}}"
73+
}
74+
}
75+
}
76+
}
77+
}
78+
""";
79+
80+
CDataMode cDataMode = GetCDataMode(GetLog4NetTextFormatterOptions(config));
81+
82+
cDataMode.Should().Be(inputCDataMode);
83+
}
84+
85+
[Theory]
86+
[InlineData("")]
87+
[InlineData("<null>")]
88+
[InlineData("🌀")]
89+
public void ConfigureNullText(string inputNullText)
90+
{
91+
// lang=json
92+
var config =
93+
$$"""
94+
{
95+
"Serilog": {
96+
"WriteTo:File": {
97+
"Name": "File",
98+
"Args": {
99+
"path": "logs.xml",
100+
"formatter": {
101+
"type": "Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net",
102+
"nullText": "{{inputNullText}}"
103+
}
104+
}
105+
}
106+
}
107+
}
108+
""";
109+
110+
string nullText = GetNullText(GetLog4NetTextFormatterOptions(config));
111+
112+
nullText.Should().Be(inputNullText);
113+
}
114+
115+
private static IFormatProvider? GetFormatProvider(dynamic options) => options.FormatProvider;
116+
private static CDataMode GetCDataMode(dynamic options) => options.CDataMode;
117+
private static string GetNullText(dynamic options) => options.NullText;
118+
private static XmlQualifiedName? GetXmlNamespace(dynamic options) => options.XmlNamespace;
119+
private static XmlWriterSettings GetXmlWriterSettings(dynamic options) => options.XmlWriterSettings;
120+
private static PropertyFilter GetFilterProperty(dynamic options) => options.FilterProperty;
121+
private static MessageFormatter GetFormatMessage(dynamic options) => options.FormatMessage;
122+
private static ExceptionFormatter GetFormatException(dynamic options) => options.FormatException;
123+
124+
private static dynamic GetLog4NetTextFormatterOptions(string config)
125+
{
126+
using var configStream = new MemoryStream(Encoding.UTF8.GetBytes(config));
127+
var configuration = new ConfigurationBuilder().AddJsonStream(configStream).Build();
128+
var options = new ConfigurationReaderOptions(typeof(ILogger).Assembly, typeof(FileSink).Assembly, typeof(Log4NetTextFormatter).Assembly);
129+
using var logger = new LoggerConfiguration().ReadFrom.Configuration(configuration, options).CreateLogger();
130+
IEnumerable<ILogEventSink> sinks = logger.AsDynamic()._sink._sinks;
131+
var fileSink = sinks.Should().ContainSingle().Which.Should().BeOfType<FileSink>().Subject;
132+
return fileSink.AsDynamic()._textFormatter._options;
133+
}
134+
}

0 commit comments

Comments
 (0)