diff --git a/src/Microsoft.Extensions.Logging.Filter/ConfigurationFilterLoggerSettings.cs b/src/Microsoft.Extensions.Logging.Filter/ConfigurationFilterLoggerSettings.cs new file mode 100644 index 00000000..f952213a --- /dev/null +++ b/src/Microsoft.Extensions.Logging.Filter/ConfigurationFilterLoggerSettings.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Filter +{ + /// + /// Filter settings for messages logged by an . + /// + public class ConfigurationFilterLoggerSettings : IFilterLoggerSettings + { + private readonly IConfiguration _configuration; + + public ConfigurationFilterLoggerSettings(IConfiguration configuration) + { + _configuration = configuration; + ChangeToken = configuration.GetReloadToken(); + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + var switches = _configuration.GetSection("LogLevel"); + if (switches == null) + { + level = LogLevel.None; + return false; + } + + var value = switches[name]; + if (string.IsNullOrEmpty(value)) + { + level = LogLevel.None; + return false; + } + else if (Enum.TryParse(value, out level)) + { + return true; + } + else + { + var message = $"Configuration value '{value}' for category '{name}' is not supported."; + throw new InvalidOperationException(message); + } + } + + public IFilterLoggerSettings Reload() + { + ChangeToken = null; + return new ConfigurationFilterLoggerSettings(_configuration); + } + + public IChangeToken ChangeToken { get; private set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Logging.Filter/FilterLoggerFactoryExtensions.cs b/src/Microsoft.Extensions.Logging.Filter/FilterLoggerFactoryExtensions.cs index 9dd56044..834a04d8 100644 --- a/src/Microsoft.Extensions.Logging.Filter/FilterLoggerFactoryExtensions.cs +++ b/src/Microsoft.Extensions.Logging.Filter/FilterLoggerFactoryExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Filter; using Microsoft.Extensions.Logging.Filter.Internal; namespace Microsoft.Extensions.Logging @@ -25,5 +27,21 @@ public static ILoggerFactory WithFilter(this ILoggerFactory loggerFactory, IFilt { return new FilterLoggerFactory(loggerFactory, settings); } + + /// + /// Registers a wrapper logger which provides a common way to filter log messages across all registered + /// s. + /// + /// The logger factory. + /// The configuration to use when creating an . + /// + /// A wrapped which provides common filtering across all registered + /// logger providers. + /// + public static ILoggerFactory WithFilter(this ILoggerFactory loggerFactory, IConfiguration configuration) + { + var settings = new ConfigurationFilterLoggerSettings(configuration); + return loggerFactory.WithFilter(settings); + } } } diff --git a/test/Microsoft.Extensions.Logging.Test/ConfigurationFilterLoggerSettingsTest.cs b/test/Microsoft.Extensions.Logging.Test/ConfigurationFilterLoggerSettingsTest.cs new file mode 100644 index 00000000..0f164a62 --- /dev/null +++ b/test/Microsoft.Extensions.Logging.Test/ConfigurationFilterLoggerSettingsTest.cs @@ -0,0 +1,142 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Filter; +using Xunit; + +namespace Microsoft.Extensions.Logging.Test +{ + public class ConfigurationFilterLoggerSettingsTest + { + [Fact] + public void TryGetSwitch_OnValidConfiguration_LoadsValueFromConfiguration() + { + // Arrange + var dict = new Dictionary + { + ["Logging:LogLevel:System"] = "Information" + }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dict) + .Build(); + var settings = new ConfigurationFilterLoggerSettings(config.GetSection("Logging")); + + // Act + LogLevel level; + var success = settings.TryGetSwitch("System", out level); + + // Assert + Assert.True(success); + Assert.Equal(LogLevel.Information, level); + } + + [Fact] + public void TryGetSwitch_OnMissingLogLevelSection_ReturnsLogLevelNone() + { + // Arrange + var dict = new Dictionary + { + ["Logging:"] = "" + }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dict) + .Build(); + var settings = new ConfigurationFilterLoggerSettings(config.GetSection("Logging")); + + // Act + LogLevel level; + var success = settings.TryGetSwitch("System", out level); + + // Assert + Assert.False(success); + Assert.Equal(LogLevel.None, level); + } + + [Fact] + public void TryGetSwitch_OnMissingSwitch_ReturnsLogLevelNone() + { + // Arrange + var dict = new Dictionary + { + ["Logging:LogLevel:System"] = "Information" + }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dict) + .Build(); + var settings = new ConfigurationFilterLoggerSettings(config.GetSection("Logging")); + + // Act + LogLevel level; + var success = settings.TryGetSwitch("Microsoft", out level); + + // Assert + Assert.False(success); + Assert.Equal(LogLevel.None, level); + } + + [Fact] + public void TryGetSwitch_IfLevelNullOrEmpty_ReturnsLogLevelNone() + { + // Arrange + var dict = new Dictionary + { + ["Logging:LogLevel:System"] = "" + }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dict) + .Build(); + var settings = new ConfigurationFilterLoggerSettings(config.GetSection("Logging")); + + // Act + LogLevel level; + var success = settings.TryGetSwitch("System", out level); + + // Assert + Assert.False(success); + Assert.Equal(LogLevel.None, level); + } + + [Fact] + public void TryGetSwitch_IfInvalidEnumValue_ThrowsException() + { + // Arrange + var dict = new Dictionary + { + ["Logging:LogLevel:System"] = "SomethingStrange" + }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dict) + .Build(); + var settings = new ConfigurationFilterLoggerSettings(config.GetSection("Logging")); + + // Act Assert + LogLevel level; + Assert.Throws(() => settings.TryGetSwitch("System", out level)); + } + + [Fact] + public void Reload_ReturnsNewObject() + { + // Arrange + var dict = new Dictionary + { + ["Logging:LogLevel:System"] = "SomethingStrange" + }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dict) + .Build(); + var settings = new ConfigurationFilterLoggerSettings(config.GetSection("Logging")); + + // Act Assert + var newSettings = settings.Reload(); + + Assert.NotNull(newSettings); + Assert.NotSame(settings, newSettings); + Assert.IsType(newSettings); + + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.Logging.Test/project.json b/test/Microsoft.Extensions.Logging.Test/project.json index 7c4924e3..a0f9ab52 100644 --- a/test/Microsoft.Extensions.Logging.Test/project.json +++ b/test/Microsoft.Extensions.Logging.Test/project.json @@ -4,6 +4,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", + "Microsoft.Extensions.Configuration": "1.1.0-*", "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.Extensions.Logging.Console": "1.1.0-*",