如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性
这是在ASP.NET Core 3.X中使用Serilog.AspNetCore系列文章的第三篇文章:。
- 第1部分-使用Serilog RequestLogging减少日志详细程度
 - 第2部分-使用Serilog记录所选的终结点属性
 - 第3部分-使用Serilog.AspNetCore记录MVC属性(本文)
 - 第4部分-从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
}
无论你使用
AddControllers,AddControllersWithViews,AddMvc,或AddMvcCore的方式你都可以采用同样的方式来添加全局过滤器。
有了这个配置之后,如果你调用一个MVC控制器,你在Serilog的请求日志消息中会看到额外的数据(ActionName,ActionId,和RouteData,ValidationState)记录:

您可以在此处将所需的任何其他数据添加到日志中。只需注意记录参数值-切记不要记录敏感或个人身份信息!
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 RouteData或ValidationStateRazorPages的其他详细信息,则也需要在此处添加它。该context属性包含您可能需要的大多数属性,例如ModelState和ActionDescriptor。
接下来,您需要在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的请求日志记录中间件替换ASP.NET Core基础结构中的日志记录时,您会丢失一些信息(与开发环境的默认配置相比)。在本文中,我将展示如何自定义Serilog,RequestLoggingOptions以重新添加特定于MVC的其他属性。
要将与MVC相关的属性添加到Serilog请求日志中,请创建一个IActionFilter并使用IDiagnosticContext.Set()来添加属性。要将与Razor页面相关的属性添加到Serilog请求日志中,请在IPageFilter中使用IDiagnosticContext的相同方法创建和添加属性。
下一节让我们一起探讨下如何从Serilog请求记录中排除运行状况检查端点。
如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性的更多相关文章
- 问题:ClientIDMode属性;结果:ASP.NET 4.0的ClientIDMode属性
		
ASP.NET 4.0的ClientIDMode属性 时光流逝,我们心爱的ASP.NET也步入了4.0的时代,微软在ASP.NET 4.0中对很多特性做了修改.比如我将要讨论的控件ID机制就是其中之一 ...
 - 2019年第一天——使用Visual Studio 2019 Preview创建第一个ASP.Net Core3.0的App
		
一.前言: 全文翻译自:https://www.talkingdotnet.com/creating-first-asp-net-core-3-0-app-visual-studio-2019/ Vi ...
 - asp.net core3.0 mvc 用 autofac
		
好久没有写文章了,最近在用.net core3.0,一些开发中问题顺便记录: 1.首先nuget引入 Autofac Autofac.Extensions.DependencyInjection 2. ...
 - ASP.NET 4.0的ClientIDMode属性
		
时光流逝,我们心爱的ASP.NET也步入了4.0的时代,微软在ASP.NET 4.0中对很多特性做了修改.比如我将要讨论的控件ID机制就是其中之一. 在ASP.NET 4.0之前我们总是要为控件的Cl ...
 - ASP.NET Core3.0 中的运行时编译
		
运行时编译 通过 Razor 文件的运行时编译补充生成时编译. 当 .cshtml 文件的内容发生更改时,ASP.NET Core MVC 将重新编译 Razor 文件 . 通过 Razor 文件的运 ...
 - Postman 调试请求Asp.Net Core3.0 WebApi几种常见的Get/Post/Put/Delete请求
		
这里就直接截图了,如下(很简单的操作): 1:Get几种请求 2:Post 3:Put 4:Delete 最后,虽然简单,代码还是给放一下(这里只是抛砖引玉的作用,自己可以根据自身的业务需要来做进一 ...
 - Asp.net Core3.0 跨域配置
		
原文:http://www.zilaohu.cn/Jie/Detail_Jie?ID=78840a04-55b8-4988-80b2-f964fd822d63 下面配置后:被拒绝的域请求后,可以进入方 ...
 - 探索Asp net core3中的 项目文件、Program.cs和通用host(译)
		
引言 原文地址 在这篇博客中我将探索一些关于Asp.net core 3.0应用的基础功能--.csproj 项目文件和Program源文件.我将会描述他们从asp.net core 2.X在默认模版 ...
 - ASP.NETCore 3.0 Autofac替换及控制器属性注入及全局容器使用
		
1.Autofac基础使用 参考: https://www.cnblogs.com/li150dan/p/10071079.html 2.ASP.NETCore 3.0 Autofac 容器替换 需要 ...
 
随机推荐
- Docker应用容器引擎
			
1.Docker概述 1.1.Docker简介 Docker 是一个开源的应用容器引擎,基于 Go 语言开发.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到 ...
 - 使用FluentEmail发送outlook邮件
			
一,邮箱账号相关设置 1,创建outLook邮箱. 2,进入邮箱设置->同步电子邮件->允许设备和应用使用pop 3,设置microsoft账号的应用程序密码->进入安全性页面-&g ...
 - onCreate不加载布局
			
如果Activity重写的是 onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentS ...
 - 9. SOFAJRaft源码分析— Follower如何通过Snapshot快速追上Leader日志?
			
前言 引入快照机制主要是为了解决两个问题: JRaft新节点加入后,如何快速追上最新的数据 Raft 节点出现故障重新启动后如何高效恢复到最新的数据 Snapshot 源码分析 生成 Raft 节点的 ...
 - Java核心技术·卷 II(原书第10版)分享下载
			
Java核心技术·卷 II 内容介绍 Java领域最有影响力和价值的著作之一,由拥有20多年教学与研究经验的资深Java技术专家撰写(获Jolt大奖),与<Java编程思想>齐名,10余年 ...
 - Web_telnet 通过JAVA实现网页上面的命令行远程工具 以及对于流的理解
			
前言 这几天研究了一下如何在web页面上通过telnet 连接一个远程的机器,通过命令行进行控制,让然,B/S架构的项目,如果直接通过 浏览器是无法和远程机器进行通信的,我们就得借助后端来帮助实现这样 ...
 - webapp开发之IIS进程调试
			
1.背景 1.当我的手机连接电脑的时候想要调试居然连接不上,之后我将项目发布之后才可以请求(同一局域网下) 2.你们不觉得发布到IIS再附加进程太烦了么?看了看网上全是这种方法,这不科学!VS已经提供 ...
 - 叶子的颜色---经典树上dp
			
挺简单的一个dp #include<iostream> #include<cstring> #include<cstdio> #include<algorit ...
 - 从0开发3D引擎(一):开篇
			
介绍 大家好,本系列带你踏上Web 3D编程之旅- 本系列是实战类型,从0开始带领读者写出"良好架构.良好扩展性.最小功能集合(MVP)" 的3D引擎. 本系列的素材来自我们的产品 ...
 - IntelliJ IDEA安装教程及使用方法
			
IntelliJ IDEA安装教程及使用方法 首先,需要去下载IDEA,直接在百度搜索IntelliJ IDEA,然后找到官网点击进入 进入官网,选择[Download],点击进入,选择自己的操作系统 ...