您的位置:首页 >C# Serilog日志上下文使用方法
发布于2026-02-12 阅读(0)
扫一扫,手机访问
LogContext.PushProperty未生效是因为缺少Enrich.FromLogContext()配置;该enricher需全局启用才能使PushProperty的属性出现在日志中,否则上下文属性不会被注入输出。

直接调用 LogContext.PushProperty("UserId", 123) 后日志没带这个字段,大概率是因为你没在日志配置中启用上下文支持。Serilog 默认不自动注入 LogContext 的属性,必须显式启用——比如用 Enrich.FromLogContext()。
常见错误是只写了 PushProperty,却漏掉 enricher 配置:
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext() // ⚠️ 必须加这一行
.WriteTo.Console()
.CreateLogger();
Enrich.FromLogContext(),PushProperty 像往水里扔石头,涟漪根本传不到日志输出AsyncLocal<ILogEventEnricher>),跨线程或新 Task 会丢失LogContext 的生命周期绑定到当前 ExecutionContext,但不是所有异步场景都自动流动。尤其在 ASP.NET Core 中,Controller 方法里 push 的属性,在 await 后的 lambda 或后台任务里可能已失效。
推荐做法是:在入口处(如中间件、Controller Action)push,且尽量避免在 Task.Run 或手动切换同步上下文的地方依赖它:
UseSerilogRequestLogging 中间件前注册 Enrich.FromLogContext(),再配合 LogContext.PushProperty("TraceId", HttpContext.TraceIdentifier)Task.Run(() => { LogContext.PushProperty(...); DoWork(); }) 里 push —— 子线程没有父上下文Log.ForContext("UserId", userId) 创建子 logger二者都能加属性,但作用域和机制完全不同:
LogContext.PushProperty("Key", value):把属性压入当前逻辑调用栈,所有后续 Log.Information(...) 都自动携带(只要没被 pop);适合请求级、事务级统一字段Log.ForContext("Key", value).Information(...):仅本次日志事件携带,不污染后续日志;适合单条日志的临时补充,比如记录某个计算结果PushProperty 支持多次同名覆盖(后 push 的生效),而 ForContext 是链式构造新 logger,不影响原 loggerForContext 每次新建 logger 对象有开销;PushProperty 是栈操作,更轻量,但需注意别漏 pop 导致内存泄漏(不过 Serilog 内部用 AsyncLocal 管理,通常无需手动 pop)PushProperty 默认存的是调用时的值快照。如果想每次日志输出时重新计算(例如生成唯一 ID、取当前毫秒数),得用它的重载版本传入 Func<object>:
LogContext.PushProperty("LogTime", () => DateTime.Now.ToString("HH:mm:ss.fff"));
LogContext.PushProperty("RequestId", () => Guid.NewGuid().ToString("N"));
这样每次日志序列化时都会执行函数,拿到最新值。但要注意:
null,否则该字段不会出现在日志中(可返回 "null" 字符串兜底)真正难处理的从来不是怎么加属性,而是上下文在异步分叉、线程切换、DI 生命周期边界处的“消失”——这些地方得靠显式传参或重构日志结构来兜底。
上一篇:塔读小说注册作者步骤详解
下一篇:电脑账户锁定设置教程
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9