我在program.cs中有此Serilog配置
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.Build();
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.WriteTo.MSSqlServer(Configuration.GetConnectionString("DefaultConnection"), "dbo.Log")
.Enrich.WithThreadId()
.Enrich.WithProperty("Version", "1.0.0")
.CreateLogger();
try
{
BuildWebHost(args).Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog()
.Build();
}
现在我想将httpContext.current.user.identity.name
添加到所有日志消息中。
我尝试在以下文档中创建新的Enrich类:https://github.com/serilog/serilog/wiki/configuration-basics#enrichers
class UsernameEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, HttpContext httpContext)
{
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(
"Username", httpContext.User.Identity.Name));
}
}
但与不知道HttpContext的ILogEventEnricher有冲突。
我还尝试安装了包含用户名丰富器的Nuget包serilog.web.classic,但是在目标框架。NET框架和。NET核心之间有冲突,因此我不能使用这个插件。
知道吗?
您可以创建一个中间件来将required属性放入LogContext。
public class LogUserNameMiddleware
{
private readonly RequestDelegate next;
public LogUserNameMiddleware(RequestDelegate next)
{
this.next = next;
}
public Task Invoke(HttpContext context)
{
LogContext.PushProperty("UserName", context.User.Identity.Name);
return next(context);
}
}
此外,您还需要将以下内容添加到记录器配置中:
.Enrich.FromLogContext()
在启动中,添加中间件LogUsernameMiddleware
,还要注意中间件应该添加在UserAuthentication
之后,以便初始化Context.User.Identity
例如。
app.UseAuthentication();
app.UseMiddleware<LogUserNameMiddleware>();
使用中间件的另一种选择是使用动作过滤器。
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Serilog.Context;
namespace Acme.Widgets.Infrastructure
{
public class LogEnrichmentFilter : IActionFilter
{
private readonly IHttpContextAccessor httpContextAccessor;
public LogEnrichmentFilter(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public void OnActionExecuting(ActionExecutingContext context)
{
var httpUser = this.httpContextAccessor.HttpContext.User;
if (httpUser.Identity.IsAuthenticated)
{
var appUser = new AppIdentity(httpUser);
LogContext.PushProperty("Username", appUser.Username);
}
else
{
LogContext.PushProperty("Username", "-");
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Do nothing
}
}
}
在startup.configureReservices
中,您需要:
IHttpContextAccessor
添加到IoC容器LogenRichmentFilter
添加到IoC容器,作用域为请求LogenRichmentFilter
注册为全局操作筛选器启动cs
:
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<LogEnrichmentFilter>();
services.AddMvc(o =>
{
o.Filters.Add<LogEnrichmentFilter>();
});
然后,您应该在MVC操作调用管道中运行的代码的日志上下文中具有当前用户名。我想如果您使用资源筛选器而不是操作筛选器,用户名将附加到更多的日志条目,因为它们在管道中运行得稍早(我才刚刚了解这些!)
如果您使用的是Serilog.aspNetCore,那么添加身份验证/用户属性非常容易。
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = PushSeriLogProperties;
});
public void PushSeriLogProperties(IDiagnosticContext diagnosticContext, HttpContext httpContext)
{
diagnosticContext.Set("SomePropertyName", httpContext.User...);
}