这是在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)记录:

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

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

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

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

如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性的更多相关文章

  1. 问题:ClientIDMode属性;结果:ASP.NET 4.0的ClientIDMode属性

    ASP.NET 4.0的ClientIDMode属性 时光流逝,我们心爱的ASP.NET也步入了4.0的时代,微软在ASP.NET 4.0中对很多特性做了修改.比如我将要讨论的控件ID机制就是其中之一 ...

  2. 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 ...

  3. asp.net core3.0 mvc 用 autofac

    好久没有写文章了,最近在用.net core3.0,一些开发中问题顺便记录: 1.首先nuget引入 Autofac Autofac.Extensions.DependencyInjection 2. ...

  4. ASP.NET 4.0的ClientIDMode属性

    时光流逝,我们心爱的ASP.NET也步入了4.0的时代,微软在ASP.NET 4.0中对很多特性做了修改.比如我将要讨论的控件ID机制就是其中之一. 在ASP.NET 4.0之前我们总是要为控件的Cl ...

  5. ASP.NET Core3.0 中的运行时编译

    运行时编译 通过 Razor 文件的运行时编译补充生成时编译. 当 .cshtml 文件的内容发生更改时,ASP.NET Core MVC 将重新编译 Razor 文件 . 通过 Razor 文件的运 ...

  6. Postman 调试请求Asp.Net Core3.0 WebApi几种常见的Get/Post/Put/Delete请求

    这里就直接截图了,如下(很简单的操作): 1:Get几种请求 2:Post 3:Put 4:Delete  最后,虽然简单,代码还是给放一下(这里只是抛砖引玉的作用,自己可以根据自身的业务需要来做进一 ...

  7. Asp.net Core3.0 跨域配置

    原文:http://www.zilaohu.cn/Jie/Detail_Jie?ID=78840a04-55b8-4988-80b2-f964fd822d63 下面配置后:被拒绝的域请求后,可以进入方 ...

  8. 探索Asp net core3中的 项目文件、Program.cs和通用host(译)

    引言 原文地址 在这篇博客中我将探索一些关于Asp.net core 3.0应用的基础功能--.csproj 项目文件和Program源文件.我将会描述他们从asp.net core 2.X在默认模版 ...

  9. ASP.NETCore 3.0 Autofac替换及控制器属性注入及全局容器使用

    1.Autofac基础使用 参考: https://www.cnblogs.com/li150dan/p/10071079.html 2.ASP.NETCore 3.0 Autofac 容器替换 需要 ...

随机推荐

  1. 开篇 | 揭秘 Flink 1.9 新架构,Blink Planner 你会用了吗?

    本文为 Apache Flink 新版本重大功能特性解读之 Flink SQL 系列文章的开篇,Flink SQL 系列文章由其核心贡献者们分享,涵盖基础知识.实践.调优.内部实现等各个方面,带你由浅 ...

  2. 浮点数NaN和INF(#IND, #INF)

    NaN&INF定义在一些情况会出现无效的浮点数,例如除0,例如负数求平方根等,像这类情况,获取到的浮点数的值是无效的. NaN 即 Not a Number         非数字 INF  ...

  3. 深入谷歌和甲骨文旷日持久的版权战争,趣味科普当前最火的编程语言JAVA的前世今生

    这篇文章是我在B站上投稿的一个科普java的视频文案,内容如标题,感兴趣的码农朋友可以移步观看https://www.bilibili.com/video/av81171108/ 在过去短短几十年间, ...

  4. Linux(Centos)安装node及anyproxy

    一.安装node //下载 wget https://nodejs.org/dist/v10.9.0/node-v10.9.0-linux-x64.tar.xz //解压 tar xf node-v1 ...

  5. JAVA8之 Stream 流(四)

    如果说前面几章是函数式编程的方法论,那么 Stream 流就应该是 JAVA8 为我们提供的最佳实践. Stream 流的定义 Stream 是支持串行和并行操作的一系列元素.流操作会被组合到流管道中 ...

  6. IntelliJ IDEA安装教程及使用方法

    IntelliJ IDEA安装教程及使用方法 首先,需要去下载IDEA,直接在百度搜索IntelliJ IDEA,然后找到官网点击进入 进入官网,选择[Download],点击进入,选择自己的操作系统 ...

  7. 小小知识点(二十七)20大5G关键技术

    5G网络技术主要分为三类:核心网.回传和前传网络.无线接入网. 核心网 核心网关键技术主要包括:网络功能虚拟化(NFV).软件定义网络(SDN).网络切片和多接入边缘计算(MEC). 1 网络功能虚拟 ...

  8. 用Eclipse和Tomcat搭建一个本地服务器

    服务器软件环境 Eclipse oxygen Tomcat 9.0 SQL Sever 2014 参考资料 https://blog.csdn.net/qq_21154101/article/deta ...

  9. Cassandra数据建模中最重要的事情:主键

    Cassandra数据建模中要了解的最重要的事情:主键 使用关系数据建模,您可以从主键开始,但是RDBMS中的有效数据模型更多地是关于表之间的外键关系和关系约束.由于Cassandra无法使用JOIN ...

  10. 小白学 Python 爬虫(36):爬虫框架 Scrapy 入门基础(四) Downloader Middleware

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...