提问者:小点点

将用户名添加到Serilog中


我在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核心之间有冲突,因此我不能使用这个插件。

知道吗?


共3个答案

匿名用户

您可以创建一个中间件来将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中,您需要:

  1. 确保将IHttpContextAccessor添加到IoC容器
  2. LogenRichmentFilter添加到IoC容器,作用域为请求
  3. 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...);
    }