如何为项目中所有Serilog日志调用注入LogContext并添加ExecutionContext属性?
实现Serilog全局注入LogContext的ExecutionContext属性
1. 启用Serilog的LogContext增强
首先要在Serilog配置中开启Enrich.FromLogContext(),确保LogContext中的属性能被自动附加到所有日志事件里。在Program.cs的配置代码如下:
var builder = WebApplication.CreateBuilder(args); builder.Host.UseSerilog((context, config) => { config.ReadFrom.Configuration(context.Configuration) .Enrich.FromLogContext() // 关键配置:开启LogContext属性注入 .WriteTo.Console(); // 根据实际需求调整输出目标 });
2. 编写全局中间件注入ExecutionContext
创建一个中间件,在每个请求启动时生成并注入ExecutionContext到LogContext,确保整个请求生命周期内的所有日志都携带该属性:
public class ExecutionContextMiddleware { private readonly RequestDelegate _next; private readonly IExecutionContextGenerator _executionGenerator; public ExecutionContextMiddleware(RequestDelegate next, IExecutionContextGenerator executionGenerator) { _next = next; _executionGenerator = executionGenerator; } public async Task InvokeAsync(HttpContext context) { // 调用共享类库生成十六进制字符串 var executionId = _executionGenerator.GenerateHexString(); // 使用using块包裹,确保请求结束后自动释放LogContext using (LogContext.PushProperty("ExecutionContext", executionId)) { await _next(context); } } } // 扩展方法简化中间件注册 public static class ExecutionContextMiddlewareExtensions { public static IApplicationBuilder UseExecutionContext(this IApplicationBuilder app) { return app.UseMiddleware<ExecutionContextMiddleware>(); } }
然后在Program.cs中注册中间件(必须放在UseSerilogRequestLogging之前,保证请求日志本身也能带上ExecutionContext):
var app = builder.Build(); // 注册ExecutionContext中间件 app.UseExecutionContext(); // 启用Serilog请求日志 app.UseSerilogRequestLogging(); // 其他中间件配置 app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 注册共享类库的生成器服务
将共享类库中生成十六进制字符串的组件注册为依赖注入服务:
// 假设共享类库中的接口与实现如下 public interface IExecutionContextGenerator { string GenerateHexString(); } public class ExecutionContextGenerator : IExecutionContextGenerator { public string GenerateHexString() { // 这里替换为共享类库的实际生成逻辑,示例用GUID转十六进制 return Guid.NewGuid().ToString("N"); } } // 在Program.cs中注册服务 builder.Services.AddScoped<IExecutionContextGenerator, ExecutionContextGenerator>();
4. 验证效果
现在项目中所有日志(包括控制器、服务类、请求日志)都会自动携带ExecutionContext属性。比如控制器中的日志调用:
[ApiController] [Route("[controller]")] public class DemoController : ControllerBase { private readonly ILogger<DemoController> _logger; public DemoController(ILogger<DemoController> logger) { _logger = logger; } [HttpGet] public IActionResult Get() { _logger.LogInformation("处理Get请求"); return Ok(); } }
控制台输出的日志会包含类似这样的内容:
[INF] 处理Get请求 {ExecutionContext: "f47ac10b58cc4372a5670e02b2c3d799"}
额外说明
- 对于后台任务(比如HostedService),因为不在请求生命周期内,需要在任务执行逻辑中手动用
LogContext.PushProperty包裹代码,才能带上ExecutionContext属性。
内容的提问来源于stack exchange,提问作者gitzko
相关产品推荐
相关产品推荐

