C# 应用程序中的日志记录:最佳实践与工具 (.NET)
日志记录不仅仅是向文件写入消息。它是任何生产级 C# 应用程序的关键组件。没有优质的日志系统,就如同盲人摸象:错误被忽视,性能难以分析,调试如同猜谜。在本文中,我们将深入探讨 .NET 生态系统中的日志记录最佳实践,介绍流行的库(Serilog、NLog)、正确的日志级别以及结构化的数据采集方法。
1. 选择日志记录库:Serilog vs NLog
在 .NET 世界中,有多种成熟的解决方案。最流行的两个是 Serilog 和 NLog。两者都支持异步日志记录、多个接收器(输出目标),并通过 ILogger 与 .NET Core/5+ 集成。
Serilog
Serilog 以其结构化日志的理念而闻名。它传递的是对象而非简单的字符串,Serilog 会将其序列化为 JSON。这对于 Elasticsearch、Seq 或 Datadog 等系统非常理想。
// Serilog Exampleusing Serilog;
Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.Console() .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day) .CreateLogger();
Log.Information("User {UserId} logged in at {Time}", userId, DateTime.UtcNow);NLog
NLog 是一个更传统但同样强大的工具。它非常适合需要通过 XML 或代码进行灵活配置的项目。它支持文件轮转、电子邮件发送和数据库集成。
// NLog Exampleusing NLog;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
Logger.Info("User {UserId} performed an action", userId);如何选择? 如果你正在构建微服务或使用 ELK 技术栈——选择 Serilog。如果需要在旧项目中简单配置——选择 NLog。无论如何,两者都支持来自 Microsoft.Extensions.Logging 的标准 ILogger。
2. 日志级别:何时写入什么内容
最常见的错误之一是所有内容都使用 Information 级别写入,或者反过来到处使用 Debug。请使用正确的级别:
- Trace (0) — 最详细的信息:方法入口/出口、变量值。仅在调试时使用。
- Debug (1) — 对开发者有用但对运维人员无用的调试信息。
- Information (2) — 业务事件:"订单已创建"、"用户已注册"。这是主要的工作级别。
- Warning (3) — 异常但不会中断应用程序的情况:请求超时、重试连接尝试。
- Error (4) — 已处理的异常、业务逻辑错误、模块故障。
- Critical (5) — 致命错误:数据库连接丢失、内存不足、整个应用程序崩溃。
// Example of correct level usagepublic async Task<Order> CreateOrderAsync(CreateOrderRequest request){ Log.Debug("Starting order creation for user {UserId}", request.UserId);
try { var order = new Order(request); await _repository.SaveAsync(order); Log.Information("Order {OrderId} created by user {UserId}", order.Id, request.UserId); return order; } catch (DbException ex) { Log.Error(ex, "DB error creating order for user {UserId}", request.UserId); throw; // Re-throw }}3. 结构化日志:为何重要?
传统的日志记录通过 st