zoukankan      html  css  js  c++  java
  • 如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性

    这是在ASP.NET Core 3.X中使用Serilog.AspNetCore系列文章的第三篇文章:。

    1. 第1部分-使用Serilog RequestLogging减少日志详细程度
    2. 第2部分-使用Serilog记录所选的终结点属性
    3. 第3部分-使用Serilog.AspNetCore记录MVC属性(本文)
    4. 第4部分-从Serilog请求日志记录中排除健康检查端点

    作者:依乐祝

    译文地址:https://www.cnblogs.com/yilezhu/p/12243984.html

    原文地址:https://andrewlock.net/using-serilog-aspnetcore-in-asp-net-core-3-logging-mvc-propertis-with-serilog/

    在我上篇文章中,我描述了如何配置Serilog的RequestLogging中间件以向Serilog的请求日志摘要中添加其他属性(例如请求主机名或选定的端点名称)。这些属性都在HttpContext中可用,因此可以由中间件本身直接添加。

    其他属性,例如MVC特定的功能,像操作方法ID,RazorPages处理程序名称或ModelValidationState,在MVC上下文中可用,因此Serilog的中间件不能直接访问。

    在本文中,我将展示如何创建action/page过滤器来为您记录这些属性,以便中间件可以在后续创建日志时访问。

    Serilog的创建者Nicholas Blumhardt之前已经解决了这个话题。解决方案非常相似,尽管他在他的示例中创建了一个特性,您可以使用该特性来装饰actions/controllers。我在本文中跳过了这种方法,并要求将其全局应用,我希望这将是常见的解决方案。

    记录来自MVC的其他信息

    就目前而言,ASP.NET Core中的一个特征是许多行为被MVC“基础结构”锁定在了MVC框架内部来实现。端点路由是采用MVC功能并将其下移到核心框架中的首要工作之一。ASP.NET Core团队一直在努力将更多MVC特定功能(例如模型绑定或操作结果)从MVC中移除,然后“下推”到核心框架中。有关此内容的更多信息,请参见Ryan Nowak在NDC上对Houdini项目的讨论

    但是,就目前情况而言,MVC内仍然存在一些不容易从应用程序其他部分访问的特性。当我们考虑到我们的Serilog的请求记录中间件的时候,这意味着有些属性我们也是不容易记录的。例如:

    • HandlerName(OnGet
    • ActionId(1fbc88fa-42db-424f-b32b-c2d0994463f1
    • ActionName (MyController.SomeApiMethod (MyTestApp)
    • RouteData({action = "SomeApiMethod", controller = "My", page = ""}
    • ValidationState(True/ False

    上一篇文章中我展示了如何使用RequestLogging中间件的扩展方法通过使用IDiagnosticContext 将附加属性写入Serilog的请求日志中。这也仅适用于在HttpContext可用的值。在这篇文章中,我将展示如何在过滤器中使用IDiagnosticContext,以及将MVC特定值添加到日志中。我还将展示如何在page过滤器中添加RazorPages特定的值(如HandlerName)。

    使用自定义过滤器记录MVC属性

    过滤器相当于为每个请求运行的类似于MVC的微型中间件管道。.NET Core MVC中有多种类型的过滤器,每种类型的过滤器在MVC过滤器管道中的有着不同的用途(有关更多详细信息,请参见此文章)。在本文中,我们将使用最常见的过滤器之一,即Action过滤器。

    Action过滤器在执行MVC操作方法之前和之后运行。他们可以访问许多MVC属性的值,例如正在执行的Action及其将被调用的参数。

    下面的Action过滤器直接实现IActionFilter。该OnActionExecuting方法在调用action方法之前被调用,并将额外的MVC特定属性添加到通过构造函数传入的IDiagnosticContext中。

    public class SerilogLoggingActionFilter : IActionFilter
        {
            private readonly IDiagnosticContext _diagnosticContext;
    
            public SerilogLoggingActionFilter(IDiagnosticContext diagnosticContext)
            {
                _diagnosticContext = diagnosticContext ?? throw new ArgumentNullException(nameof(diagnosticContext));
            }
    
            public void OnActionExecuting(ActionExecutingContext context)
            {
                _diagnosticContext.Set("RouteData", context.ActionDescriptor.RouteValues);
                _diagnosticContext.Set("ActionName", context.ActionDescriptor.DisplayName);
                _diagnosticContext.Set("ActionId", context.ActionDescriptor.Id);
                _diagnosticContext.Set("ValidationState", context.ModelState.IsValid);
            }
    		// Required by the interface
            public void OnActionExecuted(ActionExecutedContext context)
            {
    
            }
        }
    

    在将MVC服务添加到应用程序中时,可以在以下位置全局注册过滤器Startup.ConfigureServices()

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers(opts =>
        {
            opts.Filters.Add<SerilogLoggingPageFilter>();
        });
        // ... other service registration
    }
    

    无论你使用AddControllersAddControllersWithViewsAddMvc,或AddMvcCore的方式你都可以采用同样的方式来添加全局过滤器。

    有了这个配置之后,如果你调用一个MVC控制器,你在Serilog的请求日志消息中会看到额外的数据(ActionNameActionId,和RouteDataValidationState)记录:

    在Serilog请求日志中记录的其他MVC属性的图像

    您可以在此处将所需的任何其他数据添加到日志中。只需注意记录参数值-切记不要记录敏感或个人身份信息!

    Nicholas Blumhardt在他的帖子中建议的Action过滤器是从ActionFilterAttribute派生的,因此可以将其直接用作控制器和Action的特性。不幸的是,这意味着您必须使用服务定位来从每个请求的HttpContext中检索单例的IDiagnosticContext。我的方法可以改用构造函数注入,但是不建议将其用作属性,因此必须如上所述全局使用。而且,MVC将在我的实现中使用作用域生存期,而不是单例,因此它会在每个请求中创建一个新实例。

    如果要记录其他集中MVC过滤器中的值,则可以以相同的方式实现其他过滤器,例如资源过滤器,结果过滤器或授权过滤器。

    使用自定义page过滤器记录RazorPages属性

    上面实现的IActionFilter过滤器在MVC和API控制器上能够正常运行,但它不会对RazorPages起作用。如果要为选择的给定Razor页面记录HandlerName,则需要创建一个自定义的IPageFilter

    页面过滤器直接类似于Action过滤器,但它们仅适用于Razor页面。以下示例从PageHandlerSelectedContext中检索处理程序名称并将其记录为属性RazorPageHandler。在这种情况下,还需要一些样板代码,但过滤器的功能还是非常基础的-调用IDiagnosticContext.Set()以记录属性。

     public class SerilogLoggingPageFilter : IPageFilter
        {
            private readonly IDiagnosticContext _diagnosticContext;
    
            public SerilogLoggingPageFilter(IDiagnosticContext diagnosticContext)
            {
                _diagnosticContext = diagnosticContext ?? throw new ArgumentNullException(nameof(diagnosticContext));
            }
            //Required by the interface
            public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
            {
            }
            public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
            {
            }
            public void OnPageHandlerSelected(PageHandlerSelectedContext context)
            {
                var name = context.HandlerMethod?.Name ?? context.HandlerMethod?.MethodInfo.Name;
                if (name != null)
                {
                    _diagnosticContext.Set("RazorPageHandler", name);
                }
            }
        }
    

    请注意,我们之前编写的IActionFilter代码不会在Razor Pages上运行,因此,如果您也想记录RazorPages RouteDataValidationStateRazorPages的其他详细信息,则也需要在此处添加它。该context属性包含您可能需要的大多数属性,例如ModelStateActionDescriptor

    接下来,您需要在Startup.ConfigureServices()方法中注册页面过滤器:

     public void ConfigureServices(IServiceCollection services)
            {
                //services.AddMvcCore(
                //    opts => opts.Filters.Add<SerilogLoggingPageFilter>()
                //    );
                services.AddRazorPages().AddMvcOptions(
                    opts => opts.Filters.Add<SerilogLoggingPageFilter>()
                    ) ;
            }
    

    添加过滤器后,对“Razor页面”的请求现在可以看到添加的附加属性,IDiagnosticContext这些属性将添加到Serilog请求日志中。请参见下图中的RazorPageHandler属性:

    在Serilog请求日志中记录了额外的Razor Page属性的图像

    总结

    默认情况下,当用Serilog的请求日志记录中间件替换ASP.NET Core基础结构中的日志记录时,您会丢失一些信息(与开发环境的默认配置相比)。在本文中,我将展示如何自定义Serilog,RequestLoggingOptions以重新添加特定于MVC的其他属性。

    要将与MVC相关的属性添加到Serilog请求日志中,请创建一个IActionFilter并使用IDiagnosticContext.Set()来添加属性。要将与Razor页面相关的属性添加到Serilog请求日志中,请在IPageFilter中使用IDiagnosticContext的相同方法创建和添加属性。

    下一节让我们一起探讨下如何从Serilog请求记录中排除运行状况检查端点。

  • 相关阅读:
    jmeter在返回的json串中提取需要的值
    selenium 浏览器驱动下载地址
    Postman设置环境变量
    Selenium中自动输入10位随机数字的方法
    Selenium-java 中 对于下拉框 对于网页上的下拉框 如何定位
    Selenium中如何运行 auto.exe 文件
    Selenium 中 高亮元素
    linux mysql安装
    数据库中的一对多、多对多的关系讲解
    Django Models 介绍
  • 原文地址:https://www.cnblogs.com/yilezhu/p/12243984.html
Copyright © 2011-2022 走看看