Skip to content

Commit 3fea9f7

Browse files
committed
Add a callback on the reader options to expose the log filter switches
Just like it was done for log level switches in #352.
1 parent 325577e commit 3fea9f7

File tree

7 files changed

+77
-2
lines changed

7 files changed

+77
-2
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,22 @@ Using this package you can also declare `LoggingFilterSwitch`-es in custom secti
275275

276276
Level updates to switches are also respected for a dynamic update.
277277

278+
Since version 4.0.0, filter switches are exposed through a callback on the reader options so that a reference can be kept:
279+
280+
```csharp
281+
var filterSwitches = new Dictionary<string, ILoggingFilterSwitch>();
282+
var options = new ConfigurationReaderOptions
283+
{
284+
OnFilterSwitchCreated = (switchName, filterSwitch) => filterSwitches[switchName] = filterSwitch
285+
};
286+
287+
var logger = new LoggerConfiguration()
288+
.ReadFrom.Configuration(configuration, options)
289+
.CreateLogger();
290+
291+
ILoggingFilterSwitch filterSwitch = filterSwitches["$filterSwitch"];
292+
```
293+
278294
### Nested configuration sections
279295

280296
Some Serilog packages require a reference to a logger configuration object. The sample program in this project illustrates this with the following entry configuring the _[Serilog.Sinks.Async](https://github.com/serilog/serilog-sinks-async)_ package to wrap the _[Serilog.Sinks.File](https://github.com/serilog/serilog-sinks-file)_ package. The `configure` parameter references the File sink configuration:

src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ void ProcessFilterSwitchDeclarations()
7575
SetFilterSwitch(throwOnError: true);
7676
SubscribeToFilterExpressionChanges();
7777

78-
_resolutionContext.AddFilterSwitch(switchName, filterSwitch);
78+
var referenceName = _resolutionContext.AddFilterSwitch(switchName, filterSwitch);
79+
_resolutionContext.ReaderOptions.OnFilterSwitchCreated?.Invoke(referenceName, filterSwitch);
7980

8081
void SubscribeToFilterExpressionChanges()
8182
{

src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReaderOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ public ConfigurationReaderOptions() : this(dependencyContext: null)
7777
/// </summary>
7878
public Action<string, LoggingLevelSwitch>? OnLevelSwitchCreated { get; init; }
7979

80+
/// <summary>
81+
/// Called when a log filter switch is created while reading the <c>Serilog:FilterSwitches</c> section of the configuration.
82+
/// The switch name includes the leading <c>$</c> character.
83+
/// </summary>
84+
public Action<string, ILoggingFilterSwitch>? OnFilterSwitchCreated { get; init; }
85+
8086
internal Assembly[]? Assemblies { get; }
8187
internal DependencyContext? DependencyContext { get; }
8288
internal ConfigurationAssemblySource? ConfigurationAssemblySource { get; }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Serilog.Settings.Configuration;
2+
3+
/// <summary>
4+
/// A log event filter that can be modified at runtime.
5+
/// </summary>
6+
/// <remarks>
7+
/// Under the hood, the logging filter switch is either a <c>Serilog.Expressions.LoggingFilterSwitch</c> or a <c>Serilog.Filters.Expressions.LoggingFilterSwitch</c> instance.
8+
/// </remarks>
9+
public interface ILoggingFilterSwitch
10+
{
11+
/// <summary>
12+
/// A filter expression against which log events will be tested.
13+
/// Only expressions that evaluate to <c>true</c> are included by the filter. A <c>null</c> expression will accept all events.
14+
/// </summary>
15+
public string? Expression { get; set; }
16+
}

src/Serilog.Settings.Configuration/Settings/Configuration/LoggingFilterSwitchProxy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace Serilog.Settings.Configuration;
22

3-
class LoggingFilterSwitchProxy
3+
class LoggingFilterSwitchProxy : ILoggingFilterSwitch
44
{
55
readonly Action<string?> _setProxy;
66
readonly Func<string?> _getProxy;

test/Serilog.Settings.Configuration.Tests/ConfigurationSettingsTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,4 +1547,35 @@ public void TestLogLevelSwitchesCallback(string switchName)
15471547
var systemThreading = Assert.Contains("System.Threading", switches);
15481548
Assert.Equal(LogEventLevel.Debug, systemThreading.MinimumLevel);
15491549
}
1550+
1551+
[Theory]
1552+
[InlineData("$switch1", "$switch2")]
1553+
[InlineData("$switch1", "switch2")]
1554+
[InlineData("switch1", "$switch2")]
1555+
[InlineData("switch1", "switch2")]
1556+
public void TestLogFilterSwitchesCallback(string switch1Name, string switch2Name)
1557+
{
1558+
var json = $$"""
1559+
{
1560+
'Serilog': {
1561+
'FilterSwitches': {
1562+
'{{switch1Name}}': 'Prop = 1',
1563+
'{{switch2Name}}': 'Prop = 2'
1564+
}
1565+
}
1566+
}
1567+
""";
1568+
1569+
IDictionary<string, ILoggingFilterSwitch> switches = new Dictionary<string, ILoggingFilterSwitch>();
1570+
var readerOptions = new ConfigurationReaderOptions { OnFilterSwitchCreated = (name, filterSwitch) => switches[name] = filterSwitch };
1571+
ConfigFromJson(json, options: readerOptions);
1572+
1573+
Assert.Equal(2, switches.Count);
1574+
1575+
var switch1 = Assert.Contains("$switch1", switches);
1576+
Assert.Equal("Prop = 1", switch1.Expression);
1577+
1578+
var switch2 = Assert.Contains("$switch2", switches);
1579+
Assert.Equal("Prop = 2", switch2.Expression);
1580+
}
15501581
}

test/Serilog.Settings.Configuration.Tests/Serilog.Settings.Configuration.approved.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ namespace Serilog.Settings.Configuration
4646
public bool AllowInternalMethods { get; init; }
4747
public bool AllowInternalTypes { get; init; }
4848
public System.IFormatProvider? FormatProvider { get; init; }
49+
public System.Action<string, Serilog.Settings.Configuration.ILoggingFilterSwitch>? OnFilterSwitchCreated { get; init; }
4950
public System.Action<string, Serilog.Core.LoggingLevelSwitch>? OnLevelSwitchCreated { get; init; }
5051
public string? SectionName { get; init; }
5152
}
53+
public interface ILoggingFilterSwitch
54+
{
55+
string? Expression { get; set; }
56+
}
5257
}

0 commit comments

Comments
 (0)