当前标准做法是使用 ILogger + Microsoft.Extensions.Logging:依赖注入获取泛型 ILogger 实例,避免手动 new;日志级别需合理选用(Debug 仅开发期、Error 必传 Exception);结构化日志用占位符而非字符串插值;文件日志推荐 Serilog 或 NLog,而非手写文件写入。
用 ILogger + Microsoft.Extensions.Logging 是当前标准做法
ASP.NET Core 项目默认内置,.NET 6+ 桌面应用也推荐直接用它,而不是手写文件写入或老式 Trace。核心是依赖注入 + 预置提供程序(如控制台、Debug、文件),不耦合具体输出方式。
关键点:
-
ILogger是泛型接口,T一般填当前类类型,用于日志分类和过滤 - 必须通过 DI 容器获取实例(
Program.cs中builder.Services.AddLogging()已默认注册) - 不要 new
Logger—— 手动构造会丢失作用域上下文、配置和性能优化
想写入文件?别自己拼 StreamWriter,用 FileLoggerProvider 或第三方包
.NET 原生不带文件日志提供程序,Microsoft.Extensions.Logging.Console 和 Debug 是自带的,但 File 需要额外引入。官方没推内置文件提供者,所以常见选择是:
- 用
Microsoft.Extensions.Logging.Configuration+NLog或Serilog(更推荐,配置灵活、支持滚动、结构化) - 轻量场景可用社区维护的
Microsoft.Extensions.Logging.File(注意 NuGet 包名是Microsoft.Extensions.Logging.File,不是官方第一方) - 自己封装
ILoggerProvider成本高,且容易在并发写入、日志轮转、编码错误上翻车
示例(Serilog):Log.Logger = new LoggerConfiguration().WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day).Create();
然后在 Program.cs 中调用 builder.Host.UseSerilog()
LogInformation / LogWarning / LogError 别乱用级别
日志级别不是“越详细越好”,它直接影响性能和可观测性:
-
LogDebug:仅开发期启用,发布后默认被过滤掉(除非显式配置最低级别为Debug) -
LogInformation:记录常规流程,比如“用户登录成功”,但别塞敏感字段(如密码明文、token) -
LogWarning:异常未抛出但可能有问题,比如重试三次后降级处理 -
LogError:必须伴随Exception对象传入(logger.LogError(ex, "msg")),否则堆栈丢失
错误示范:logger.LogError("Failed to connect: " + ex.Message) → 堆栈没了,无法定位根本原因