Skip to content

Commit d28357d

Browse files
committed
Add a way to get the configured log level switches
Fixes serilog#206
1 parent ab87641 commit d28357d

File tree

6 files changed

+133
-18
lines changed

6 files changed

+133
-18
lines changed

src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ public static LoggerConfiguration Configuration(
4747
IConfiguration configuration,
4848
string sectionName,
4949
DependencyContext dependencyContext = null)
50+
{
51+
return Configuration(settingConfiguration, configuration, sectionName, out _, dependencyContext);
52+
}
53+
54+
/// <summary>
55+
/// Reads logger settings from the provided configuration object using the provided section name. Generally this
56+
/// is preferable over the other method that takes a configuration section. Only this version will populate
57+
/// IConfiguration parameters on target methods.
58+
/// </summary>
59+
/// <param name="settingConfiguration">Logger setting configuration.</param>
60+
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
61+
/// <param name="sectionName">A section name for section which contains a Serilog section.</param>
62+
/// <param name="loadedConfiguration">Contains information about the loaded configuration upon return.</param>
63+
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
64+
/// default will be used.</param>
65+
/// <returns>An object allowing configuration to continue.</returns>
66+
public static LoggerConfiguration Configuration(
67+
this LoggerSettingsConfiguration settingConfiguration,
68+
IConfiguration configuration,
69+
string sectionName,
70+
out LoadedConfiguration loadedConfiguration,
71+
DependencyContext dependencyContext = null)
5072
{
5173
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
5274
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
@@ -56,11 +78,10 @@ public static LoggerConfiguration Configuration(
5678
? AssemblyFinder.Auto()
5779
: AssemblyFinder.ForDependencyContext(dependencyContext);
5880

59-
return settingConfiguration.Settings(
60-
new ConfigurationReader(
61-
configuration.GetSection(sectionName),
62-
assemblyFinder,
63-
configuration));
81+
var configurationReader = new ConfigurationReader(configuration.GetSection(sectionName), assemblyFinder, configuration);
82+
var loggerConfiguration = settingConfiguration.Settings(configurationReader);
83+
loadedConfiguration = configurationReader.GetLoadedConfiguration();
84+
return loggerConfiguration;
6485
}
6586

6687
/// <summary>
@@ -79,6 +100,24 @@ public static LoggerConfiguration Configuration(
79100
DependencyContext dependencyContext = null)
80101
=> Configuration(settingConfiguration, configuration, DefaultSectionName, dependencyContext);
81102

103+
/// <summary>
104+
/// Reads logger settings from the provided configuration object using the default section name. Generally this
105+
/// is preferable over the other method that takes a configuration section. Only this version will populate
106+
/// IConfiguration parameters on target methods.
107+
/// </summary>
108+
/// <param name="settingConfiguration">Logger setting configuration.</param>
109+
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
110+
/// <param name="loadedConfiguration">Contains information about the loaded configuration upon return.</param>
111+
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
112+
/// default will be used.</param>
113+
/// <returns>An object allowing configuration to continue.</returns>
114+
public static LoggerConfiguration Configuration(
115+
this LoggerSettingsConfiguration settingConfiguration,
116+
IConfiguration configuration,
117+
out LoadedConfiguration loadedConfiguration,
118+
DependencyContext dependencyContext = null)
119+
=> Configuration(settingConfiguration, configuration, DefaultSectionName, out loadedConfiguration, dependencyContext);
120+
82121
/// <summary>
83122
/// Reads logger settings from the provided configuration section. Generally it is preferable to use the other
84123
/// extension method that takes the full configuration object.
@@ -123,14 +162,36 @@ public static LoggerConfiguration Configuration(
123162
IConfiguration configuration,
124163
string sectionName,
125164
ConfigurationAssemblySource configurationAssemblySource)
165+
=> Configuration(settingConfiguration, configuration, sectionName, configurationAssemblySource, out _);
166+
167+
/// <summary>
168+
/// Reads logger settings from the provided configuration object using the provided section name. Generally this
169+
/// is preferable over the other method that takes a configuration section. Only this version will populate
170+
/// IConfiguration parameters on target methods.
171+
/// </summary>
172+
/// <param name="settingConfiguration">Logger setting configuration.</param>
173+
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
174+
/// <param name="sectionName">A section name for section which contains a Serilog section.</param>
175+
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other types.</param>
176+
/// <param name="loadedConfiguration">Contains information about the loaded configuration upon return.</param>
177+
/// <returns>An object allowing configuration to continue.</returns>
178+
public static LoggerConfiguration Configuration(
179+
this LoggerSettingsConfiguration settingConfiguration,
180+
IConfiguration configuration,
181+
string sectionName,
182+
ConfigurationAssemblySource configurationAssemblySource,
183+
out LoadedConfiguration loadedConfiguration)
126184
{
127185
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
128186
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
129187
if (sectionName == null) throw new ArgumentNullException(nameof(sectionName));
130188

131189
var assemblyFinder = AssemblyFinder.ForSource(configurationAssemblySource);
132190

133-
return settingConfiguration.Settings(new ConfigurationReader(configuration.GetSection(sectionName), assemblyFinder, configuration));
191+
var configurationReader = new ConfigurationReader(configuration.GetSection(sectionName), assemblyFinder, configuration);
192+
var loggerConfiguration = settingConfiguration.Settings(configurationReader);
193+
loadedConfiguration = configurationReader.GetLoadedConfiguration();
194+
return loggerConfiguration;
134195
}
135196

136197
/// <summary>
@@ -183,12 +244,32 @@ public static LoggerConfiguration Configuration(
183244
IConfiguration configuration,
184245
string sectionName,
185246
params Assembly[] assemblies)
247+
=> Configuration(settingConfiguration, configuration, sectionName, out _, assemblies);
248+
249+
/// <summary>
250+
/// Reads logger settings from the provided configuration object using the provided section name.
251+
/// </summary>
252+
/// <param name="settingConfiguration">Logger setting configuration.</param>
253+
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
254+
/// <param name="sectionName">A section name for section which contains a Serilog section.</param>
255+
/// <param name="loadedConfiguration">Contains information about the loaded configuration upon return.</param>
256+
/// <param name="assemblies">A collection of assemblies that contains sinks and other types.</param>
257+
/// <returns>An object allowing configuration to continue.</returns>
258+
public static LoggerConfiguration Configuration(
259+
this LoggerSettingsConfiguration settingConfiguration,
260+
IConfiguration configuration,
261+
string sectionName,
262+
out LoadedConfiguration loadedConfiguration,
263+
params Assembly[] assemblies)
186264
{
187265
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
188266
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
189267
if (sectionName == null) throw new ArgumentNullException(nameof(sectionName));
190268

191-
return settingConfiguration.Settings(new ConfigurationReader(configuration.GetSection(sectionName), assemblies, new ResolutionContext(configuration)));
269+
var configurationReader = new ConfigurationReader(configuration.GetSection(sectionName), assemblies, new ResolutionContext(configuration));
270+
var loggerConfiguration = settingConfiguration.Settings(configurationReader);
271+
loadedConfiguration = configurationReader.GetLoadedConfiguration();
272+
return loggerConfiguration;
192273
}
193274

194275
/// <summary>

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public void Configure(LoggerConfiguration loggerConfiguration)
5858
ApplyAuditSinks(loggerConfiguration);
5959
}
6060

