NLog 中 Callsite 布局渲染器的性能影响

问题描述 投票:0回答:2

NLog 能够通过

${callsite:className=Boolean:fileName=Boolean:includeSourcePath=Boolean:methodName=Boolean}:
包含调用点信息 渲染器。

我假设 NLog 获取堆栈跟踪来实现此功能。

我想知道是否是这种情况,或者 NLog 的优化是否超出了在每个日志记录调用上创建新的堆栈跟踪的范围,以及在写入大量日志条目的应用程序中对性能有何影响?

.net performance nlog
2个回答
4
投票

.NET 框架没有提供比使用

StackTrace
类更多的选项 [1] 来获取堆栈跟踪,无论是直接使用还是通过
Exception
Environment.StackTrace
作为字符串,因此 NLog 能做的就很少了。此外,对于每个日志调用,调用堆栈(可能)会有所不同。一个例外是循环内的日志调用。但即使在这种情况下,也需要一些机制来帮助 NLog 知道该调用是从与前一个调用“相同的位置”发出的。这只能通过(再次)查看调用堆栈来确定。

所以,总而言之,我认为 NLog 必须完全做到这一点:捕获正在进行的每个日志调用的调用堆栈(尽管不是针对处理调用的每个布局/附加程序) - 就像 log4net 一样,它“警告”关于此选项是一个日志调用频率高的性能问题。

无论如何,您可能想查看,它也表明(尽管我没有在调试器中单步调试它),每个日志调用都会捕获一个调用堆栈。

更新 为了完整起见,从 .NET 4.5 开始,可以使用 caller info 属性。但它们有自己的“限制”,比如不包含类型名。然而,NLog 目前尚未使用它们。

[1] 除了使用某些 IL 级别重写或在调试器中运行应用程序之外。


0
投票

NLog v5 添加了对使用 Caller Info-Attributes 的支持,因此添加 ${callsite} 将不需要捕获完整的 StackTrace。

使用 NLog v5 记录呼叫者信息成员属性的示例:

_logger.ForInfoEvent()
       .Message("This is a fluent message {0}", "test")
       .Property("PropertyName", "PropertyValue")
       .Log();  // Log-method captures the callsite

注意,可以考虑指定

${callsite:captureStackTrace=false}
以确保 NLog 永远不会自动捕获完整的 StackTrace,以防日志语句未提供调用者成员信息。

© www.soinside.com 2019 - 2024. All rights reserved.