Skip to content

Commit 4b52550

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 de58300 commit 4b52550

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
@@ -67,6 +67,12 @@ public ConfigurationReaderOptions() : this(dependencyContext: null)
6767
/// </summary>
6868
public Action<string, LoggingLevelSwitch>? OnLevelSwitchCreated { get; init; }
6969

70+
/// <summary>
71+
/// Called when a log filter switch is created while reading the <c>Serilog:FilterSwitches</c> section of the configuration.
72+
/// The switch name includes the leading <c>$</c> character.
73+
/// </summary>
74+
public Action<string, ILoggingFilterSwitch>? OnFilterSwitchCreated { get; init; }
75+
7076
internal Assembly[]? Assemblies { get; }
7177
internal DependencyContext? DependencyContext { get; }
7278
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
@@ -1406,4 +1406,35 @@ public void TestLogLevelSwitchesCallback(string switchName)
14061406
var systemThreading = Assert.Contains("System.Threading", switches);
14071407
Assert.Equal(LogEventLevel.Debug, systemThreading.MinimumLevel);
14081408
}
1409+
1410+
[Theory]
1411+
[InlineData("$switch1", "$switch2")]
1412+
[InlineData("$switch1", "switch2")]
1413+
[InlineData("switch1", "$switch2")]
1414+
[InlineData("switch1", "switch2")]
1415+
public void TestLogFilterSwitchesCallback(string switch1Name, string switch2Name)
1416+
{
1417+
var json = $$"""
1418+
{
1419+
'Serilog': {
1420+
'FilterSwitches': {
1421+
'{{switch1Name}}': 'Prop = 1',
1422+
'{{switch2Name}}': 'Prop = 2'
1423+
}
1424+
}
1425+
}
1426+
""";
1427+
1428+
IDictionary<string, ILoggingFilterSwitch> switches = new Dictionary<string, ILoggingFilterSwitch>();
1429+
var readerOptions = new ConfigurationReaderOptions { OnFilterSwitchCreated = (name, filterSwitch) => switches[name] = filterSwitch };
1430+
ConfigFromJson(json, options: readerOptions);
1431+
1432+
Assert.Equal(2, switches.Count);
1433+
1434+
var switch1 = Assert.Contains("$switch1", switches);
1435+
Assert.Equal("Prop = 1", switch1.Expression);
1436+
1437+
var switch2 = Assert.Contains("$switch2", switches);
1438+
Assert.Equal("Prop = 2", switch2.Expression);
1439+
}
14091440
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ namespace Serilog.Settings.Configuration
4444
public ConfigurationReaderOptions(Serilog.Settings.Configuration.ConfigurationAssemblySource configurationAssemblySource) { }
4545
public ConfigurationReaderOptions(params System.Reflection.Assembly[] assemblies) { }
4646
public System.IFormatProvider? FormatProvider { get; init; }
47+
public System.Action<string, Serilog.Settings.Configuration.ILoggingFilterSwitch>? OnFilterSwitchCreated { get; init; }
4748
public System.Action<string, Serilog.Core.LoggingLevelSwitch>? OnLevelSwitchCreated { get; init; }
4849
public string? SectionName { get; init; }
4950
}
51+
public interface ILoggingFilterSwitch
52+
{
53+
string? Expression { get; set; }
54+
}
5055
}

0 commit comments

Comments
 (0)