61+
public LoadedConfiguration GetLoadedConfiguration()
62+
{
63+
return new LoadedConfiguration(_resolutionContext.LogLevelSwitches);
64+
}
65+
6166
void ProcessFilterSwitchDeclarations()
6267
{
6368
var filterSwitchesDirective = _section.GetSection("FilterSwitches");
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Serilog.Core;
2+
3+
namespace Serilog.Settings.Configuration;
4+
5+
/// <summary>
6+
/// Contains information about the loaded configuration.
7+
/// </summary>
8+
public class LoadedConfiguration
9+
{
10+
readonly IDictionary<string,LoggingLevelSwitch> _logLevelSwitches;
11+
12+
internal LoadedConfiguration(IDictionary<string, LoggingLevelSwitch> logLevelSwitches)
13+
{
14+
_logLevelSwitches = logLevelSwitches;
15+
}
16+
17+
/// <summary>
18+
/// The log level switches that were loaded from the <c>LevelSwitches</c> section of the configuration.
19+
/// </summary>
20+
/// <remarks>The keys of the dictionary are the name of the switches without the <c>$</c> character.</remarks>
21+
public IReadOnlyDictionary<string, LoggingLevelSwitch> LogLevelSwitches => _logLevelSwitches.ToDictionary(e => e.Key.TrimStart('$'), e => e.Value);
22+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public ResolutionContext(IConfiguration appConfiguration = null)
2020
_appConfiguration = appConfiguration;
2121
}
2222

23+
public IDictionary<string, LoggingLevelSwitch> LogLevelSwitches => _declaredLevelSwitches;
24+
2325
/// <summary>
2426
/// Looks up a switch in the declared LoggingLevelSwitches
2527
/// </summary>

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

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.Extensions.Configuration;
1+
using Microsoft.Extensions.Configuration;
22
using Serilog.Core;
33
using Serilog.Events;
44
using Serilog.Settings.Configuration.Tests.Support;
@@ -12,22 +12,22 @@ public class ConfigurationSettingsTests
1212
{
1313
static LoggerConfiguration ConfigFromJson(string jsonString, string secondJsonSource = null)
1414
{
15-
return ConfigFromJson(jsonString, secondJsonSource, out _);
15+
return ConfigFromJson(jsonString, secondJsonSource, out _, out _);
1616
}
1717

18-
static LoggerConfiguration ConfigFromJson(string jsonString, out IConfiguration configuration)
18+
static LoggerConfiguration ConfigFromJson(string jsonString, out IConfiguration configuration, out LoadedConfiguration loadedConfiguration)
1919
{
20-
return ConfigFromJson(jsonString, null, out configuration);
20+
return ConfigFromJson(jsonString, null, out configuration, out loadedConfiguration);
2121
}
2222

23-
static LoggerConfiguration ConfigFromJson(string jsonString, string secondJsonSource, out IConfiguration configuration)
23+
static LoggerConfiguration ConfigFromJson(string jsonString, string secondJsonSource, out IConfiguration configuration, out LoadedConfiguration loadedConfiguration)
2424
{
2525
var builder = new ConfigurationBuilder().AddJsonString(jsonString);
2626
if (secondJsonSource != null)
2727
builder.AddJsonString(secondJsonSource);
2828
configuration = builder.Build();
2929
return new LoggerConfiguration()
30-
.ReadFrom.Configuration(configuration);
30+
.ReadFrom.Configuration(configuration, out loadedConfiguration);
3131
}
3232

3333
[Fact]
@@ -208,7 +208,7 @@ public void TestMinimumLevelOverrides()
208208

209209
LogEvent evt = null;
210210

211-
var log = ConfigFromJson(json)
211+
var log = ConfigFromJson(json, out _, out _)
212212
.WriteTo.Sink(new DelegatingSink(e => evt = e))
213213
.CreateLogger();
214214

@@ -384,10 +384,12 @@ public void LoggingLevelSwitchIsConfigured(string switchName)
384384
}}";
385385
LogEvent evt = null;
386386

