diff --git a/src/libraries/Common/src/Extensions/Logging/NullExternalScopeProvider.cs b/src/libraries/Common/src/Extensions/Logging/NullExternalScopeProvider.cs index 5c50de4dd6207..f7631ab6f1273 100644 --- a/src/libraries/Common/src/Extensions/Logging/NullExternalScopeProvider.cs +++ b/src/libraries/Common/src/Extensions/Logging/NullExternalScopeProvider.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable - using System; namespace Microsoft.Extensions.Logging diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs index ee48f8f22bb39..72e6ae6afce77 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs @@ -160,7 +160,7 @@ namespace Microsoft.Extensions.Logging.Abstractions public string Category { get { throw null; } } public Microsoft.Extensions.Logging.EventId EventId { get { throw null; } } public System.Exception? Exception { get { throw null; } } - public System.Func? Formatter { get { throw null; } } + public System.Func Formatter { get { throw null; } } public Microsoft.Extensions.Logging.LogLevel LogLevel { get { throw null; } } public TState State { get { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogEntry.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogEntry.cs index cebd054da91b7..17f070cf02391 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogEntry.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogEntry.cs @@ -57,6 +57,6 @@ public LogEntry(LogLevel logLevel, string category, EventId eventId, TState stat /// /// Gets the formatter /// - public Func? Formatter { get; } + public Func Formatter { get; } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs index 1d7693afc2eb4..aa9077333e6c5 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs @@ -29,7 +29,7 @@ public abstract partial class ConsoleFormatter { protected ConsoleFormatter(string name) { } public string Name { get { throw null; } } - public abstract void Write(in Microsoft.Extensions.Logging.Abstractions.LogEntry logEntry, Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider, System.IO.TextWriter textWriter); + public abstract void Write(in Microsoft.Extensions.Logging.Abstractions.LogEntry logEntry, Microsoft.Extensions.Logging.IExternalScopeProvider? scopeProvider, System.IO.TextWriter textWriter); } public static partial class ConsoleFormatterNames { @@ -42,7 +42,7 @@ public partial class ConsoleFormatterOptions public ConsoleFormatterOptions() { } public bool IncludeScopes { get { throw null; } set { } } [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("DateTimeFormat")] - public string TimestampFormat { get { throw null; } set { } } + public string? TimestampFormat { get { throw null; } set { } } public bool UseUtcTimestamp { get { throw null; } set { } } } [System.ObsoleteAttribute("ConsoleLoggerFormat has been deprecated.")] @@ -58,12 +58,12 @@ public partial class ConsoleLoggerOptions public bool DisableColors { get { throw null; } set { } } [System.ObsoleteAttribute("ConsoleLoggerOptions.Format has been deprecated. Use ConsoleLoggerOptions.FormatterName instead.")] public Microsoft.Extensions.Logging.Console.ConsoleLoggerFormat Format { get { throw null; } set { } } - public string FormatterName { get { throw null; } set { } } + public string? FormatterName { get { throw null; } set { } } [System.ObsoleteAttribute("ConsoleLoggerOptions.IncludeScopes has been deprecated. Use ConsoleFormatterOptions.IncludeScopes instead.")] public bool IncludeScopes { get { throw null; } set { } } public Microsoft.Extensions.Logging.LogLevel LogToStandardErrorThreshold { get { throw null; } set { } } [System.ObsoleteAttribute("ConsoleLoggerOptions.TimestampFormat has been deprecated. Use ConsoleFormatterOptions.TimestampFormat instead.")] - public string TimestampFormat { get { throw null; } set { } } + public string? TimestampFormat { get { throw null; } set { } } [System.ObsoleteAttribute("ConsoleLoggerOptions.UseUtcTimestamp has been deprecated. Use ConsoleFormatterOptions.UseUtcTimestamp instead.")] public bool UseUtcTimestamp { get { throw null; } set { } } } @@ -72,7 +72,7 @@ public partial class ConsoleLoggerOptions public partial class ConsoleLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, Microsoft.Extensions.Logging.ISupportExternalScope, System.IDisposable { public ConsoleLoggerProvider(Microsoft.Extensions.Options.IOptionsMonitor options) { } - public ConsoleLoggerProvider(Microsoft.Extensions.Options.IOptionsMonitor options, System.Collections.Generic.IEnumerable formatters) { } + public ConsoleLoggerProvider(Microsoft.Extensions.Options.IOptionsMonitor options, System.Collections.Generic.IEnumerable? formatters) { } public Microsoft.Extensions.Logging.ILogger CreateLogger(string name) { throw null; } public void Dispose() { } public void SetScopeProvider(Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider) { } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj index 71aeb235fd3b0..199f8409eb161 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + enable true diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatter.cs index b4c20770f830c..0fbaaf80a8e1e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatter.cs @@ -32,6 +32,6 @@ protected ConsoleFormatter(string name!!) /// The provider of scope data. /// The string writer embedding ansi code for colors. /// The type of the object to be written. - public abstract void Write(in LogEntry logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter); + public abstract void Write(in LogEntry logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter); } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs index e4a9800ad6e3e..18978a2c40a61 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs @@ -23,7 +23,7 @@ public class ConsoleFormatterOptions /// Gets or sets format string used to format timestamp in logging messages. Defaults to null. /// [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] - public string TimestampFormat { get; set; } + public string? TimestampFormat { get; set; } /// /// Gets or sets indication whether or not UTC timezone should be used to format timestamps in logging messages. Defaults to false. diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLogger.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLogger.cs index 301ed0a9fbc5f..608e7bbcbfad0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLogger.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLogger.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Versioning; using Microsoft.Extensions.Logging.Abstractions; @@ -14,21 +15,28 @@ internal sealed class ConsoleLogger : ILogger private readonly string _name; private readonly ConsoleLoggerProcessor _queueProcessor; - internal ConsoleLogger(string name!!, ConsoleLoggerProcessor loggerProcessor) + internal ConsoleLogger( + string name!!, + ConsoleLoggerProcessor loggerProcessor, + ConsoleFormatter formatter, + IExternalScopeProvider? scopeProvider, + ConsoleLoggerOptions options) { _name = name; _queueProcessor = loggerProcessor; + Formatter = formatter; + ScopeProvider = scopeProvider; + Options = options; } internal ConsoleFormatter Formatter { get; set; } - internal IExternalScopeProvider ScopeProvider { get; set; } - + internal IExternalScopeProvider? ScopeProvider { get; set; } internal ConsoleLoggerOptions Options { get; set; } [ThreadStatic] - private static StringWriter t_stringWriter; + private static StringWriter? t_stringWriter; - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { if (!IsEnabled(logLevel)) { @@ -61,6 +69,6 @@ public bool IsEnabled(LogLevel logLevel) return logLevel != LogLevel.None; } - public IDisposable BeginScope(TState state) => ScopeProvider?.Push(state) ?? NullScope.Instance; + public IDisposable BeginScope(TState state) where TState : notnull => ScopeProvider?.Push(state) ?? NullScope.Instance; } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs index 694d0b6c2da3a..4036fc258add3 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs @@ -39,7 +39,7 @@ public ConsoleLoggerFormat Format /// /// Name of the log message formatter to use. Defaults to "simple" />. /// - public string FormatterName { get; set; } + public string? FormatterName { get; set; } /// /// Includes scopes when . @@ -56,7 +56,7 @@ public ConsoleLoggerFormat Format /// Gets or sets format string used to format timestamp in logging messages. Defaults to null. /// [System.ObsoleteAttribute("ConsoleLoggerOptions.TimestampFormat has been deprecated. Use ConsoleFormatterOptions.TimestampFormat instead.")] - public string TimestampFormat { get; set; } + public string? TimestampFormat { get; set; } /// /// Gets or sets indication whether or not UTC timezone should be used to format timestamps in logging messages. Defaults to false. diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProcessor.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProcessor.cs index c79ccac72f9fd..86864142d3ecb 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProcessor.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProcessor.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; using System.Threading; @@ -16,11 +17,13 @@ internal class ConsoleLoggerProcessor : IDisposable private readonly BlockingCollection _messageQueue = new BlockingCollection(_maxQueuedMessages); private readonly Thread _outputThread; - public IConsole Console; - public IConsole ErrorConsole; + public IConsole Console { get; } + public IConsole ErrorConsole { get; } - public ConsoleLoggerProcessor() + public ConsoleLoggerProcessor(IConsole console, IConsole errorConsole) { + Console = console; + ErrorConsole = errorConsole; // Start Console message queue processor _outputThread = new Thread(ProcessLogQueue) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs index 8c71e96e21f9d..d24a935e858c6 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Microsoft.Extensions.Options; @@ -22,7 +23,7 @@ public class ConsoleLoggerProvider : ILoggerProvider, ISupportExternalScope private ConcurrentDictionary _formatters; private readonly ConsoleLoggerProcessor _messageQueue; - private IDisposable _optionsReloadToken; + private IDisposable? _optionsReloadToken; private IExternalScopeProvider _scopeProvider = NullExternalScopeProvider.Instance; /// @@ -37,7 +38,7 @@ public ConsoleLoggerProvider(IOptionsMonitor options) /// /// The options to create instances with. /// Log formatters added for insteaces. - public ConsoleLoggerProvider(IOptionsMonitor options, IEnumerable formatters) + public ConsoleLoggerProvider(IOptionsMonitor options, IEnumerable? formatters) { _options = options; _loggers = new ConcurrentDictionary(); @@ -46,18 +47,19 @@ public ConsoleLoggerProvider(IOptionsMonitor options, IEnu ReloadLoggerOptions(options.CurrentValue); _optionsReloadToken = _options.OnChange(ReloadLoggerOptions); - _messageQueue = new ConsoleLoggerProcessor(); - + IConsole? console; + IConsole? errorConsole; if (DoesConsoleSupportAnsi()) { - _messageQueue.Console = new AnsiLogConsole(); - _messageQueue.ErrorConsole = new AnsiLogConsole(stdErr: true); + console = new AnsiLogConsole(); + errorConsole = new AnsiLogConsole(stdErr: true); } else { - _messageQueue.Console = new AnsiParsingLogConsole(); - _messageQueue.ErrorConsole = new AnsiParsingLogConsole(stdErr: true); + console = new AnsiParsingLogConsole(); + errorConsole = new AnsiParsingLogConsole(stdErr: true); } + _messageQueue = new ConsoleLoggerProcessor(console, errorConsole); } [UnsupportedOSPlatformGuard("windows")] @@ -78,7 +80,8 @@ private static bool DoesConsoleSupportAnsi() return (consoleMode & Interop.Kernel32.ENABLE_VIRTUAL_TERMINAL_PROCESSING) == Interop.Kernel32.ENABLE_VIRTUAL_TERMINAL_PROCESSING; } - private void SetFormatters(IEnumerable formatters = null) + [MemberNotNull(nameof(_formatters))] + private void SetFormatters(IEnumerable? formatters = null) { var cd = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); @@ -105,7 +108,7 @@ private void SetFormatters(IEnumerable formatters = null) // warning: ReloadLoggerOptions can be called before the ctor completed,... before registering all of the state used in this method need to be initialized private void ReloadLoggerOptions(ConsoleLoggerOptions options) { - if (options.FormatterName == null || !_formatters.TryGetValue(options.FormatterName, out ConsoleFormatter logFormatter)) + if (options.FormatterName == null || !_formatters.TryGetValue(options.FormatterName, out ConsoleFormatter? logFormatter)) { #pragma warning disable CS0618 logFormatter = options.Format switch @@ -130,7 +133,7 @@ private void ReloadLoggerOptions(ConsoleLoggerOptions options) /// public ILogger CreateLogger(string name) { - if (_options.CurrentValue.FormatterName == null || !_formatters.TryGetValue(_options.CurrentValue.FormatterName, out ConsoleFormatter logFormatter)) + if (_options.CurrentValue.FormatterName == null || !_formatters.TryGetValue(_options.CurrentValue.FormatterName, out ConsoleFormatter? logFormatter)) { #pragma warning disable CS0618 logFormatter = _options.CurrentValue.Format switch @@ -146,14 +149,9 @@ public ILogger CreateLogger(string name) } } - return _loggers.TryGetValue(name, out ConsoleLogger logger) ? + return _loggers.TryGetValue(name, out ConsoleLogger? logger) ? logger : - _loggers.GetOrAdd(name, new ConsoleLogger(name, _messageQueue) - { - Options = _options.CurrentValue, - ScopeProvider = _scopeProvider, - Formatter = logFormatter, - }); + _loggers.GetOrAdd(name, new ConsoleLogger(name, _messageQueue, logFormatter, _scopeProvider, _options.CurrentValue)); } #pragma warning disable CS0618 diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/FormatterOptionsMonitor.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/FormatterOptionsMonitor.cs index 16f1d5572893c..a47d455b4f5f1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/FormatterOptionsMonitor.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/FormatterOptionsMonitor.cs @@ -17,9 +17,9 @@ public FormatterOptionsMonitor(TOptions options) _options = options; } - public TOptions Get(string name) => _options; + public TOptions Get(string? name) => _options; - public IDisposable OnChange(Action listener) + public IDisposable? OnChange(Action listener) { return null; } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs index f6bdea56c57bd..2e07ed89cc43d 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Runtime.InteropServices; @@ -15,16 +16,16 @@ namespace Microsoft.Extensions.Logging.Console { internal sealed class JsonConsoleFormatter : ConsoleFormatter, IDisposable { - private IDisposable _optionsReloadToken; + private IDisposable? _optionsReloadToken; public JsonConsoleFormatter(IOptionsMonitor options) - : base (ConsoleFormatterNames.Json) + : base(ConsoleFormatterNames.Json) { ReloadLoggerOptions(options.CurrentValue); _optionsReloadToken = options.OnChange(ReloadLoggerOptions); } - public override void Write(in LogEntry logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter) + public override void Write(in LogEntry logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter) { string message = logEntry.Formatter(logEntry.State, logEntry.Exception); if (logEntry.Exception == null && message == null) @@ -34,7 +35,7 @@ public override void Write(in LogEntry logEntry, IExternalScopeP LogLevel logLevel = logEntry.LogLevel; string category = logEntry.Category; int eventId = logEntry.EventId.Id; - Exception exception = logEntry.Exception; + Exception? exception = logEntry.Exception; const int DefaultBufferSize = 1024; using (var output = new PooledByteBufferWriter(DefaultBufferSize)) { @@ -102,7 +103,7 @@ private static string GetLogLevelString(LogLevel logLevel) }; } - private void WriteScopeInformation(Utf8JsonWriter writer, IExternalScopeProvider scopeProvider) + private void WriteScopeInformation(Utf8JsonWriter writer, IExternalScopeProvider? scopeProvider) { if (FormatterOptions.IncludeScopes && scopeProvider != null) { @@ -185,10 +186,11 @@ private static void WriteItem(Utf8JsonWriter writer, KeyValuePair Convert.ToString(obj, CultureInfo.InvariantCulture); + private static string? ToInvariantString(object? obj) => Convert.ToString(obj, CultureInfo.InvariantCulture); internal JsonConsoleFormatterOptions FormatterOptions { get; set; } + [MemberNotNull(nameof(FormatterOptions))] private void ReloadLoggerOptions(JsonConsoleFormatterOptions options) { FormatterOptions = options; diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj index 7948275ff4799..4fc4123708397 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj @@ -1,9 +1,9 @@ - + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + enable true - annotations true $(DefineConstants);NO_SUPPRESS_GC_TRANSITION diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs index 0ec05de570060..7ca3f232e87dd 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; @@ -13,15 +14,16 @@ internal sealed class SimpleConsoleFormatter : ConsoleFormatter, IDisposable private const string LoglevelPadding = ": "; private static readonly string _messagePadding = new string(' ', GetLogLevelString(LogLevel.Information).Length + LoglevelPadding.Length); private static readonly string _newLineWithMessagePadding = Environment.NewLine + _messagePadding; - private IDisposable _optionsReloadToken; + private IDisposable? _optionsReloadToken; public SimpleConsoleFormatter(IOptionsMonitor options) - : base (ConsoleFormatterNames.Simple) + : base(ConsoleFormatterNames.Simple) { ReloadLoggerOptions(options.CurrentValue); _optionsReloadToken = options.OnChange(ReloadLoggerOptions); } + [MemberNotNull(nameof(FormatterOptions))] private void ReloadLoggerOptions(SimpleConsoleFormatterOptions options) { FormatterOptions = options; @@ -34,7 +36,7 @@ public void Dispose() internal SimpleConsoleFormatterOptions FormatterOptions { get; set; } - public override void Write(in LogEntry logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter) + public override void Write(in LogEntry logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter) { string message = logEntry.Formatter(logEntry.State, logEntry.Exception); if (logEntry.Exception == null && message == null) @@ -45,8 +47,8 @@ public override void Write(in LogEntry logEntry, IExternalScopeP ConsoleColors logLevelColors = GetLogLevelConsoleColors(logLevel); string logLevelString = GetLogLevelString(logLevel); - string timestamp = null; - string timestampFormat = FormatterOptions.TimestampFormat; + string? timestamp = null; + string? timestampFormat = FormatterOptions.TimestampFormat; if (timestampFormat != null) { DateTimeOffset dateTimeOffset = GetCurrentDateTime(); @@ -63,11 +65,11 @@ public override void Write(in LogEntry logEntry, IExternalScopeP CreateDefaultLogMessage(textWriter, logEntry, message, scopeProvider); } - private void CreateDefaultLogMessage(TextWriter textWriter, in LogEntry logEntry, string message, IExternalScopeProvider scopeProvider) + private void CreateDefaultLogMessage(TextWriter textWriter, in LogEntry logEntry, string message, IExternalScopeProvider? scopeProvider) { bool singleLine = FormatterOptions.SingleLine; int eventId = logEntry.EventId.Id; - Exception exception = logEntry.Exception; + Exception? exception = logEntry.Exception; // Example: // info: ConsoleApp.Program[10] @@ -175,7 +177,7 @@ private ConsoleColors GetLogLevelConsoleColors(LogLevel logLevel) }; } - private void WriteScopeInformation(TextWriter textWriter, IExternalScopeProvider scopeProvider, bool singleLine) + private void WriteScopeInformation(TextWriter textWriter, IExternalScopeProvider? scopeProvider, bool singleLine) { if (FormatterOptions.IncludeScopes && scopeProvider != null) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs index 7a3e6dabb925c..9ee390ed6ebfa 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; using Microsoft.Extensions.Logging.Abstractions; @@ -11,7 +12,7 @@ namespace Microsoft.Extensions.Logging.Console { internal sealed class SystemdConsoleFormatter : ConsoleFormatter, IDisposable { - private IDisposable _optionsReloadToken; + private IDisposable? _optionsReloadToken; public SystemdConsoleFormatter(IOptionsMonitor options) : base(ConsoleFormatterNames.Systemd) @@ -20,6 +21,7 @@ public SystemdConsoleFormatter(IOptionsMonitor options) _optionsReloadToken = options.OnChange(ReloadLoggerOptions); } + [MemberNotNull(nameof(FormatterOptions))] private void ReloadLoggerOptions(ConsoleFormatterOptions options) { FormatterOptions = options; @@ -32,7 +34,7 @@ public void Dispose() internal ConsoleFormatterOptions FormatterOptions { get; set; } - public override void Write(in LogEntry logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter) + public override void Write(in LogEntry logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter) { string message = logEntry.Formatter(logEntry.State, logEntry.Exception); if (logEntry.Exception == null && message == null) @@ -42,7 +44,7 @@ public override void Write(in LogEntry logEntry, IExternalScopeP LogLevel logLevel = logEntry.LogLevel; string category = logEntry.Category; int eventId = logEntry.EventId.Id; - Exception exception = logEntry.Exception; + Exception? exception = logEntry.Exception; // systemd reads messages from standard out line-by-line in a 'message' format. // newline characters are treated as message delimiters, so we must replace them. // Messages longer than the journal LineMax setting (default: 48KB) are cropped. @@ -54,7 +56,7 @@ public override void Write(in LogEntry logEntry, IExternalScopeP textWriter.Write(logLevelString); // timestamp - string timestampFormat = FormatterOptions.TimestampFormat; + string? timestampFormat = FormatterOptions.TimestampFormat; if (timestampFormat != null) { DateTimeOffset dateTimeOffset = GetCurrentDateTime(); @@ -116,7 +118,7 @@ private static string GetSyslogSeverityString(LogLevel logLevel) }; } - private void WriteScopeInformation(TextWriter textWriter, IExternalScopeProvider scopeProvider) + private void WriteScopeInformation(TextWriter textWriter, IExternalScopeProvider? scopeProvider) { if (FormatterOptions.IncludeScopes && scopeProvider != null) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs index 78e17092a5f0e..8c4b68ba6193b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs @@ -38,37 +38,35 @@ protected string GetMessage(List contexts) var errorSink = new ConsoleSink(); var console = new TestConsole(sink); var errorConsole = new TestConsole(errorSink); - var consoleLoggerProcessor = new TestLoggerProcessor(); - consoleLoggerProcessor.Console = console; - consoleLoggerProcessor.ErrorConsole = errorConsole; + var consoleLoggerProcessor = new TestLoggerProcessor(console, errorConsole); - var logger = new ConsoleLogger(_loggerName, consoleLoggerProcessor); - logger.ScopeProvider = new LoggerExternalScopeProvider(); - logger.Options = options ?? new ConsoleLoggerOptions(); var formatters = new ConcurrentDictionary(ConsoleLoggerTest.GetFormatters(simpleOptions, systemdOptions, jsonOptions).ToDictionary(f => f.Name)); + ConsoleFormatter? formatter = null; + var loggerOptions = options ?? new ConsoleLoggerOptions(); Func levelAsString; int writesPerMsg; - switch (logger.Options.FormatterName) + switch (loggerOptions.FormatterName) { case ConsoleFormatterNames.Simple: levelAsString = ConsoleLoggerTest.LogLevelAsStringDefault; writesPerMsg = 2; - logger.Formatter = formatters[ConsoleFormatterNames.Simple]; + formatter = formatters[ConsoleFormatterNames.Simple]; break; case ConsoleFormatterNames.Systemd: levelAsString = ConsoleLoggerTest.GetSyslogSeverityString; writesPerMsg = 1; - logger.Formatter = formatters[ConsoleFormatterNames.Systemd]; + formatter = formatters[ConsoleFormatterNames.Systemd]; break; case ConsoleFormatterNames.Json: levelAsString = ConsoleLoggerTest.GetJsonLogLevelString; writesPerMsg = 1; - logger.Formatter = formatters[ConsoleFormatterNames.Json]; + formatter = formatters[ConsoleFormatterNames.Json]; break; default: - throw new ArgumentOutOfRangeException(nameof(logger.Options.FormatterName)); + throw new ArgumentOutOfRangeException(nameof(loggerOptions.FormatterName)); } + var logger = new ConsoleLogger(_loggerName, consoleLoggerProcessor, formatter, new LoggerExternalScopeProvider(), loggerOptions); return (logger, sink, errorSink, levelAsString, writesPerMsg); } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs index ebe9985a245d2..7ab86fbf509ac 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs @@ -45,32 +45,30 @@ private static (ConsoleLogger Logger, ConsoleSink Sink, ConsoleSink ErrorSink, F var errorSink = new ConsoleSink(); var console = new TestConsole(sink); var errorConsole = new TestConsole(errorSink); - var consoleLoggerProcessor = new TestLoggerProcessor(); - consoleLoggerProcessor.Console = console; - consoleLoggerProcessor.ErrorConsole = errorConsole; + var consoleLoggerProcessor = new TestLoggerProcessor(console, errorConsole); - var logger = new ConsoleLogger(_loggerName, consoleLoggerProcessor); - logger.ScopeProvider = new LoggerExternalScopeProvider(); - logger.Options = options ?? new ConsoleLoggerOptions(); var formatters = new ConcurrentDictionary(GetFormatters().ToDictionary(f => f.Name)); + ConsoleFormatter? formatter = null; + var loggerOptions = options ?? new ConsoleLoggerOptions(); Func levelAsString; int writesPerMsg; - switch (logger.Options.Format) + switch (loggerOptions.Format) { case ConsoleLoggerFormat.Default: levelAsString = LogLevelAsStringDefault; writesPerMsg = 2; - logger.Formatter = formatters[ConsoleFormatterNames.Simple]; + formatter = formatters[ConsoleFormatterNames.Simple]; break; case ConsoleLoggerFormat.Systemd: levelAsString = GetSyslogSeverityString; writesPerMsg = 1; - logger.Formatter = formatters[ConsoleFormatterNames.Systemd]; + formatter = formatters[ConsoleFormatterNames.Systemd]; break; default: - throw new ArgumentOutOfRangeException(nameof(logger.Options.Format)); + throw new ArgumentOutOfRangeException(nameof(loggerOptions.Format)); } + var logger = new ConsoleLogger(_loggerName, consoleLoggerProcessor, formatter, new LoggerExternalScopeProvider(), loggerOptions); UpdateFormatterOptions(logger.Formatter, logger.Options); VerifyDeprecatedPropertiesUsedOnNullFormatterName(logger); @@ -1115,14 +1113,11 @@ public void LogAfterDisposeWritesLog() // Arrange var sink = new ConsoleSink(); var console = new TestConsole(sink); - var processor = new ConsoleLoggerProcessor(); - processor.Console = console; + var processor = new ConsoleLoggerProcessor(console, null!); var formatters = new ConcurrentDictionary(GetFormatters().ToDictionary(f => f.Name)); - var logger = new ConsoleLogger(_loggerName, loggerProcessor: processor); - logger.Options = new ConsoleLoggerOptions(); + var logger = new ConsoleLogger(_loggerName, loggerProcessor: processor, formatters[ConsoleFormatterNames.Simple], null, new ConsoleLoggerOptions()); Assert.Null(logger.Options.FormatterName); - logger.Formatter = formatters[ConsoleFormatterNames.Simple]; UpdateFormatterOptions(logger.Formatter, logger.Options); // Act processor.Dispose(); @@ -1374,7 +1369,7 @@ private string CreateHeader(ConsoleLoggerFormat format, int eventId = 0) internal class TestLoggerProcessor : ConsoleLoggerProcessor { - public TestLoggerProcessor() + public TestLoggerProcessor(IConsole console, IConsole errorConsole) : base(console, errorConsole) { }