From d410d53c7f6c527381e2e7cbe47fbcbfde4cfada Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Thu, 29 Jun 2023 13:28:19 +0300 Subject: [PATCH 1/5] Case-insensitive enum parsing for level overrides --- .../Settings/Configuration/ConfigurationReader.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs index 2a6c317..34b476a 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs @@ -164,7 +164,7 @@ void ApplyMinimumLevel(LoggerConfiguration loggerConfiguration) { var overridePrefix = overrideDirective.Key; var overridenLevelOrSwitch = overrideDirective.Value; - if (Enum.TryParse(overridenLevelOrSwitch, out LogEventLevel _)) + if (Enum.TryParse(overridenLevelOrSwitch, ignoreCase: true, out LogEventLevel _)) { ApplyMinimumLevelConfiguration(overrideDirective, (configuration, levelSwitch) => { @@ -591,9 +591,7 @@ internal static bool IsValidSwitchName(string input) } static LogEventLevel ParseLogEventLevel(string value) - { - if (!Enum.TryParse(value, ignoreCase: true, out LogEventLevel parsedLevel)) - throw new InvalidOperationException($"The value {value} is not a valid Serilog level."); - return parsedLevel; - } + => Enum.TryParse(value, ignoreCase: true, out LogEventLevel parsedLevel) + ? parsedLevel + : throw new InvalidOperationException($"The value {value} is not a valid Serilog level."); } From b66d9786fb00b18cc1d2b5c590ee8803a86680d0 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Wed, 5 Jul 2023 08:37:02 +0300 Subject: [PATCH 2/5] SubscribeToLoggingLevelChanges --- .../Settings/Configuration/ConfigurationReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs index 34b476a..f994e25 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs @@ -221,7 +221,7 @@ void SubscribeToLoggingLevelChanges(IConfigurationSection levelSection, LoggingL levelSection.GetReloadToken, () => { - if (Enum.TryParse(levelSection.Value, out LogEventLevel minimumLevel)) + if (Enum.TryParse(levelSection.Value, ignoreCase: true, out LogEventLevel minimumLevel)) levelSwitch.MinimumLevel = minimumLevel; else SelfLog.WriteLine($"The value {levelSection.Value} is not a valid Serilog level."); From ca957607742117769b2f2c236123c54cbcca3b06 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Wed, 5 Jul 2023 08:43:41 +0300 Subject: [PATCH 3/5] trigger ci --- .../Settings/Configuration/StringArgumentValue.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs index ebf3d2e..2ba8dcc 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs @@ -10,7 +10,7 @@ class StringArgumentValue : IConfigurationArgumentValue { readonly string _providedValue; - static readonly Regex StaticMemberAccessorRegex = new Regex("^(?[^:]+)::(?[A-Za-z][A-Za-z0-9]*)(?[^:]*)$"); + static readonly Regex StaticMemberAccessorRegex = new("^(?[^:]+)::(?[A-Za-z][A-Za-z0-9]*)(?[^:]*)$"); public StringArgumentValue(string providedValue) { From e4468ce9be9993b0aec7e33e68f668a96687cce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Tue, 1 Aug 2023 22:56:10 +0200 Subject: [PATCH 4/5] Throw for missing configured assemblies only when required Fixes #389 --- .../Configuration/ConfigurationReader.cs | 8 +++++- .../PublishSingleFileTests.cs | 9 +++++++ test/TestApp/Program.cs | 26 ++++++++++++++----- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs index 2a6c317..c318f62 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs @@ -17,6 +17,9 @@ class ConfigurationReader : IConfigurationReader { const string LevelSwitchNameRegex = @"^\${0,1}[A-Za-z]+[A-Za-z0-9]*$"; + // Section names that can be handled by Serilog itself (hence builtin) without requiring any additional assemblies. + static readonly string[] BuiltinSectionNames = { "LevelSwitches", "MinimumLevel", "Properties" }; + readonly IConfiguration _section; readonly IReadOnlyCollection _configurationAssemblies; readonly ResolutionContext _resolutionContext; @@ -383,7 +386,10 @@ static IReadOnlyCollection LoadConfigurationAssemblies(IConfiguration assemblies.Add(assumed); } - if (assemblies.Count == 1) + // We don't want to throw if the configuration contains only sections that can be handled by Serilog itself, without requiring any additional assembly. + // See https://github.com/serilog/serilog-settings-configuration/issues/389 + var requiresAdditionalAssemblies = section.GetChildren().Select(e => e.Key).Except(BuiltinSectionNames).Any(); + if (assemblies.Count == 1 && requiresAdditionalAssemblies) { var message = $""" No {usingSection.Path} configuration section is defined and no Serilog assemblies were found. diff --git a/test/Serilog.Settings.Configuration.Tests/PublishSingleFileTests.cs b/test/Serilog.Settings.Configuration.Tests/PublishSingleFileTests.cs index 2197e78..c2f5d33 100644 --- a/test/Serilog.Settings.Configuration.Tests/PublishSingleFileTests.cs +++ b/test/Serilog.Settings.Configuration.Tests/PublishSingleFileTests.cs @@ -88,6 +88,15 @@ public async Task RunTestApp_ConsoleAndThread(PublishMode publishMode, string st stdErr.Should().BeEmpty(); } + [Theory] + [ClassData(typeof(PublishModeTheoryData))] + public async Task RunTestApp_ConfigureMinimumLevelOnly(PublishMode publishMode) + { + var (_, stdOut, stdErr) = await RunTestAppAsync(publishMode, "--minimum-level-only"); + stdOut.Should().Be("(Main thread) [Information] Expected success"); + stdErr.Should().BeEmpty(); + } + async Task<(bool IsSingleFile, string StdOut, string StdErr)> RunTestAppAsync(PublishMode publishMode, params string[] args) { // Determine whether the app is a _true_ single file, i.e. not a .NET Core 3.x version which diff --git a/test/TestApp/Program.cs b/test/TestApp/Program.cs index b376df4..033b43d 100644 --- a/test/TestApp/Program.cs +++ b/test/TestApp/Program.cs @@ -21,13 +21,20 @@ SelfLog.Enable(Console.Error); Thread.CurrentThread.Name = "Main thread"; +const string outputTemplate = "({ThreadName}) [{Level}] {Message}{NewLine}"; -var configurationValues = new Dictionary +var configurationValues = new Dictionary(); +var minimumLevelOnly = args.Contains("--minimum-level-only"); +if (minimumLevelOnly) { - ["Serilog:Enrich:0"] = "WithThreadName", - ["Serilog:WriteTo:0:Name"] = "Console", - ["Serilog:WriteTo:0:Args:outputTemplate"] = "({ThreadName}) [{Level}] {Message}{NewLine}", -}; + configurationValues["Serilog:MinimumLevel"] = "Verbose"; +} +else +{ + configurationValues["Serilog:Enrich:0"] = "WithThreadName"; + configurationValues["Serilog:WriteTo:0:Name"] = "Console"; + configurationValues["Serilog:WriteTo:0:Args:outputTemplate"] = outputTemplate; +} if (args.Contains("--using-thread")) configurationValues["Serilog:Using:Thread"] = "Serilog.Enrichers.Thread"; if (args.Contains("--using-console")) configurationValues["Serilog:Using:Console"] = "Serilog.Sinks.Console"; @@ -40,7 +47,14 @@ { var configuration = new ConfigurationBuilder().AddInMemoryCollection(configurationValues).Build(); var options = assemblies.Count > 0 ? new ConfigurationReaderOptions(assemblies.ToArray()) : null; - var logger = new LoggerConfiguration().ReadFrom.Configuration(configuration, options).CreateLogger(); + var loggerConfiguration = new LoggerConfiguration().ReadFrom.Configuration(configuration, options); + if (minimumLevelOnly) + { + loggerConfiguration + .Enrich.WithThreadName() + .WriteTo.Console(outputTemplate: outputTemplate); + } + var logger = loggerConfiguration.CreateLogger(); logger.Information("Expected success"); return 0; } From e92f2014bd7e66c243db2a76db8b8983e71aab28 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 22 Aug 2023 09:33:34 +1000 Subject: [PATCH 5/5] Dev version bump --- .../Serilog.Settings.Configuration.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj b/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj index ed87018..60b1c67 100644 --- a/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj +++ b/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj @@ -3,7 +3,7 @@ Microsoft.Extensions.Configuration (appsettings.json) support for Serilog. - 7.0.0 + 7.0.1 Serilog Contributors