Serilog 仅记录数组的第一个元素

Fab*_*ian 10 c# serilog asp.net-core microsoft-extensions-logging

我正在使用 Serilog 2.10.0 登录 .NET 5 上的 ASP.NET Core 应用程序。当尝试记录只有一个参数且该参数是一个数组的事件时,我遇到了问题。以下是一些示例代码和 JSON 文件接收器的日志输出:

var myArray = new string[] { "foo", "bar" };
logger.LogInformation("Log stuff: {@MyArray}", myArray);
Run Code Online (Sandbox Code Playgroud)
{"@t":"2021-02-22T14:09:46.8673482Z","@mt":"Log stuff: {@MyArray}","MyArray":"foo","SourceContext":"MyNamespace.MyClass"}
Run Code Online (Sandbox Code Playgroud)

logger是通过依赖注入注入的 ILogger。记录的事件仅包含我的字符串数组的第一个元素。如果我添加另一个参数,字符串数组将被正确记录。我尝试过使用和不@使用不同的水槽。

这是一个带有附加参数的修改示例,其工作原理符合我的预期:

var myArray = new string[] { "foo", "bar" };
logger.LogInformation("Log stuff: {baz} {@MyArray}", "baz", myArray);
Run Code Online (Sandbox Code Playgroud)
{"@t":"2021-02-22T14:19:21.3580354Z","@mt":"Log stuff: {baz} {@MyArray}","baz":"baz","MyArray":["foo","bar"],"SourceContext":"MyNamespace.MyClass"}
Run Code Online (Sandbox Code Playgroud)

我怀疑我在这里误解了可变参数函数如何确定模板字符串中参数和变量之间的映射。但我无法找到一种方法可以使其在不添加不相关的附加参数的情况下正常工作。

如何让 Serilog 正确处理以单个数组作为参数的日志消息?

Roa*_* S. 19

我能够重现您的问题。Resharper 标记了问题,如下面的屏幕截图所示。

在此输入图像描述

如果我们输入 LoggerExtensions#LogInformation 的源代码,它具有以下签名:

public static void LogInformation(this ILogger logger, string message, params object[] args)
Run Code Online (Sandbox Code Playgroud)

最后一个参数是params object[] args,当传入单个数组时,该方法认为该数组是参数列表并将数组强制转换为object[],而您的意图是将数组作为参数传入。通过更改模板可以确认这一点:

_logger.LogInformation("Log stuff: {FirstElement} {SecondElement}", myArray); 
Run Code Online (Sandbox Code Playgroud)

这将输出Log stuff: foo bar. 上面的代码与以下代码具有相同的逻辑和行为:

_logger.LogInformation("Log stuff: {FirstElement} {SecondElement}", "foo", "bar");
Run Code Online (Sandbox Code Playgroud)

将数组更改为列表,或者像 @IharYakimush 建议的那样,将数组简单地转换为object,就可以解决问题,因为集合现在将被视为参数,而不是参数列表。

_logger.LogInformation("Log stuff: {MyArray}", (object)myArray);
Run Code Online (Sandbox Code Playgroud)

  • 不需要执行不必要的列表创建。使用以下方法: `_logger.LogInformation("Log stuff: {MyArray}", (object)myArray);` (5认同)