如何使用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 容器替换 需要 ...
随机推荐
- java.lang.NoSuchMethodException: com.hgkj.controler.action.UserAction.newsLoginAction()
java.lang.NoSuchMethodException: com.hgkj.controler.action.UserAction.newsLoginAction() 不久前在学习struts ...
- vagrant在windows下的安装和配置(一)
记录一下安装和配置过程中的一些坑步骤一分别下载vagrant和VirtualBox,我这里下载的是vagrant_1.9.1.msi 和 VirtualBox-5.1.14-112924-Win.ex ...
- Visioi形状相关应用
选择手柄为白点 按住shift的同时移动白点更为灵活 黄色的点就是控制手柄(只有一维图形有) 当调整形状出现绿色边的时候说明:这个时候这个形状的边等于了某个形状的长 铅笔工具可以移动控制点来更形状 ...
- ulimit -u 解决 Jenkins OOM 错误
Apr 24, 2018 11:19:48 AM hudson.init.impl.InstallUncaughtExceptionHandler$DefaultUncaughtExceptionHa ...
- iOS定位权限请求时易犯的错误小结
起因 用户群反馈app可能请求了不合适的定位权限:始终定位. 看到这个截图,根据经验判断可能是后台定位功能导致可能不得不请求始终定位权限.再加上之前提交审核时,苹果要求在plist文件中新增NSLoc ...
- 1041 考试座位号 (15 分)C语言
每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位.正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考 ...
- DM7的SQL批量插入for、while方法
示例1,for用法: begin for i in 1...10000 loop insert into test values(i,i,'aaa',sysdate); if i mod 20 = 0 ...
- vue-cli3 中 sockjs-node/info?t=报错 的解决方法
页面突然出现这种报错: 查看Network看到是info接口报错,我项目中没有调用过该项目,然后百度查询sockjs-node/info?t=1562204191563, 首先 sockjs-node ...
- realme X2谷歌套件
目前市面上的很多手机是不支持谷歌相关组件的,经过不断的测试成功适配realme X2(真机测试完美适配) 为框架的GMS是用户想要体验整套Google服务不可绕开的一环,Google地图.Play商店 ...
- QGIS WGS84转其它坐标系并计算坐标
需求: 将带有经度.纬度(WGS84坐标系)坐标的文本(*.txt)转换成指定投影坐标系的shp文件并计算x,y坐标. 环境和工具: WIN10.QGIS2.16.带有经纬度坐标的文本.格式如下图: ...