.NET 日志记录和跟踪

可以检测代码以生成日志,该日志用作程序运行时发生的有趣事件的记录。 若要了解应用程序的行为,可以查看日志。 .NET 在其历史记录中积累了多个不同的日志记录 API,本文将帮助你了解可用的选项。

注意

有时日志记录也称为“跟踪”,例如在一些较旧的 Windows 和 .NET API 中。 近年来,“跟踪”更常用作分布式跟踪的缩写,但这不是本文的含义。

.NET 日志记录 API

ILogger

在大多数情况下,无论是将日志记录添加到现有项目还是创建新项目,ILogger 基础结构都是一个很好的默认选择。 ILogger 支持快速的结构化日志记录、灵活配置和包括控制台在内的一系列常见接收器,运行 ASP.NET 应用时应能看到该控制台。 此外,ILogger 接口还可以用作许多第三方日志记录实现的外观,用于提供更丰富的功能和可扩展性。

ILogger 为 .NET 的 OpenTelemetry 实现提供了日志记录案例,允许将日志从应用程序流出到各种 APM 系统以进行进一步分析。

EventSource

EventSource 是一个较旧的高性能 API,具有结构化日志记录。 最初旨在与 Windows 事件跟踪 (ETW) 有效集成,但后来扩展为支持 EventPipe 跨平台跟踪和自定义接收器的 EventListener。 相比 ILoggerEventSource 的预制日志记录接收器相对较少,也不提供通过单独的配置文件进行配置的内置支持。 如果想要更严格地控制 ETWEventPipe 集成,EventSource 将非常有用,但对于常规用途日志记录,ILogger 更灵活且更易于使用。

跟踪

System.Diagnostics.TraceSystem.Diagnostics.Debug .NET 最早的日志记录 API。 这些类具有灵活的配置 API 和大型接收器生态系统,但仅支持非结构化日志记录。 在 .NET Framework 上,可以通过 app.config 文件进行配置,但在 .NET Core 中,没有基于文件的内置配置机制。 它们通常用于在调试程序下运行时为开发人员生成诊断输出。 出于向后兼容性考虑,.NET 团队继续支持这些 API,但不会添加新功能。 对于已经使用这些 API 的应用程序来说,它们是一个不错的选择。 对于尚未提交到日志记录 API 的较新应用,ILogger 可以提供更好的功能。

专用日志记录 API

控制台

System.Console 类具有 WriteWriteLine 方法,两者可用于简单日志记录场景。 虽然这些 API 很容易上手,但解决方案不会像常规用途日志记录 API 那样灵活。 控制台仅允许非结构化日志记录,并且没有配置支持来选择启用哪些日志消息或重定向到其他接收器。 将 ILogger 或 Trace API 与控制台接收器配合使用不会花费太多额外的精力,还能使日志记录保持可配置状态。

DiagnosticSource

System.Diagnostics.DiagnosticSource 用于记录日志,其中将在进程内对日志信息进行同步分析,而不是将其序列化到任何存储。 这样,源和侦听器就可以将任意 .NET 对象交换为消息,而大多数日志记录 API 则要求日志事件可序列化。 如果有效使用侦听器,此方法还能提速,以数十纳秒的速度处理日志事件。 使用这些 API 的工具通常更类似于进程内探查器,不过 API 不会在此处施加任何约束。

EventLog

System.Diagnostics.EventLog 是一个仅限于 Windows 的 API,用于将消息写入 Windows EventLog。 在许多情况下,在 Windows 上运行时,将 ILogger 与可选的 EventLog 接收器配合使用可能会提供类似的功能,而无需将应用紧密耦合到 Windows 操作系统。

日志记录术语

结构化和非结构化日志记录

日志记录可以是“结构化”或“非结构化”:

  • 非结构化:日志条目编码为人类可以读取的自由格式文本,但很难以编程方式分析和查询。
  • 结构化:日志条目具有定义明确的架构,可以采用不同的二进制和文本格式进行编码。 这些日志专为机器翻译和查询而设计,因此人类和自动化系统都可以轻松操作。

良好的结构化日志记录 API 可以提供更多功能和性能,但使用复杂程度略有增加。

接收器

大多数日志记录 API 允许将日志消息发送到称为接收器的不同目标。 某些 API 具有大量的预制接收器,而其他 API 则只有少许几个接收器。 如果没有预制接收器,通常会提供一个扩展性 API,用于创作自定义接收器,不过这需要编写更多的代码。