Skip to content

[Microsoft.Extensions.Logging] Bug: Logging arrays is broken and behaves unreliably #103338

Closed
@czdietrich

Description

@czdietrich

Description

Depending on which option is used for logging (Source Generators, LoggerMessage.Define, Logger.Log) the resulting format for arrays (or any other type of enumeration) is different and sometimes even unusable.

On the first glance the issue seems to be part of the LogValuesFormatter that tries to specially handle enumerations using TryFormatArgumentIfNullOrEnumerable.

The issue is probably caused here where TryFormatArgumentIfNullOrEnumerable is not invoked for every parameter in some combinations:

{
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);
}

Reproduction Steps

  1. Create a new console application for net8.0
  2. Add Microsoft.Extensions.Logging.Console NuGet in version 8.0.0
  3. Paste the following code into Program.cs
using Microsoft.Extensions.Logging;

public static partial class Program
{
    private const string MessageTemplate = "Log {Number}: {Array1} and {Array2}";

    private static readonly string[] Array1 = ["a", "b", "c"];
    private static readonly string[] Array2 = ["d", "e", "f"];        

    [LoggerMessage( EventId = 0, Level = LogLevel.Information, Message = MessageTemplate )]
    private static partial void LogBad(this ILogger logger, int number, string[] array1, string[] array2);

    [LoggerMessage( EventId = 0, Level = LogLevel.Information, Message = MessageTemplate )]
    private static partial void LogGood(this ILogger logger, string[] array1, string[] array2, int number);
    
    public static void Main()
    {
        var logger = LoggerFactory
            .Create( x => x.AddConsole() )
            .CreateLogger( "Logger" );

        logger.LogBad( 10, Array1, Array2 );
        logger.LogGood( Array1, Array2, 20 );

        var badDefine = LoggerMessage.Define<int, string[], string[]>( LogLevel.Information, new EventId(), MessageTemplate );
        
        badDefine( logger, 30, Array1, Array2, null );
        
        logger.LogInformation( MessageTemplate, 40, Array1, Array2 );
    }
}
  1. Run the application

Expected behavior

The resulting log should look something like this:

info: Logger[0]
      Log 10: [a, b, c] and [d, e, f]
info: Logger[0]
      Log 20: [a, b, c] and [d, e, f]
info: Logger[0]
      Log 30: [a, b, c] and [d, e, f]
info: Logger[0]
      Log 40: [a, b, c] and [d, e, f]

Actual behavior

The resulting log entries look different. Some options struggle with formatting arrays.

info: Logger[0]
      Log 10: a, b, c and System.String[]
info: Logger[0]
      Log 20: [a, b, c] and [d, e, f]
info: Logger[0]
      Log 30: a, b, c and System.String[]
info: Logger[0]
      Log 40: a, b, c and d, e, f

Regression?

No response

Known Workarounds

The issue can be minimized if the enumerations (e.g. an array) are passed as first parameters of the logging invocation. Alternatively the developer can manually format the arrays and pass the value as a string parameter.

Configuration

SDK version: 8.0.300

Other information

No response

Metadata

Metadata

Assignees

Labels

area-Extensions-Loggingin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions