问题
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 theLogContext.PushProperty
call is happening before your call to something likePasswordSignInAsync
(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