From 9f38745066b4eedf3a6bb97b0d6f9ee79ab1acde Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Fri, 16 Oct 2015 13:27:28 -0700 Subject: [PATCH] Add more configuration options for logging, add reload --- samples/SampleApp/Program.cs | 84 +++++++++++++++-- samples/SampleApp/logging.json | 8 ++ samples/SampleApp/project.json | 40 ++++---- .../LogLevel.cs | 5 + .../ConfigurationConsoleLoggerSettings.cs | 76 +++++++++++++++ .../ConsoleLogger.cs | 57 ++++++++--- .../ConsoleLoggerFactoryExtensions.cs | 17 +++- .../ConsoleLoggerProvider.cs | 94 ++++++++++++++++++- .../ConsoleLoggerSettings.cs | 28 ++++++ .../IConsoleLoggerSettings.cs | 16 ++++ .../project.json | 63 +++++++------ .../ConsoleLoggerTest.cs | 87 +++++++++++++++++ .../LogLevelEnumTest.cs | 2 +- 13 files changed, 505 insertions(+), 72 deletions(-) create mode 100644 samples/SampleApp/logging.json create mode 100644 src/Microsoft.Extensions.Logging.Console/ConfigurationConsoleLoggerSettings.cs create mode 100644 src/Microsoft.Extensions.Logging.Console/ConsoleLoggerSettings.cs create mode 100644 src/Microsoft.Extensions.Logging.Console/IConsoleLoggerSettings.cs diff --git a/samples/SampleApp/Program.cs b/samples/SampleApp/Program.cs index 39fce3fd..e029d9d5 100644 --- a/samples/SampleApp/Program.cs +++ b/samples/SampleApp/Program.cs @@ -1,5 +1,11 @@ using System; +using System.Collections.Generic; +using Microsoft.AspNet.FileProviders; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; +using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.Extensions.Primitives; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SampleApp @@ -21,14 +27,72 @@ public Program() factory.AddNLog(new global::NLog.LogFactory()); factory.AddEventLog(); #endif - factory.AddConsole(includeScopes: true); + + // How to configure the console logger to reload based on a configuration file. + // + // + var loggingConfiguration = new ConfigurationBuilder().AddJsonFile("logging.json").Build(); + factory.AddConsole(loggingConfiguration); + loggingConfiguration.ReloadOnChanged("logging.json"); + + // How to configure the console logger to use settings provided in code. + // + // + //var settings = new ConsoleLoggerSettings() + //{ + // IncludeScopes = true, + // Switches = + // { + // ["Default"] = LogLevel.Verbose, + // ["Microsoft"] = LogLevel.Information, + // } + //}; + //factory.AddConsole(settings); + + // How to manually wire up file-watching without a configuration file + // + // + //factory.AddConsole(new RandomReloadingConsoleSettings()); + } + + private class RandomReloadingConsoleSettings : IConsoleLoggerSettings + { + private PhysicalFileProvider _files = new PhysicalFileProvider(PlatformServices.Default.Application.ApplicationBasePath); + + public RandomReloadingConsoleSettings() + { + Reload(); + } + + public IChangeToken ChangeToken { get; private set; } + + public bool IncludeScopes { get; } + + private Dictionary Switches { get; set; } + + public IConsoleLoggerSettings Reload() + { + ChangeToken = _files.Watch("logging.json"); + Switches = new Dictionary() + { + ["Default"] = (LogLevel)(DateTimeOffset.Now.Second % 5 + 1), + ["Microsoft"] = (LogLevel)(DateTimeOffset.Now.Second % 5 + 1), + }; + + return this; + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + return Switches.TryGetValue(name, out level); + } } public void Main(string[] args) { _logger.LogInformation("Starting"); - var startTime = DateTimeOffset.UtcNow; + var startTime = DateTimeOffset.Now; _logger.LogInformation(1, "Started at '{StartTime}' and 0x{Hello:X} is hex of 42", startTime, 42); // or _logger.ProgramStarting(startTime, 42); @@ -48,15 +112,23 @@ public void Main(string[] args) using (_logger.BeginScopeImpl("Main")) { - Console.WriteLine("Hello World"); _logger.LogInformation("Waiting for user input"); - var input = Console.ReadLine(); - _logger.LogInformation("User typed '{input}' on the command line", input); + + string input; + do + { + Console.WriteLine("Enter some test to log more, or 'quit' to exit."); + input = Console.ReadLine(); + + _logger.LogInformation("User typed '{input}' on the command line", input); + _logger.LogWarning("The time is now {Time}, it's getting late!", DateTimeOffset.Now); + } + while (input != "quit"); } } - var endTime = DateTimeOffset.UtcNow; + var endTime = DateTimeOffset.Now; _logger.LogInformation(2, "Stopping at '{StopTime}'", endTime); // or _logger.ProgramStopping(endTime); diff --git a/samples/SampleApp/logging.json b/samples/SampleApp/logging.json new file mode 100644 index 00000000..3f2f4b73 --- /dev/null +++ b/samples/SampleApp/logging.json @@ -0,0 +1,8 @@ +{ + "includeScopes" : "false", + "switches": { + "Default": "Verbose", + "System": "Information", + "Microsoft": "Information" + } +} \ No newline at end of file diff --git a/samples/SampleApp/project.json b/samples/SampleApp/project.json index 67bc2056..7f51b892 100644 --- a/samples/SampleApp/project.json +++ b/samples/SampleApp/project.json @@ -1,22 +1,26 @@ { - "commands": { - "SampleApp": "SampleApp" + "commands": { + "SampleApp": "SampleApp" + }, + "dependencies": { + "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", + "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-*", + "Microsoft.Extensions.Configuration.Json": "1.0.0-*", + "Microsoft.Extensions.Logging": "1.0.0-*", + "Microsoft.Extensions.Logging.Console": "1.0.0-*", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*" + }, + "frameworks": { + "dnx451": { + "dependencies": { + "Microsoft.Extensions.Logging.EventLog": "1.0.0-*", + "Microsoft.Extensions.Logging.NLog": "1.0.0-*" + } }, - "dependencies": { - "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*" - }, - "frameworks": { - "dnx451": { - "dependencies": { - "Microsoft.Extensions.Logging.EventLog": "1.0.0-*", - "Microsoft.Extensions.Logging.NLog": "1.0.0-*" - } - }, - "dnxcore50": { - "dependencies": { - "System.Console": "4.0.0-beta-*" - } - } + "dnxcore50": { + "dependencies": { + "System.Console": "4.0.0-beta-*" + } } + } } diff --git a/src/Microsoft.Extensions.Logging.Abstractions/LogLevel.cs b/src/Microsoft.Extensions.Logging.Abstractions/LogLevel.cs index b57c0805..791de650 100644 --- a/src/Microsoft.Extensions.Logging.Abstractions/LogLevel.cs +++ b/src/Microsoft.Extensions.Logging.Abstractions/LogLevel.cs @@ -42,5 +42,10 @@ public enum LogLevel /// immediate attention. /// Critical = 6, + + /// + /// Not used for writing log messages. Specifies that a logging category should not write any messages. + /// + None = int.MaxValue, } } diff --git a/src/Microsoft.Extensions.Logging.Console/ConfigurationConsoleLoggerSettings.cs b/src/Microsoft.Extensions.Logging.Console/ConfigurationConsoleLoggerSettings.cs new file mode 100644 index 00000000..b611b582 --- /dev/null +++ b/src/Microsoft.Extensions.Logging.Console/ConfigurationConsoleLoggerSettings.cs @@ -0,0 +1,76 @@ +// 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.Console +{ + public class ConfigurationConsoleLoggerSettings : IConsoleLoggerSettings + { + private readonly IConfiguration _configuration; + + public ConfigurationConsoleLoggerSettings(IConfiguration configuration) + { + _configuration = configuration; + ChangeToken = configuration.GetReloadToken(); + } + + public IChangeToken ChangeToken { get; private set; } + + public bool IncludeScopes + { + get + { + bool includeScopes; + var value = _configuration["includeScopes"]; + if (string.IsNullOrEmpty(value)) + { + return false; + } + else if (bool.TryParse(value, out includeScopes)) + { + return includeScopes; + } + else + { + var message = $"Configuration value '{value}' for setting '{nameof(IncludeScopes)}' is not supported."; + throw new InvalidOperationException(message); + } + } + } + + public IConsoleLoggerSettings Reload() + { + ChangeToken = null; + return new ConfigurationConsoleLoggerSettings(_configuration); + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + var switches = _configuration.GetSection("switches"); + 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); + } + } + } +} diff --git a/src/Microsoft.Extensions.Logging.Console/ConsoleLogger.cs b/src/Microsoft.Extensions.Logging.Console/ConsoleLogger.cs index b699538b..073a02b9 100644 --- a/src/Microsoft.Extensions.Logging.Console/ConsoleLogger.cs +++ b/src/Microsoft.Extensions.Logging.Console/ConsoleLogger.cs @@ -21,9 +21,9 @@ public class ConsoleLogger : ILogger private readonly ConsoleColor? DefaultConsoleColor = null; private const int _indentation = 2; - private readonly string _name; - private readonly Func _filter; - private readonly bool _includeScopes; + + private IConsole _console; + private Func _filter; static ConsoleLogger() { @@ -33,9 +33,14 @@ static ConsoleLogger() public ConsoleLogger(string name, Func filter, bool includeScopes) { - _name = name; - _filter = filter ?? ((category, logLevel) => true); - _includeScopes = includeScopes; + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + Filter = filter ?? ((category, logLevel) => true); + IncludeScopes = includeScopes; if (RuntimeEnvironmentHelper.IsWindows) { @@ -47,9 +52,37 @@ public ConsoleLogger(string name, Func filter, bool incl } } - public IConsole Console { get; set; } + public IConsole Console + { + get { return _console; } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _console = value; + } + } + + public Func Filter + { + get { return _filter; } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _filter = value; + } + } + + public bool IncludeScopes { get; set; } - protected string Name { get { return _name; } } + public string Name { get; } public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) { @@ -86,7 +119,7 @@ public void Log(LogLevel logLevel, int eventId, object state, Exception exceptio return; } - WriteMessage(logLevel, _name, eventId, message); + WriteMessage(logLevel, Name, eventId, message); } public virtual void WriteMessage(LogLevel logLevel, string logName, int eventId, string message) @@ -118,7 +151,7 @@ public virtual void WriteMessage(LogLevel logLevel, string logName, int eventId, newLine: true); // scope information - if (_includeScopes) + if (IncludeScopes) { var scopeInformation = GetScopeInformation(); if (!string.IsNullOrEmpty(scopeInformation)) @@ -146,7 +179,7 @@ public virtual void WriteMessage(LogLevel logLevel, string logName, int eventId, public bool IsEnabled(LogLevel logLevel) { - return _filter(_name, logLevel); + return Filter(Name, logLevel); } public IDisposable BeginScopeImpl(object state) @@ -156,7 +189,7 @@ public IDisposable BeginScopeImpl(object state) throw new ArgumentNullException(nameof(state)); } - return ConsoleLogScope.Push(_name, state); + return ConsoleLogScope.Push(Name, state); } private void FormatLogValues(StringBuilder builder, ILogValues logValues, int level, bool bullet) diff --git a/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerFactoryExtensions.cs b/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerFactoryExtensions.cs index 335ca5cd..51d6961b 100644 --- a/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerFactoryExtensions.cs +++ b/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerFactoryExtensions.cs @@ -2,6 +2,7 @@ // 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.Logging.Console; namespace Microsoft.Extensions.Logging @@ -24,7 +25,7 @@ public static ILoggerFactory AddConsole(this ILoggerFactory factory) /// in the output. public static ILoggerFactory AddConsole(this ILoggerFactory factory, bool includeScopes) { - factory.AddConsole(LogLevel.Information, includeScopes); + factory.AddConsole((n, l) => l >= LogLevel.Information, includeScopes); return factory; } @@ -82,5 +83,19 @@ public static ILoggerFactory AddConsole( factory.AddProvider(new ConsoleLoggerProvider(filter, includeScopes)); return factory; } + + public static ILoggerFactory AddConsole( + this ILoggerFactory factory, + IConsoleLoggerSettings settings) + { + factory.AddProvider(new ConsoleLoggerProvider(settings)); + return factory; + } + + public static ILoggerFactory AddConsole(this ILoggerFactory factory, IConfiguration configuration) + { + var settings = new ConfigurationConsoleLoggerSettings(configuration); + return factory.AddConsole(settings); + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerProvider.cs b/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerProvider.cs index 96efe98a..ab60ec5a 100644 --- a/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerProvider.cs +++ b/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerProvider.cs @@ -2,23 +2,111 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Concurrent; +using System.Collections.Generic; namespace Microsoft.Extensions.Logging.Console { public class ConsoleLoggerProvider : ILoggerProvider { + private readonly ConcurrentDictionary _loggers = new ConcurrentDictionary(); + private readonly Func _filter; - private readonly bool _includeScopes; + private IConsoleLoggerSettings _settings; public ConsoleLoggerProvider(Func filter, bool includeScopes) { + if (filter == null) + { + throw new ArgumentNullException(nameof(filter)); + } + _filter = filter; - _includeScopes = includeScopes; + _settings = new ConsoleLoggerSettings() + { + IncludeScopes = includeScopes, + }; + } + + public ConsoleLoggerProvider(IConsoleLoggerSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + _settings = settings; + + if (_settings.ChangeToken != null) + { + _settings.ChangeToken.RegisterChangeCallback(OnConfigurationReload, null); + } + } + + private void OnConfigurationReload(object state) + { + // The settings object needs to change here, because the old one is probably holding on + // to an old change token. + _settings = _settings.Reload(); + + foreach (var logger in _loggers.Values) + { + logger.Filter = GetFilter(logger.Name, _settings); + logger.IncludeScopes = _settings.IncludeScopes; + } + + // The token will change each time it reloads, so we need to register again. + if (_settings?.ChangeToken != null) + { + _settings.ChangeToken.RegisterChangeCallback(OnConfigurationReload, null); + } } public ILogger CreateLogger(string name) { - return new ConsoleLogger(name, _filter, _includeScopes); + return _loggers.GetOrAdd(name, CreateLoggerImplementation); + } + + private ConsoleLogger CreateLoggerImplementation(string name) + { + return new ConsoleLogger(name, GetFilter(name, _settings), _settings.IncludeScopes); + } + + private Func GetFilter(string name, IConsoleLoggerSettings settings) + { + if (_filter != null) + { + return _filter; + } + + if (settings != null) + { + foreach (var prefix in GetKeyPrefixes(name)) + { + LogLevel level; + if (settings.TryGetSwitch(prefix, out level)) + { + return (n, l) => l >= level; + } + } + } + + return (n, l) => false; + } + + private IEnumerable GetKeyPrefixes(string name) + { + while (!string.IsNullOrEmpty(name)) + { + yield return name; + var lastIndexOfDot = name.LastIndexOf('.'); + if (lastIndexOfDot == -1) + { + yield return "Default"; + break; + } + name = name.Substring(0, lastIndexOfDot); + } } public void Dispose() diff --git a/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerSettings.cs b/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerSettings.cs new file mode 100644 index 00000000..8a0dfd11 --- /dev/null +++ b/src/Microsoft.Extensions.Logging.Console/ConsoleLoggerSettings.cs @@ -0,0 +1,28 @@ +// 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.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + public class ConsoleLoggerSettings : IConsoleLoggerSettings + { + public IChangeToken ChangeToken { get; set; } + + public bool IncludeScopes { get; set; } + + public IDictionary Switches { get; set; } = new Dictionary(); + + public IConsoleLoggerSettings Reload() + { + return this; + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + return Switches.TryGetValue(name, out level); + } + } +} diff --git a/src/Microsoft.Extensions.Logging.Console/IConsoleLoggerSettings.cs b/src/Microsoft.Extensions.Logging.Console/IConsoleLoggerSettings.cs new file mode 100644 index 00000000..fe44a5f9 --- /dev/null +++ b/src/Microsoft.Extensions.Logging.Console/IConsoleLoggerSettings.cs @@ -0,0 +1,16 @@ +using System; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + public interface IConsoleLoggerSettings + { + bool IncludeScopes { get; } + + IChangeToken ChangeToken { get; } + + bool TryGetSwitch(string name, out LogLevel level); + + IConsoleLoggerSettings Reload(); + } +} diff --git a/src/Microsoft.Extensions.Logging.Console/project.json b/src/Microsoft.Extensions.Logging.Console/project.json index a7355ff1..07bebfcd 100644 --- a/src/Microsoft.Extensions.Logging.Console/project.json +++ b/src/Microsoft.Extensions.Logging.Console/project.json @@ -1,36 +1,37 @@ { - "version": "1.0.0-*", - "repository": { - "type": "git", - "url": "git://github.com/aspnet/logging" + "version": "1.0.0-*", + "repository": { + "type": "git", + "url": "git://github.com/aspnet/logging" + }, + "description": "Console logger implementation.", + "compilationOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "Microsoft.Dnx.Runtime.Sources": { + "version": "1.0.0-*", + "type": "build" }, - "description": "Console logger implementation.", - "compilationOptions": { - "warningsAsErrors": true + "Microsoft.Extensions.Configuration.Abstractions": "1.0.0-*", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*" + }, + "frameworks": { + "net451": { }, + "dotnet5.4": { + "dependencies": { + "System.Console": "4.0.0-beta-*", + "System.IO": "4.0.11-beta-*", + "System.Reflection.Extensions": "4.0.1-beta-*", + "System.Runtime": "4.0.21-beta-*", + "System.Threading": "4.0.11-beta-*" + } }, - "dependencies": { - "Microsoft.Dnx.Runtime.Sources": { - "version": "1.0.0-*", - "type": "build" - }, - "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*" - }, - "frameworks": { - "net451": { }, - "dotnet5.4": { - "dependencies": { - "System.Console": "4.0.0-beta-*", - "System.IO": "4.0.11-beta-*", - "System.Reflection.Extensions": "4.0.1-beta-*", - "System.Runtime": "4.0.21-beta-*", - "System.Threading": "4.0.11-beta-*" - } - }, - "netcore50": { - "dependencies": { - "System.Console": "4.0.0-*" - } - } + "netcore50": { + "dependencies": { + "System.Console": "4.0.0-*" + } } + } } \ No newline at end of file diff --git a/test/Microsoft.Extensions.Logging.Test/ConsoleLoggerTest.cs b/test/Microsoft.Extensions.Logging.Test/ConsoleLoggerTest.cs index 2869af69..bb900a68 100644 --- a/test/Microsoft.Extensions.Logging.Test/ConsoleLoggerTest.cs +++ b/test/Microsoft.Extensions.Logging.Test/ConsoleLoggerTest.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Logging.Test.Console; +using Microsoft.Extensions.Primitives; +using System.Threading; #if MOCK_SUPPORT using Moq; #endif @@ -652,6 +654,70 @@ public void CallingBeginScopeOnLogger_ReturnsNonNullableInstance() Assert.NotNull(disposable); } + [Fact] + public void ConsoleLogger_ReloadSettings_CanChangeLogLevel() + { + // Arrange + var settings = new MockConsoleLoggerSettings() + { + Cancel = new CancellationTokenSource(), + Switches = + { + ["Test"] = LogLevel.Information, + } + }; + + var loggerFactory = new LoggerFactory(); + loggerFactory.AddConsole(settings); + + var logger = loggerFactory.CreateLogger("Test"); + Assert.False(logger.IsEnabled(LogLevel.Verbose)); + + settings.Switches["Test"] = LogLevel.Verbose; + + var cancellationTokenSource = settings.Cancel; + settings.Cancel = new CancellationTokenSource(); + + // Act + cancellationTokenSource.Cancel(); + + // Assert + Assert.True(logger.IsEnabled(LogLevel.Verbose)); + } + + [Fact] + public void ConsoleLogger_ReloadSettings_CanReloadMultipleTimes() + { + // Arrange + var settings = new MockConsoleLoggerSettings() + { + Cancel = new CancellationTokenSource(), + Switches = + { + ["Test"] = LogLevel.Information, + } + }; + + var loggerFactory = new LoggerFactory(); + loggerFactory.AddConsole(settings); + + var logger = loggerFactory.CreateLogger("Test"); + Assert.False(logger.IsEnabled(LogLevel.Verbose)); + + // Act & Assert + for (var i = 0; i < 10; i++) + { + settings.Switches["Test"] = i % 2 == 0 ? LogLevel.Information : LogLevel.Verbose; + + var cancellationTokenSource = settings.Cancel; + settings.Cancel = new CancellationTokenSource(); + + cancellationTokenSource.Cancel(); + + Assert.Equal(i % 2 == 1, logger.IsEnabled(LogLevel.Verbose)); + } + } + private string GetMessage(string logLevelString, int eventId, Exception exception) { var loglevelStringWithPadding = $"{logLevelString}: "; @@ -670,5 +736,26 @@ private string GetMessage(List contexts) { return string.Join("", contexts.Select(c => c.Message)); } + + private class MockConsoleLoggerSettings : IConsoleLoggerSettings + { + public CancellationTokenSource Cancel { get; set; } + + public IChangeToken ChangeToken => new CancellationChangeToken(Cancel.Token); + + public IDictionary Switches { get; } = new Dictionary(); + + public bool IncludeScopes { get; set; } + + public IConsoleLoggerSettings Reload() + { + return this; + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + return Switches.TryGetValue(name, out level); + } + } } } \ No newline at end of file diff --git a/test/Microsoft.Extensions.Logging.Test/LogLevelEnumTest.cs b/test/Microsoft.Extensions.Logging.Test/LogLevelEnumTest.cs index a7784aa0..2fa3de02 100644 --- a/test/Microsoft.Extensions.Logging.Test/LogLevelEnumTest.cs +++ b/test/Microsoft.Extensions.Logging.Test/LogLevelEnumTest.cs @@ -21,7 +21,7 @@ public static void EnumValuesAreUniqueAndConsecutive() { var values = GetEnumValues(); values.Sort(); - Assert.Equal(new[] { 1, 2, 3, 4, 5, 6 }, values); + Assert.Equal(new[] { 1, 2, 3, 4, 5, 6, int.MaxValue}, values); } private static List GetEnumValues()