web-dev-qa-db-ja.com

ユーザー名を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));
        }
    }

しかし、IContextEventEnricherとの競合があり、HttpContextを認識していません。

ユーザー名エンリッチャーを含むNugetパッケージSerilog.Web.Classicもインストールしようとしましたが、ターゲットフレームワークの.Net Frameworkと.Net Coreの間に競合がありますこのプラグインは使用できません。

何か案が ?

9
Muflix

ミドルウェアを作成して、必要なプロパティを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()
12
Alex Riabov

ミドルウェアを使用する代わりに、アクションフィルターを使用することができます。

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.ConfigureServices次のことを行う必要があります。

  1. IHttpContextAccessorがIoCコンテナーに追加されていることを確認します
  2. LogEnrichmentFilterをIoCコンテナに追加し、リクエストをスコープとします
  3. LogEnrichmentFilterをグローバルアクションフィルターとして登録する

Startup.cs

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<LogEnrichmentFilter>();

services.AddMvc(o =>
{
    o.Filters.Add<LogEnrichmentFilter>();
});

次に、 MVCアクション呼び出しパイプライン で実行されるコードのログコンテキストに現在のユーザー名を含める必要があります。アクションフィルターの代わりに resource filter を使用すると、パイプラインの少し前に実行されるため、ユーザー名がさらにいくつかのログエントリに添付されると思います(これらについて知っているだけです) !)

3
Cocowalla