为什么 ILogger 无法多次使用参数数组的同一位置?

Fra*_*oya 16 c# format logging

我正在尝试跟踪/记录有关我正在处理的消息调度过程的一些信息。

当您尝试多次使用参数数组中某个具体位置的对象时,会引发异常。

    private void LogRandomInfo(ILogger Log, string processName, string messageType)
    {
        try
        {
            Log.LogInformation("{0} : The event {0} has received the info {1}", processName, messageType);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我期待与我们使用string.Format. 在 中string.Format,您可以打印所请求值的任意次数。

因此string.Format("{0} {0} {0}", 1);将打印1 1 1,但 Log.LogInformation("{0} {0} {0}", 1);会抛出 Index 超出数组范围的异常。

有没有简单的解释为什么会发生这种情况?

使用的日志库是Microsoft.Extensions.Logging

can*_*on7 40

看起来你正在使用Microsoft.Extensions.Logging?

Microsoft.Extensions.Logging使用结构化日志记录。这意味着占位符不是引用传递的不同参数的数字,而是与每个参数关联的名称。

来自文档

每个日志指定一个消息模板。消息模板可以包含为其提供参数的占位符。使用名称作为占位符,而不是数字。
...

_logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
Run Code Online (Sandbox Code Playgroud)

...

占位符的顺序(而不是其名称)决定了使用哪些参数来提供其值。在以下代码中,请注意消息模板中的参数名称不按顺序排列:

string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Run Code Online (Sandbox Code Playgroud)

日志记录框架以这种方式工作,以便日志记录提供程序可以实现语义日志记录,也称为结构化日志记录。参数本身被传递到日志系统,而不仅仅是格式化的消息模板。此信息使日志记录提供程序能够将参数值存储为字段。例如,假设记录器方法调用如下所示:

_logger.LogInformation("Getting item {ID} at {RequestTime}", id, DateTime.Now);
Run Code Online (Sandbox Code Playgroud)

如果将日志发送到 Azure 表存储,每个 Azure 表实体都可以具有 ID 和 RequestTime 属性,这可以简化对日志数据的查询。查询可以找到特定 RequestTime 范围内的所有日志,而无需解析文本消息中的时间。