You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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属性动态生成日志文件,步骤如下:

  1. 确保已安装Serilog.Sinks.Map NuGet包
  2. 调整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();
  1. 保持原中间件不变,无需在控制器中手动创建带固定属性的Logger,直接注入ILogger<T>即可,中间件会自动将当前请求的UserName推入LogContext。

关键注意点

  • 中间件必须放在app.UseAuthentication()和app.UseAuthorization()之后,否则context.User.Identity.Name无法获取到已认证的用户名
  • 若需要按小时生成日志文件,将rollingInterval改为RollingInterval.Hour,路径中的{Date}会自动生成为小时级格式
  • 移除appsettings.json中原有File sink配置,避免日志重复输出

内容的提问来源于stack exchange,提问作者Dnyati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 04:53:35