Skip to content

Commit 26945f1

Browse files
authored
Merge pull request #366 from 0xced/LogFilterSwitches
Add a callback on the reader options to expose the log filter switches
2 parents 321156e + 7f5c27f commit 26945f1

File tree

8 files changed

+73
-3
lines changed

8 files changed

+73
-3
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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ void ProcessFilterSwitchDeclarations()
7676
SubscribeToFilterExpressionChanges();
7777

7878
_resolutionContext.AddFilterSwitch(switchName, filterSwitch);
79+
_resolutionContext.ReaderOptions.OnFilterSwitchCreated?.Invoke(switchName, filterSwitch);
7980

8081
void SubscribeToFilterExpressionChanges()
8182
{

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ 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+
/// </summary>
83+
public Action<string, ILoggingFilterSwitch>? OnFilterSwitchCreated { get; init; }
84+
8085
internal Assembly[]? Assemblies { get; }
8186
internal DependencyContext? DependencyContext { get; }
8287
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;

src/Serilog.Settings.Configuration/Settings/Configuration/ResolutionContext.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,12 @@ public string AddLevelSwitch(string levelSwitchName, LoggingLevelSwitch levelSwi
6262
return referenceName;
6363
}
6464

65-
public string AddFilterSwitch(string filterSwitchName, LoggingFilterSwitchProxy filterSwitch)
65+
public void AddFilterSwitch(string filterSwitchName, LoggingFilterSwitchProxy filterSwitch)
6666
{
6767
if (filterSwitchName == null) throw new ArgumentNullException(nameof(filterSwitchName));
6868
if (filterSwitch == null) throw new ArgumentNullException(nameof(filterSwitch));
6969
var referenceName = ToSwitchReference(filterSwitchName);
7070
_declaredFilterSwitches[referenceName] = filterSwitch;
71-
return referenceName;
7271
}
7372

7473
string ToSwitchReference(string switchName)

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

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

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)