如何在C# Web API中使用Serilog自定义指定格式的JSON日志并添加运行时字段
如何在C# Web API中使用Serilog自定义指定格式的JSON日志并添加运行时字段
看起来你已经搭好了Serilog的基础配置,现在要改成指定的JSON格式,还要加上那些动态的运行时字段对吧?我来一步步帮你实现:
第一步:修改appsettings.json,让Serilog输出指定格式的JSON
首先,我们需要把控制台输出换成JSON格式,并且匹配你要的字段结构。修改你的appsettings.json里的Serilog配置:
"Serilog": { "Using": ["Serilog.Sinks.Console"], "MinimumLevel": { "Default": "Information" }, "Enrich": ["FromLogContext"], "WriteTo": [ { "Name": "Console", "Args": { "outputTemplate": "{{\"LEVEL\": \"{Level:u}\", \"TIMESTAMP\": \"{Timestamp:yyyy-MM-dd HH:mm:ss,fff}\", \"CALLER\": \"{Properties:Caller}\", \"EVENT_NAME\": \"{Properties:EventName}\", \"ERRORID\": \"{Properties:ErrorId}\", \"MESSAGE\": \"{Message}\"}} {NewLine}{Exception}", "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console" } } ] }
这个模板会直接输出你要的JSON结构,注意双引号的转义处理即可。
第二步:添加运行时动态字段(CALLER、EVENT_NAME、ERRORID)
这些动态字段需要我们把值注入到Serilog的日志上下文里,这样日志输出时就能自动包含它们,有两种常用方式:
方式1:单个日志调用时手动添加
在需要记录日志的方法里,用LogContext.PushProperty临时注入字段:
using Serilog.Context; // 示例:从请求头获取客户端名称,当前方法名作为事件名,自定义错误ID var callerName = HttpContext.Request.Headers["Client-Name"].FirstOrDefault() ?? "UNKNOWN_CLIENT"; var eventName = nameof(GetUserInfo); // 获取当前方法名 var errorId = "10001"; // 用using包裹,确保上下文在日志完成后自动释放 using (LogContext.PushProperty("Caller", callerName)) using (LogContext.PushProperty("EventName", eventName)) using (LogContext.PushProperty("ErrorId", errorId)) { Log.Error("INVALID REQUEST"); }
方式2:中间件统一处理全局字段
如果像CALLER这种字段是每个请求都需要的,可以写个中间件自动注入,不用每次手动加:
public class LogContextMiddleware { private readonly RequestDelegate _next; public LogContextMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var callerName = context.Request.Headers["Client-Name"].FirstOrDefault() ?? "UNKNOWN_CLIENT"; // 注入客户端名称到日志上下文 using (LogContext.PushProperty("Caller", callerName)) { await _next(context); } } } // 在Program.cs里注册中间件(要放在其他业务中间件之前) app.UseMiddleware<LogContextMiddleware>();
第三步:确保Serilog配置正确生效
你的logConfig.cs可以简化一下,直接在Program.cs里注册Serilog更直观:
var builder = WebApplication.CreateBuilder(args); // 先配置Serilog builder.Host.UseSerilog((context, config) => { config.ReadFrom.Configuration(context.Configuration); }); // 再添加其他服务 builder.Services.AddControllers(); // ...其他业务服务注册 var app = builder.Build(); // 注册中间件(包括上面的LogContextMiddleware) app.UseHttpsRedirection(); app.UseMiddleware<LogContextMiddleware>(); app.UseAuthorization(); app.MapControllers(); app.Run();
测试效果
当你触发日志后,控制台会输出完全符合你要求的JSON格式:
{"LEVEL":"ERROR","TIMESTAMP":"2023-06-07 14:07:59,983","CALLER":"MY_CLIENT","EVENT_NAME":"GetUserInfo","ERRORID":"10001","MESSAGE":"INVALID REQUEST"}
备注:内容来源于stack exchange,提问作者learningdotnet
相关产品推荐
相关产品推荐