387-
var log = ConfigFromJson(json)
387+
var log = ConfigFromJson(json, out _, out var loadedConfiguration)
388388
.WriteTo.Sink(new DelegatingSink(e => evt = e))
389389
.CreateLogger();
390390

391+
Assert.Contains("switch1", loadedConfiguration.LogLevelSwitches);
392+
Assert.Equal(LogEventLevel.Warning, loadedConfiguration.LogLevelSwitches["switch1"].MinimumLevel);
391393
log.Write(Some.DebugEvent());
392394
Assert.True(evt is null, "LoggingLevelSwitch initial level was Warning. It should not log Debug messages");
393395
log.Write(Some.InformationEvent());
@@ -542,7 +544,7 @@ public void SinkWithIConfigurationArguments()
542544
}";
543545

544546
DummyConfigurationSink.Reset();
545-
var log = ConfigFromJson(json, out var expectedConfig)
547+
var log = ConfigFromJson(json, out var expectedConfig, out _)
546548
.CreateLogger();
547549

548550
log.Write(Some.InformationEvent());
@@ -566,7 +568,7 @@ public void SinkWithOptionalIConfigurationArguments()
566568
}";
567569

568570
DummyConfigurationSink.Reset();
569-
var log = ConfigFromJson(json, out var expectedConfig)
571+
var log = ConfigFromJson(json, out var expectedConfig, out _)
570572
.CreateLogger();
571573

572574
log.Write(Some.InformationEvent());

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ public void ShouldRespectDynamicLevelChanges()
4747
{
4848
using var logger = new LoggerConfiguration()
4949
.ReadFrom
50-
.Configuration(new ConfigurationBuilder().Add(_configSource).Build())
50+
.Configuration(new ConfigurationBuilder().Add(_configSource).Build(), out var loadedConfiguration)
5151
.CreateLogger();
5252

53+
Assert.Equal(LogEventLevel.Information, loadedConfiguration.LogLevelSwitches["mySwitch"].MinimumLevel);
54+
5355
DummyConsoleSink.Emitted.Clear();
5456
logger.Write(Some.DebugEvent());
5557
Assert.Empty(DummyConsoleSink.Emitted);
@@ -64,6 +66,7 @@ public void ShouldRespectDynamicLevelChanges()
6466
logger.Write(Some.DebugEvent());
6567
logger.ForContext(Constants.SourceContextPropertyName, "Root.Test").Write(Some.DebugEvent());
6668
Assert.Single(DummyConsoleSink.Emitted);
69+
Assert.Equal(LogEventLevel.Debug, loadedConfiguration.LogLevelSwitches["mySwitch"].MinimumLevel);
6770

6871
DummyConsoleSink.Emitted.Clear();
6972
UpdateConfig(overrideLevel: LogEventLevel.Debug);

0 commit comments

Comments
 (0)