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

.NET6中如何通过NLog传递UserId至数据库日志字段?

解决方案

要在.NET 6的ILogger环境下传递UserId到NLog并写入数据库LogUserId字段,有以下几种实用方式:

方法1:通过日志范围(BeginScope)全局传递

适合在整个请求生命周期内自动为所有日志附加UserId,无需在每个日志调用中重复传递:

步骤1:创建自定义中间件

public class UserIdLoggingMiddleware
{
    private readonly RequestDelegate _next;

    public UserIdLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 从当前请求上下文获取用户ID(实际项目中可从Claims、Token等获取)
        var userId = context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier) ?? "Anonymous";
        
        // 创建日志范围,后续所有日志都会自动包含UserId属性
        using (context.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger("UserIdScope").BeginScope(new Dictionary<string, object> { ["UserId"] = userId }))
        {
            await _next(context);
        }
    }
}

步骤2:注册中间件

在Program.cs中添加中间件(注意放在认证中间件之后):

var app = builder.Build();

// ... 其他中间件(如UseAuthentication、UseAuthorization)
app.UseMiddleware<UserIdLoggingMiddleware>();

// ... 其他配置
app.Run();

步骤3:正常记录日志

你的服务代码无需额外修改,NLog会自动读取范围中的UserId:

public void SomeMethod()
{
   string userID = "ABC123";
   _logger.LogInformation("UserId {UserId} has created a new report.", userID);
}

方法2:单个日志调用时直接传递属性

如果仅需在特定日志中附加UserId,可以使用结构化日志或带属性的重载方法:

结构化日志方式(推荐)

利用结构化日志的占位符,NLog会自动将占位符名称作为属性键:

public void SomeMethod()
{
   string userID = "ABC123";
   // 占位符{UserId}会自动映射到event-properties中的UserId
   _logger.LogInformation("UserId {UserId} has created a new report.", userID);
}

显式传递属性字典

使用LogInformation的重载方法,直接传入属性字典:

public void SomeMethod()
{
   string userID = "ABC123";
   var properties = new Dictionary<string, object> { ["UserId"] = userID };
   _logger.LogInformation(new EventId(), properties, "UserId {0} has created a new report.", userID);
}

方法3:转换为NLog原生Logger(不推荐)

若想保持.NET 4.8中WithProperty的写法,可以将ILogger转换为NLog原生Logger,但会破坏ILogger的抽象性:

using NLog;
using NLog.Extensions.Logging;

public class AuthorizationManagerService: IAuthorizationManagerService
{
    private readonly NLog.Logger _nlogLogger;

    public AuthorizationManagerService(ILogger<AuthorizationManagerService> logger)
    {
        _nlogLogger = logger.GetCurrentClassLogger();
    }

    public void SomeMethod()
    {
       string userID = "ABC123";
       _nlogLogger.WithProperty("UserId", userID).Info("UserId {0} has created a new report.", userID);
    }
}

配置验证

你的appsettings.json中@LogUserID的layout配置${event-properties:UserId}是正确的,只要传递的属性名称为UserId,就能自动写入数据库的LogUserId字段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 20:50:54