ILogger必须通过DI容器构造函数注入,不可new;结构化日志须用{FieldName}占位符而非字符串拼接;生产环境需正确配置Console等提供程序,确保日志输出可达。

别自己 new ILogger,也别在静态上下文里硬造实例——90% 的日志失效、请求 ID 丢失、级别不生效问题都源于此。
ILogger 必须通过构造函数注入,不能手动 new
ASP.NET Core 的 ILogger 是接口,没有具体实现。它必须由 DI 容器提供,才能参与日志配置、作用域(如 RequestId)、过滤规则和统一调级。
- 错误做法:
new LoggerFactory().CreateLogger<MyService>()→ 绕过所有配置,appsettings.json中的日志级别失效 - 控制器中正确写法:
public HomeController(ILogger<HomeController> logger) - 普通服务类(如
OrderService)需先注册进 DI:services.AddScoped<OrderService>(),否则构造函数参数不会被解析 - 若服务未注册或需在
Program.cs顶层代码中用,取app.Services.GetRequiredService<ILogger<Program>>(),而非自己 new
结构化日志必须用 {FieldName} 占位符,不是字符串拼接
{UserId} 不是语法糖,而是日志引擎识别结构化字段的标记。值会被提取为独立 JSON 字段,支持 Kibana/Seq 按字段过滤或聚合。
- 错误写法:
logger.LogInformation("User " + userId + " failed login")→ 纯文本,userId不可索引 - 正确写法:
logger.LogInformation("Login failed for user {UserId}", userId) - 多个参数顺序必须严格对应:
logger.LogWarning("Order {OrderId} failed after {RetryCount} retries", orderId, retryCount) - 禁止在占位符里写表达式:
{user.Name}不会求值,应拆成{UserName}并传user.Name
本地有日志,IIS/Linux 容器里“消失”?大概率输出目标没配对
默认只启用 Console 和 Debug 提供程序。IIS 会截断 Console 输出;Linux 容器中 stdout 才是日志采集入口(fluentd/loki 依赖它);写文件路径在容器里基本等于丢日志。
- 生产环境必须确保
builder.Logging.AddConsole()被调用(哪怕只是保留它) - 要用文件日志,路径不能硬编码:
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "logs"),且提前Directory.CreateDirectory() - Docker 部署时,检查是否漏了
builder.Host.UseSerilog()或builder.Host.UseNLog()—— 第三方框架若没在Use()中注册,会静默 fallback 到空配置 - 第三方包如
Microsoft.Extensions.Logging.File需显式安装:dotnet add package Microsoft.Extensions.Logging.File
LoggerMessage.Define 和源生成日志适合高频场景,但别过早优化
编译时日志(LoggerMessage.Define 或 [LoggerMessage] 源生成)能避免装箱、减少分配,性能比普通 LogInformation 高 2–3 倍,但只在日志量极大(如每秒万级)时才值得引入。
- 必须用
partial类或方法,编译器自动生成实现 - 静态扩展写法示例:
public static partial void CouldNotOpenSocket(this ILogger logger, string hostName) - 非静态用法需主构造函数含
ILogger参数:public partial class InstanceLoggingExample(ILogger logger) - 日常业务逻辑中,优先用标准
ILogger<T>注入 + 占位符,更易读、易维护、调试友好
最常被忽略的是:日志提供程序的注册顺序、配置文件是否「始终复制」、以及占位符与参数的严格一一对应——这三个点出错,日志要么不写,要么写了也查不到。


















