如何使用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
或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属性的更多相关文章
- 问题: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 容器替换 需要 ...
随机推荐
- jQuery---鼠标滚轮控制div横向滚动条左右移动
HTML <div class="table-responsive"> <div class="fhtable" style="wi ...
- rabbitmq template发送的消息中,Date类型字段比当前时间晚了8小时
前言 前一阵开发过程遇到的问题,用的rabbitmq template发送消息,消息body里的时间是比当前时间少了8小时的,这种一看就是时区问题了. 就说说为什么出现吧. 之前的配置是这样的: @B ...
- Winform C#关于utf8编码问题
public string SendDataByPost(string param, string Url) { try { HttpWebRequest request = (HttpWebRequ ...
- DEVOPS技术实践_02:jenkins自动构建项目
一.用户名密码错误 打开jenkins发现用户名密码错误,解决 1.1 找到config.xml文件 [root@jenkins-master ~]# ll -a drwxr-xr-x. root r ...
- 负载均衡基本原理与lvs
前言: 之前在山西的项目上使用的是lvs下的NAT模式,但另外两个模式并没有涉及,今天系统的整理下关于负载均衡的相关理论与lvs各模式的相关优点与不足,知其然与所以然,而后能针对性的应用: 基本介绍 ...
- C Primer Plus(二)
重读C Primer Plus ,查漏补缺 重读C Primer Plus,记录遗漏的.未掌握的.不清楚的知识点 分支和跳转 1.ctype.h头文件里包含了一些列用于字符判断的函数,包括判断数字.大 ...
- MacBook Pro 入手一年了,到底香不香?
最近又有小伙伴问到底值不值得入手一台 MacBook Pro,松哥自己在 2018 年 10 月份的时候入手了一台,到现在为止,也用了一年多了,今天就来和小伙伴们聊一聊使用感受,至于到底值不值,需要大 ...
- 力扣208——实现 Trie (前缀树)
这道题主要是构造前缀树节点的数据结构,帮助解答问题. 原题 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = ...
- 【已解决】CentOS7使用yum安装Docker显示错误:cannot find a valid baseurl for repo: base/7/x86_64
不得不说,Docker 要求 CentOS 系统的内核版本高于 3.10,这就让有些人开始头疼了,而要查看具体的版本可以用以下命令 uname -r 当然,CentOS 6.8版本也能安装Docker ...
- git:rebase的原理
git:rebase的原理 前提: 在最近的项目中,我碰到这样一个情况:第一版app上线之后,团队紧接着进行第二版本的开发,由于团队成员对git使用不熟悉,所以开发的每一次提交都是往远端master分 ...