.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
相关产品推荐
相关产品推荐

