我目前正在将 NLog 与 Blazor Server 结合使用,并将生成的日志存储在数据库中。我想要存储的数据点之一是创建日志时用户所在的 URL。
在其他 asp.net core 项目中,我会使用 aspnet-request-url
布局渲染器,但在 Blazor 服务器上,这似乎总是返回 https://localhost/_blazor
。有没有办法获取当前的 Blazor URL 并将其包含在日志中?
最佳答案
目前,似乎无法使用 NLog 布局渲染器,例如 ${aspnet-request-url}
记录 Blazor 服务器应用程序的正确请求 url,但您仍然可以通过使用 ${event-properties}
自行将请求 URL 附加到记录器来使其工作。布局渲染器(参见下面的代码)。
原因是${aspnet-request-url}
布局渲染器搜索 HttpContext.Request
获取请求 URL ( NLog AspNetRequestUrlRenderer.cs ),这对于其他 ASP.NET Core 项目来说效果很好,但 Blazor 的处理方式有所不同。
对于 Blazor 服务器应用程序,客户端仅向应用程序发送一次 HTTP 请求(发送到 https://localhost/_blazor
),其中下载所有必需的文件(html/css/js/images),并且 Blazor 建立一个SignalR与客户端的连接。一次SignalR
连接建立后,它使用 HTTP 以外的传输方法(通常是 WebSockets)在客户端与服务器之间进行通信,之后不再发出 HTTP 请求。所有后续请求都是通过 SignalR 连接发出的,因此,您始终会得到 https://localhost/_blazor
在${aspnet-request-url}
布局渲染器。
根据文档,获取当前请求 URI 的定义方法是注入(inject) NavigationManager
在您的 Blazor 组件中。您可以获取Uri
属性(property)来自 NavigationManager
它为您提供字符串格式的绝对 URI。 NLog 记录器可以通过上下文信息和自定义属性(使用 WithProperty
或 WithProperties
方法)来丰富,然后可以使用 Event Properties 进行记录。布局渲染器。所以你能做的就是附上 NavigationManager.Uri
到您的记录器,然后通过在 NLog.config 的布局中定义它来访问该属性。
解决方案 #01 示例:
/* Counter.razor */
@page "/counter"
@inject NavigationManager navigationManager
/* Define Logger */
NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
/* Attaching a property to a logger returns a new enriched logger */
var loggerWithProps = _logger.WithProperty("navigation-manager-uri", navigationManager.Uri);
/* Use this logger which has request url attached in key 'navigation-manager-uri' */
loggerWithProps.Info("Sample message which contains NavManager.Uri property");
现在在您的NLog.config
中文件中,您可以使用布局渲染器 ${event-properties:item=navigation-manager-uri}
访问请求 uri 。您的配置文件将如下所示:
<!-- NLog.config -->
<targets>
<target xsi:type="Console" layout="${event-properties:item=navigation-manager-uri} ${message}">
<!-- Or skip logging this property if it is empty (uses ${when} condition) -->
<!-- <target xsi:type="Console" layout="${when:when='${event-properties:item=navigation-manager-uri}'!='':Inner=${event-properties:item=navigation-manager-uri} }${message}"> -->
</target>
</targets>
给出输出日志:
https://localhost:7123/counter Sample message which contains NavManager.Uri property
[推荐]解决方案#02示例(感谢@Rolf Kristensen)
不要通过附加一个属性来丰富记录器(这会创建 2 个记录器,一个包含您的属性,一个不包含您的属性)并使用 ${event-properties}
布局渲染器,您可以简单添加NavigationManager.Uri
进入HttpContext.Items
在OnInitialized
生命周期 Hook 。由于 NLog 有 HttpContext Item Layout Renderer可以访问HttpContext.Items
,您可以在NLog.config
中访问它通过使用${aspnet-item:variable=YOUR_VARIABLE_NAME}
/* Counter.razor */
@page "/counter"
/* @* Inject NavigationManager to get current URI *@ */
@inject NavigationManager navigationManager
/* @* Inject IHttpContextAccessor to get access to current HttpContext *@ */
@inject IHttpContextAccessor httpContextAccessor
@code {
/* Define a simple logger */
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
protected override void OnInitialized()
{
/* Add NavigationManager.Uri into HttpContext Items */
/* This will then be accessible in NLog.config like ${aspnet-item:variable=navigation-manager-uri} */
httpContextAccessor?.HttpContext?.Items.Add("navigation-manager-uri", navigationManager.Uri);
/* Or make it fail safe so that it doesn't give 'key' already present error when switching to multiple pages */
// if (httpContextAccessor is not null && httpContextAccessor.HttpContext is not null && httpContextAccessor.HttpContext.Items.ContainsKey("navigation-manager-uri"))
// httpContextAccessor?.HttpContext?.Items.Remove("navigation-manager-uri");
// httpContextAccessor?.HttpContext?.Items.Add("navigation-manager-uri", navigationManager.Uri);
/* Now logging anything will have correct URL displayed in logs */
/* Use this logger everywhere in this component */
logger.Info("This will have correct URL attached from NavigationManager.Uri");
}
}
现在在您的NLog.config
中文件中,您可以访问您推送到HttpContext.Items
的请求URI使用布局渲染器 ${aspnet-item:variable=navigation-manager-uri}
。您的配置文件将如下所示:
<!-- NLog.config -->
<targets>
<target xsi:type="Console" layout="${aspnet-item:variable=navigation-manager-uri} ${message}">
<!-- Or skip logging this property if it is empty (uses ${when} condition) -->
<!-- <target xsi:type="Console" layout="${when:when='${aspnet-item:variable=navigation-manager-uri}'!='':Inner=${aspnet-item:variable=navigation-manager-uri} }${message}"> -->
</target>
</targets>
给出输出日志:
https://localhost:7123/counter This will have correct URL attached from NavigationManager.Uri
这个解决方案更简单,因为您只需添加 3 行代码即可使其工作,NLog 会处理其余的事情。
- 注入(inject)NavigationManager
- 注入(inject) IHttpContextAccessor
- 添加
NavigationManager.Uri
进入HttpContext.Items
目前,这些是使用 NLog 记录 Blazor 应用程序的请求 URL 的唯一方法。请参阅NLog Issue - Provide support for logging Blazor request information了解更多信息。
关于c# - 使用 Nlog 在 Blazor 服务器中记录 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72063711/