ASP.NET Core中如何将用户名添加至Serilog日志文件名?
问题:在ASP.NET Core Web API中为Serilog日志文件名添加用户名
需求是生成类似Log_ABC_Date.txt格式、包含当前请求用户名的日志文件,以下是原配置、尝试的更新及解决方案:
原配置与代码
appsettings.json 配置
"Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "WriteTo": [ { "Name": "File", "Args": { "Path": "E:\\WebSite\\Development\\HealthAPI\\Logs\\log.txt", "rollingInterval": "Hour", "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {CorrelationId} {Level:u3}] [{Username}] {Message:lj}{NewLine}{Exception}" } } ] }
Program.cs 原代码
var _logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) .Enrich.FromLogContext() .CreateLogger(); builder.Logging.AddSerilog(_logger); app.UseMiddleware<LogUserNameMiddleware>(); app.UseSerilogRequestLogging();
LogUserNameMiddleware 中间件代码
public class LogUserNameMiddleware { private readonly RequestDelegate next; public LogUserNameMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { using (LogContext.PushProperty("UserName", context.User.Identity.Name ?? "anonymous")) { await next(context); } } }
更新后的尝试(存在问题)
尝试使用Serilog.Sinks.Map重构配置,但未达到预期效果:
修改后的Program.cs
var _logger = new LoggerConfiguration() .WriteTo.Map("LoginController", "Other", (name, wt) => wt.File(@"E:\Logs\log-{name}.txt")) .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) .Enrich.FromLogContext() .CreateLogger();
控制器代码
private readonly Serilog.ILogger _logger = Log.Logger.ForContext("LoginController","Username"); _logger.Warning("Helllo !! {Name}",user.UserName);
解决方案
核心是利用Serilog.Sinks.Map根据LogContext中传递的UserName属性动态生成日志文件,步骤如下:
- 确保已安装
Serilog.Sinks.MapNuGet包 - 调整Program.cs中的Serilog配置,移除appsettings.json中原有File sink配置,改用代码配置Map:
var _logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .WriteTo.Map( keyPropertyName: "UserName", // 对应中间件推入LogContext的属性名 defaultKey: "anonymous", // 匿名用户默认值 (userName, writeTo) => writeTo.File( path: @"E:\WebSite\Development\HealthAPI\Logs\Log_{userName}_{Date:yyyy-MM-dd}.txt", rollingInterval: RollingInterval.Day, // 按天滚动,可改为RollingInterval.Hour按小时滚动 outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {CorrelationId} {Level:u3}] [{UserName}] {Message:lj}{NewLine}{Exception}" ) ) .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) .Enrich.FromLogContext() .CreateLogger(); builder.Logging.AddSerilog(_logger); // 注意中间件位置:需放在认证中间件之后,确保能获取到用户名 app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware<LogUserNameMiddleware>(); app.UseSerilogRequestLogging();
- 保持原中间件不变,无需在控制器中手动创建带固定属性的Logger,直接注入
ILogger<T>即可,中间件会自动将当前请求的UserName推入LogContext。
关键注意点
- 中间件必须放在
app.UseAuthentication()和app.UseAuthorization()之后,否则context.User.Identity.Name无法获取到已认证的用户名 - 若需要按小时生成日志文件,将
rollingInterval改为RollingInterval.Hour,路径中的{Date}会自动生成为小时级格式 - 移除appsettings.json中原有File sink配置,避免日志重复输出
内容的提问来源于stack exchange,提问作者Dnyati
相关产品推荐
相关产品推荐

