c# - 使用 Nlog 在 Blazor 服务器中记录 URL

标签 c# asp.net-core blazor blazor-server-side nlog

我目前正在将 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 记录器可以通过上下文信息和自定义属性(使用 WithPropertyWithProperties 方法)来丰富,然后可以使用 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.ItemsOnInitialized生命周期 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 会处理其余的事情。

  1. 注入(inject)NavigationManager
  2. 注入(inject) IHttpContextAccessor
  3. 添加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/

相关文章:

c# - WinForms - 为什么每次我在 Visual Studio 中打开 C# 窗体时都会在其中运行 SQL?

c# - 如何从 C# 连接到 SQLite 数据库文件?

c# - 有效地将大量参数传递给 ASP.NET MVC Controller Action

c# - Postman 表单数据到 ASP.NET Core 2.2 Controller 未使用私有(private) setter 绑定(bind)到命令

json - 为什么 FetchData 中的天气样本似乎已缓存到示例 Blazor 应用程序中?

asp.net - ASP .net 6 通过 httpclient 下载文件 - 流问题

file-upload - Blazor - 无法将文件保存在文件夹 wwwroot/img 中

c# - Entity Framework 4 : Table per Type inheritance problem on insert

javascript - JQuery UI 自动完成功能在 MVC View 中不起作用

c# - 如何从 ASP.NET Core 3.1 中的 appsettings.json 读取整个部分?