.NET Core Serilog username is always null

[亡魂溺海] 提交于 2019-12-24 10:48:53

问题


I have added this middleware to add usernames to my logging, however, it always appears as null.

This is the middleware

private readonly RequestDelegate next;

    public LogUserName(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        LogContext.PushProperty("UserName", context.User.Identity.Name);
        await next(context);
        //return next(context);
    }

I call it in Program.cs and Startup.cs like this

Program.cs

Log.Logger = new LoggerConfiguration()
 .ReadFrom.Configuration(Configuration)
 .Enrich.FromLogContext()
 .Filter.ByExcluding(Matching.FromSource("Microsoft"))
 .Filter.ByExcluding(Matching.FromSource("System"))
 .CreateLogger();

Startup.cs

  app.UseAuthentication();
  app.UseMiddleware<LogUserName>();

I noticed that when I hardcoded a property, it would appear in my log under the properties tag. E.g

LogContext.PushProperty("UserName", "Test");

<properties><property key='SourceContext'>AAAA.Areas.Identity.Pages.Account.LoginModel</property><property key='ActionId'>e477aa96-f0b5-4790-9253-80fcbc72fbda</property><property key='ActionName'>/Account/Login</property><property key='RequestId'>0HLJ6EBJ4V6PP:00000002</property><property key='RequestPath'>/Identity/Account/Login</property><property key='CorrelationId'></property><property key='ConnectionId'>0HLJ6EBJ4V6PP</property><property key='UserName'>Test</property></properties>

Also, I would like to bring it out of the properties tag and into its own field if possible.


回答1:


I noticed that when I hardcoded a property, it would appear in my log under the properties tag. E.g. LogContext.PushProperty("UserName", "Test")

<properties>
    <property key='UserName'>Test</property>
</properties>

Also, I would like to bring it out of the properties tag and into its own field if possible.

The MSSqlServer sink for Serilog by default puts additional properties into the Properties column in its XML format. However, there is a way to configure custom property columns to move certain properties into its own properties. You can configure that using code but since you are using the JSON-based configuration in appsettings.json, you can also do it there.

The configuration should look something like this (shortened the configuration here to show only the relevant parts):

"Serilog": {
  "WriteTo": [
    {
      "Name": "MSSqlServer",
      "Args": {
        "connectionString": "…",
        "schemaName": "AnalyticsStudio",
        "tableName": "EventLogs",
        "columnOptionsSection": {
          "additionalColumns": [
            { "ColumnName": "UserName" }
          ]
        }
      }
    }
  ]
}

The column is configured as a varchar by default, so it should work for your string value.


For properly filling the custom property see the following questions:

  • Serilog Additional Properties (for using Serilog for this in general)
  • Add user to the log context when using Serilog and Asp.Net Core (using ASP.NET Core 1.x but should still give the general idea)

Kirk Larkin suggested the following on chat:

From your explanation so far, I'm wondering if you're expecting to see UserName in the message that is being logged as part of the same request that actually signs you in. If you are expecting this, it won't be the case because the LogContext.PushProperty call is happening before your call to something like PasswordSignInAsync (assuming you're using Identity).

If this is truly your situation, then you should know that your middleware that sets the custom property is running before any of your controller logic runs. So the custom property is set before the sign-in completed and as such, at the time the middleware ran, an empty username was added as a custom property. So the behavior is perfectly correct. It’s only for subsequent requests that the authentication middleware will be able to authenticate the user before your middleware runs so that you should see the correct username in your logging output.

There is not really a good way around this. Of course you could explicitly set the custom property again as you sign the user in. But I would recommend you against that as technically the request was still invoked without any authentication, so it shouldn’t be a problem not to have a username there.



来源:https://stackoverflow.com/questions/53867490/net-core-serilog-username-is-always-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!