使用多个参数在 NLog 中将对象打印为 JSON

Print object as JSON in NLog with multiple arguments

我开始使用 NLog,只有一个简单的文件输出:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
        <target
            name="logFile"
            xsi:type="File"
            layout="${longdate} ${callsite} ${message} ${exception:format=tostring}"
            fileName="${basedir}/logs/Log.txt"
            archiveFileName="${basedir}/logs/Log.{#}.txt"
            archiveEvery="Day"
            archiveNumbering="Rolling"
            maxArchiveFiles="60"
            concurrentWrites="true"
            keepFileOpen="false"
            encoding="iso-8859-2" />
    </targets>
    <rules>
        <logger name="*" minlevel="Trace" writeTo="logFile" />
    </rules>
</nlog>

我发现我可以 serialise objects in JSON form 进行日志记录,使用 @ 前缀,例如:

Logger.Debug("Request: {@0}", request);

这很好用,只要我只有一个参数。但后来我开始在我的日志中发现未格式化的占位符:

Processing purchase order {0}/{1} for user {@2}

经过一些调查,这似乎与我使用的是命名索引还是编号索引以及 JSON-格式前缀 @ 的位置有关。我写了一个快速测试:

User user = new User("Bill", "Gates", "12345");

Logger.Info("All numbered");
Logger.Info("0: {@0}, 1: {1}", user, 1);       // 0: {"FirstName":"Bill", "LastName":"Gates", "Id":"12345"}, 1: 1 
Logger.Info("0: {0}, 1: {@1}", 1, user);       // 0: {0}, 1: {@1} 

Logger.Info("Object named, int numbered");
Logger.Info("User: {@user}, 1: {1}", user, 1); // User: {"FirstName":"Bill", "LastName":"Gates", "Id":"12345"}, 1: 1 
Logger.Info("0: {0}, User: {@user}", user, 1); // 0: {0}, User: {@user} 

Logger.Info("Object numbered, int named");
Logger.Info("0: {@0}, n: {n}", user, 1);       // 0: {"FirstName":"Bill", "LastName":"Gates", "Id":"12345"}, n: 1 
Logger.Info("n: {n}, 1: {@1}", 1, user);       // n: 1, 1: {"FirstName":"Bill", "LastName":"Gates", "Id":"12345"} 

Logger.Info("All named");
Logger.Info("User: {@user}, n: {n}", user, 1); // User: {"FirstName":"Bill", "LastName":"Gates", "Id":"12345"}, n: 1 
Logger.Info("n: {n}, User: {@user}", 1, user); // n: 1, User: {"FirstName":"Bill", "LastName":"Gates", "Id":"12345"} 

我做错了什么?当然规则不是“如果使用 @ 它必须是第一个参数,或者它必须遵循命名参数”。我意识到有关 @ 前缀的详细信息在结构化日志记录部分下,但我并不完全理解。我不允许将它与平面文件一起使用吗?

NLog“作弊”并且仅在看到第一个时激活其 message-template-parser place-holder 使用 message-template-logic(就像使用名字或 @)。

NLog 在不需要使用 message-template-parser 时回退到标准 string.Format。这既是为了提高性能,也是为了减少因未按预期使用 string.Format 而导致更改中断的可能性。

另请参阅:https://github.com/NLog/NLog/wiki/How-to-use-structured-logging#combine-indexed-and-structured-logging