如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性
这是Serilog系列的第三篇文章。
第1部分-如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出
第2部分-Serilog高级玩法之用Serilog记录所选终结点附加属性
第3部分-使用Serilog.AspNetCore记录MVC属性(本文)
第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 interfacepublic 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 interfacepublic 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
或ValidationState
RazorPages的其他详细信息,则也需要在此处添加它。该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属性相关推荐
- ASP.NET 2.0 – 善用DataSourceMode属性 (转自章立民CnBlogs)
ASP.NET 2.0 – 善用DataSourceMode属性 SqlDataSource控件的DataSourceMode属性决定所提取的数据要如何维护. DataSourceMode属性的默认值 ...
- asp.net core3.0 mvc 用 autofac
好久没有写文章了,最近在用.net core3.0,一些开发中问题顺便记录: 1.首先nuget引入 Autofac Autofac.Extensions.DependencyInjection 2. ...
- ASP.NET 2.0 – 善用DataSourceMode属性
SqlDataSource控件的DataSourceMode属性决定所提取的数据要如何维护.<?xml:namespace prefix = o /> DataSourceMode属性的默 ...
- asp.net 2.0中一次性更新所有GRIDVIEW的记录
在asp.net 2.0中,gridview控件是十分不错的控件.有的时候,可能一个GRIDVIEW控件中 的各行都是文本框,如何一次性更新所有修改过的记录呢?有两种方法,一种是使用sqldataso ...
- asp.net 2.0中用GRIDVIEW插入新记录
出处:www.knowsky.com 作者:www.knowsky.com <script language=JavaScript src="/ad/ad.js">&l ...
- Enterprise Library 2.0 技巧(3):记录ASP.NET站点中未处理的异常
这篇文章不能算是Enterprise Library 2.0的一个技巧,只是Logging Application Block的一个简单应用而已,在这里我们使用Logging Application ...
- 艾伟:【翻译】使用ASP.NET 2.0记录错误
原文:http://www.dotnetcurry.com/ShowArticle.aspx?ID=94&AspxAutoDetectCookieSupport=1 使用ASP.NET 2.0 ...
- EF Core3.0+ 通过拦截器实现读写分离与SQL日志记录
前言 本文主要是讲解EF Core3.0+ 通过拦截器实现读写分离与SQL日志记录 注意拦截器只有EF Core3.0+ 支持,2.1请考虑上下文工厂的形式实现. 说点题外话.. 一晃又大半年没更新技 ...
- Log4Net异常日志记录在asp.net mvc3.0的应用
前言 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是简单的介绍如何在Visual ...
最新文章
- 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers
- python文档生成工具 sphinx 简介
- Html:upload
- 深度解析企业级存储解决方案
- 独家对话阿里云函数计算负责人不瞋:你所不知道的 Serverless
- linux各种查看端口号
- 【laravel5.4 + TP5.0】hasOne和belongsTo的区别
- linux识别新加存储盘,Linux下新加磁盘
- Android下文件的压缩和解压(Zip格式)
- maven 关于使用 snapshot 的坑
- java 消费者 生产者 队列_用Java写一个生产者-消费者队列
- Linux 用inotify监听文件和目录
- POJ P1185 炮兵阵地 【状压dp】
- Flutter之Stack
- VS F5自动编译 F5不自动编译
- GPS同步时钟(NTP时钟服务器)常见故障解决与价格差异分析
- excel打不开_2016EXCEL表格打不开,提示格式与文件扩展名指定的格式不一致,这么做!...
- 显微镜C接口_壁虎支架、AI相机、手机镜头、便携显微镜,十一旅行有它们更精彩...
- windows应用程序与控制台应用程序的区别
- rpm包管理器常见用法
热门文章
- Windows按名称排序问题
- 60佳优秀的 Photoshop 网页制作教程【下篇】
- word 替换 增加引号_如何在Word 2013文档中替换部分(不是全部)智能引号
- 简单的单臂路由的配置实验 (思科)
- vue vue-router vuex element-ui axios 写一个代理平台的学习笔记(十一)构思商品页面...
- SSIS 执行变量中的脚步输出列顺序与SQL查询列顺序不同
- CMD、AMD、commonJs 规范的写法
- Word打不开,如何修复word文档?
- 如何扩展开发团队(转)
- 深入理解Magento-第十章-数据操作数据收集器