From 29b517d93e9f212255c9a8e1b2b803904213496d Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Tue, 13 Aug 2024 12:31:34 -0700 Subject: [PATCH] [release/8.0-staging] Fix logging formatting --- .../src/LogValuesFormatter.cs | 28 ++++++--------- ...oft.Extensions.Logging.Abstractions.csproj | 4 +-- .../ConsoleLoggerTest.cs | 35 ++++++++++++++++--- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs index beae39c00287ad..4f9832950084c2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs @@ -192,32 +192,26 @@ internal string Format() #if NET8_0_OR_GREATER internal string Format(TArg0 arg0) { - object? arg0String = null; return - !TryFormatArgumentIfNullOrEnumerable(arg0, ref arg0String) ? + !TryFormatArgumentIfNullOrEnumerable(arg0, out object? arg0String) ? string.Format(CultureInfo.InvariantCulture, _format, arg0) : string.Format(CultureInfo.InvariantCulture, _format, arg0String); } internal string Format(TArg0 arg0, TArg1 arg1) { - object? arg0String = null, arg1String = null; return - !TryFormatArgumentIfNullOrEnumerable(arg0, ref arg0String) && - !TryFormatArgumentIfNullOrEnumerable(arg1, ref arg1String) ? - string.Format(CultureInfo.InvariantCulture, _format, arg0, arg1) : - string.Format(CultureInfo.InvariantCulture, _format, arg0String ?? arg0, arg1String ?? arg1); - } + TryFormatArgumentIfNullOrEnumerable(arg0, out object? arg0String) | TryFormatArgumentIfNullOrEnumerable(arg1, out object? arg1String) ? + string.Format(CultureInfo.InvariantCulture, _format, arg0String ?? arg0, arg1String ?? arg1) : + string.Format(CultureInfo.InvariantCulture, _format, arg0, arg1); + } internal string Format(TArg0 arg0, TArg1 arg1, TArg2 arg2) { - object? arg0String = null, arg1String = null, arg2String = null; return - !TryFormatArgumentIfNullOrEnumerable(arg0, ref arg0String) && - !TryFormatArgumentIfNullOrEnumerable(arg1, ref arg1String) && - !TryFormatArgumentIfNullOrEnumerable(arg2, ref arg2String) ? - string.Format(CultureInfo.InvariantCulture, _format, arg0, arg1, arg2) : - string.Format(CultureInfo.InvariantCulture, _format, arg0String ?? arg0, arg1String ?? arg1, arg2String ?? arg2); + TryFormatArgumentIfNullOrEnumerable(arg0, out object? arg0String) | TryFormatArgumentIfNullOrEnumerable(arg1, out object? arg1String) | TryFormatArgumentIfNullOrEnumerable(arg2, out object? arg2String) ? + string.Format(CultureInfo.InvariantCulture, _format, arg0String ?? arg0, arg1String ?? arg1, arg2String ?? arg2): + string.Format(CultureInfo.InvariantCulture, _format, arg0, arg1, arg2); } #else internal string Format(object? arg0) => @@ -259,11 +253,10 @@ internal string Format(object? arg0, object? arg1, object? arg2) => private static object FormatArgument(object? value) { - object? stringValue = null; - return TryFormatArgumentIfNullOrEnumerable(value, ref stringValue) ? stringValue : value!; + return TryFormatArgumentIfNullOrEnumerable(value, out object? stringValue) ? stringValue : value!; } - private static bool TryFormatArgumentIfNullOrEnumerable(T? value, [NotNullWhen(true)] ref object? stringValue) + private static bool TryFormatArgumentIfNullOrEnumerable(T? value, [NotNullWhen(true)] out object? stringValue) { if (value == null) { @@ -290,6 +283,7 @@ private static bool TryFormatArgumentIfNullOrEnumerable(T? value, [NotNullWhe return true; } + stringValue = null; return false; } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index cfb15ea788e9e5..12c30e271e7738 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -5,8 +5,8 @@ true true true - false - 1 + true + 2 Logging abstractions for Microsoft.Extensions.Logging. Commonly Used Types: 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 0994980590122b..ab8c88f4ba3c45 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 @@ -32,7 +32,7 @@ internal static IEnumerable GetFormatters( var defaultMonitor = new TestFormatterOptionsMonitor(simpleOptions ?? new SimpleConsoleFormatterOptions()); var systemdMonitor = new TestFormatterOptionsMonitor(systemdOptions ?? new ConsoleFormatterOptions()); var jsonMonitor = new TestFormatterOptionsMonitor(jsonOptions ?? new JsonConsoleFormatterOptions()); - var formatters = new List() { + var formatters = new List() { new SimpleConsoleFormatter(defaultMonitor), new SystemdConsoleFormatter(systemdMonitor), new JsonConsoleFormatter(jsonMonitor) @@ -86,13 +86,13 @@ private static void VerifyDeprecatedPropertiesUsedOnNullFormatterName(ConsoleLog Assert.Equal(formatter.FormatterOptions.IncludeScopes, logger.Options.IncludeScopes); Assert.Equal(formatter.FormatterOptions.UseUtcTimestamp, logger.Options.UseUtcTimestamp); Assert.Equal(formatter.FormatterOptions.TimestampFormat, logger.Options.TimestampFormat); - Assert.Equal(formatter.FormatterOptions.ColorBehavior, - logger.Options.DisableColors ? LoggerColorBehavior.Disabled : LoggerColorBehavior.Enabled); + Assert.Equal(formatter.FormatterOptions.ColorBehavior, + logger.Options.DisableColors ? LoggerColorBehavior.Disabled : LoggerColorBehavior.Enabled); } else { var formatter = Assert.IsType(logger.Formatter); - Assert.Equal(formatter.FormatterOptions.IncludeScopes, logger.Options.IncludeScopes); + Assert.Equal(formatter.FormatterOptions.IncludeScopes, logger.Options.IncludeScopes); Assert.Equal(formatter.FormatterOptions.UseUtcTimestamp, logger.Options.UseUtcTimestamp); Assert.Equal(formatter.FormatterOptions.TimestampFormat, logger.Options.TimestampFormat); } @@ -103,7 +103,7 @@ private static void UpdateFormatterOptions(ConsoleFormatter formatter, ConsoleLo // kept for deprecated apis: if (formatter is SimpleConsoleFormatter defaultFormatter) { - defaultFormatter.FormatterOptions.ColorBehavior = deprecatedFromOptions.DisableColors ? + defaultFormatter.FormatterOptions.ColorBehavior = deprecatedFromOptions.DisableColors ? LoggerColorBehavior.Disabled : LoggerColorBehavior.Enabled; defaultFormatter.FormatterOptions.IncludeScopes = deprecatedFromOptions.IncludeScopes; defaultFormatter.FormatterOptions.TimestampFormat = deprecatedFromOptions.TimestampFormat; @@ -1346,6 +1346,31 @@ public void ConsoleLoggerOptions_IncludeScopes_IsReadFromLoggingConfiguration() Assert.True(formatter.FormatterOptions.IncludeScopes); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public void LogMultipleArrays() + { + // Arrange + var t = SetUp(); + var logger = t.Logger; + var sink = t.Sink; + + var define1 = LoggerMessage.Define(LogLevel.Information, new EventId(), "Log: {Array1} and {Array2}"); + var define2 = LoggerMessage.Define(LogLevel.Information, new EventId(), "Log {Number}: {Array1} and {Array2}"); + + // Act + define1(logger, ["a", "b", "c"], ["d", "e", "f"], null); + define2(logger, 30, ["a", "b", "c"], ["d", "e", "f"], null); + + var expectedMessage1 = $"{CreateHeader(ConsoleLoggerFormat.Default)}{Environment.NewLine}{_paddingString}Log: a, b, c and d, e, f{Environment.NewLine}"; + var expectedMessage2 = $"{CreateHeader(ConsoleLoggerFormat.Default)}{Environment.NewLine}{_paddingString}Log 30: a, b, c and d, e, f{Environment.NewLine}"; + + Assert.Equal(4, sink.Writes.Count); + Assert.Equal("info", sink.Writes[0].Message); + Assert.Equal(expectedMessage1, sink.Writes[1].Message); + Assert.Equal("info", sink.Writes[2].Message); + Assert.Equal(expectedMessage2, sink.Writes[3].Message); + } + public static TheoryData FormatsAndLevels { get