专栏首页依乐祝Serilog高级玩法之用Serilog记录所选终结点附加属性

Serilog高级玩法之用Serilog记录所选终结点附加属性

这是该系列的第二篇文章:在ASP.NET Core 3.0中使用Serilog.AspNetCore

  1. 第1部分-使用Serilog RequestLogging来简化ASP.NET Core的日志输出
  2. 第2部分-用Serilog记录所选终结点的附加属性(本文)
  3. 第3部分-使用Serilog.AspNetCore记录MVC属性[敬请期待]
  4. 第4部分-从Serilog请求记录中排除运行状况检查端点[敬请期待]

作者:依乐祝 译文地址:https://www.cnblogs.com/yilezhu/p/12227271.html 原文地址:https://andrewlock.net/using-serilog-aspnetcore-in-asp-net-core-3-logging-the-selected-endpoint-name-with-serilog/

我的上一篇文章中,我描述了如何配置Serilog的RequestLogging中间件为每个请求创建“摘要”日志,以替换默认情况下从ASP.NET Core获取的10个或更多日志。

在本文中,我将展示如何向Serilog的摘要请求日志中添加其他元数据,例如请求的主机名,响应的内容类型或从ASP.NET Core 3.0中使用的终结点路由中间件所选择的端点名称。

ASP.NET Core基础结构日志很详细,但是默认情况下具有太多详细信息

正如我在上一篇文章(https://andrewlock.net/using-serilog-aspnetcore-in-asp-net-core-3-reducing-log-verbosity/)中所展示的那样,在开发环境中,ASP.NET Core基础架构将为每一个RazorPage处理程序生成10条日志消息:

通过安装了Serilog.AspNetCore的 NuGet包后并引入RequestLoggingMiddleware之后,可以将其精简为一条日志消息:

本文中使用的所有日志图片均来自一款优秀的为结构化日志提供可视化界面的工具-Seq

显然,原始的日志集更加冗长,并且其中大部分不是特别有用的信息。但是,如果您将原始的10条日志作为一个整体来看,则与Serilog摘要日志相比,它们确实会在结构日志模板中记录一些其他属性。

由ASP.NET Core基础结构记录的而Serilog 未记录的扩展内容包括(下面这些还是英文的看着顺眼):

  • Host (localhost:5001)
  • Scheme (https)
  • Protocol (HTTP/2)
  • QueryString (test=true)
  • EndpointName (/Index)
  • HandlerName (OnGet/SerilogRequestLogging.Pages.IndexModel.OnGet)
  • ActionId (1fbc88fa-42db-424f-b32b-c2d0994463f1)
  • ActionName (/Index)
  • RouteData ({page = "/Index"})
  • ValidationState (True/False)
  • ActionResult (PageResult)
  • ContentType (text/html; charset=utf-8)

我认为如果要把上述属性中的其中一些包含在摘要日志消息中,将非常有用。例如,如果您的应用程序绑定到多个主机名,那么Host绝对是重要的日志。QueryString可能是另一个有用的字段。EndpointName/ HandlerNameActionId并且ActionName似乎不那么重要,因为您应该能够推断出给定的请求路径,但是显式记录它们将帮助您更加方便的捕获错误,并使过滤针对特定操作的所有请求变得更加容易。

概括地说,您可以将这些属性分为两类:

  • 请求/响应特性:如HostSchemeContentTypeQueryStringEndpointName
  • MVC / RazorPages相关的属性:如HandlerNameActionIdActionResult

在这篇文章中,我将展示如何添加这些类别中的第一种,即与请求/响应相关的属性,在下一篇文章中,我将展示如何添加基于MVC / RazorPages的属性。

向Serilog请求日志添加扩展数据

在上一篇文章中,我展示了如何将Serilog请求日志记录添加到您的应用程序中,因此在此不再赘述。现在,我假设您已经进行了设置,并且您拥有一个包含以下内容的Startup.Configure方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... Error handling/HTTPS middleware
    app.UseStaticFiles();

    app.UseSerilogRequestLogging(); // <-- Add this line

    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

UseSerilogRequestLogging()扩展方法将Serilog RequestLoggingMiddleware添加到请求管道中。您还可以通过调用重载来配置RequestLoggingOptions的实例。此类具有几个属性,可以让您自定义请求记录器如何生成日志语句:

public class RequestLoggingOptions
{
    public string MessageTemplate { get; set; }
    public Func<HttpContext, double, Exception, LogEventLevel> GetLevel { get; set; }
    public Action<IDiagnosticContext, HttpContext> EnrichDiagnosticContext { get; set; }
}

MessageTemplate属性控制将日志呈现为的字符串格式,GetLevel允许您控制给定日志索要记录的级别,如 Debug/ Info/ Warning等。这里我们所关心的是EnrichDiagnosticContext属性。

设置了该属性的Action<>之后,在生成日志消息时它将被Serilog中间件调用并执行。它在日志写入之前运行,这意味着它中间件管道执行之后运行。例如,在下图中(取自我的书《 ASP.NET Core in Action》),当响应“回传”到中间件管道时,在第5步写入日志:

在管道处理之后写入日志这一事实意味着两件事:

  • 我们可以访问Response的属性,例如状态码,经过的时间或内容类型
  • 我们可以访问在管道后面设置的中间件的功能,例如,由EndpointRoutingMiddleware(通过UseRouting()添加的)设置的功能:IEndpointFeature

在下一部分中,我将提供一个帮助程序功能,该功能会将所有“缺少”属性添加到Serilog请求日志消息中。

在IDiagnosticContext中设置扩展值

Serilog.AspNetCore会将接口IDiagnosticContext作为单例添加到DI容器中,因此您可以从任何类中访问它。然后,您可以调用Set()方法,将其他属性附加到请求日志消息中。

例如,如文档所示,您可以从操作方法中添加任意值:

public class HomeController : Controller
{
    readonly IDiagnosticContext _diagnosticContext;
    public HomeController(IDiagnosticContext diagnosticContext)
    {
        _diagnosticContext = diagnosticContext;
    }

    public IActionResult Index()
    {
        // The request completion event will carry this property
        _diagnosticContext.Set("CatalogLoadTime", 1423);
        return View();
    }
}

然后,结果摘要日志将包含属性CatalogLoadTime

RequestLoggingOptions通过设置所提供IDiagnosticContext实例的值,我们基本上使用完全相同的方法来定制中间件所使用的方法。下面的静态帮助器类从当前HttpContext上下文检索值,并在值可用时对其进行设置。 下面的静态helper类从当前HttpContext检索值,并在值可用时设置它们。

public static class LogHelper 
{
    public static void EnrichFromRequest(IDiagnosticContext diagnosticContext, HttpContext httpContext)
    {
        var request = httpContext.Request;

        // Set all the common properties available for every request
        diagnosticContext.Set("Host", request.Host);
        diagnosticContext.Set("Protocol", request.Protocol);
        diagnosticContext.Set("Scheme", request.Scheme);

        // Only set it if available. You're not sending sensitive data in a querystring right?!
        if(request.QueryString.HasValue)
        {
            diagnosticContext.Set("QueryString", request.QueryString.Value);
        }

        // Set the content-type of the Response at this point
        diagnosticContext.Set("ContentType", httpContext.Response.ContentType);

        // Retrieve the IEndpointFeature selected for the request
        var endpoint = httpContext.GetEndpoint();
        if (endpoint is object) // endpoint != null
        {
            diagnosticContext.Set("EndpointName", endpoint.DisplayName);
        }
    }
}

上面的帮助器函数从“Request”,“Response”以及其他中间件(端点名称)设置的功能中检索值。您可以扩展它,以根据需要在请求中添加其他值。

您可以在你的Startup.Configure()方法中通过调用UseSerilogRequestLoggingEnrichDiagnosticContext属性,来注册上面的帮助类:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... Other middleware

    app.UseSerilogRequestLogging(opts
        => opts.EnrichDiagnosticContext = LogHelper.EnrichFromRequest);

    // ... Other middleware
}

现在,当您发出请求时,您将看到添加到Serilog结构化日志中的所有其他属性:

只要您具有通过当前HttpContext可供中间件管道使用的值,就可以使用此方法。但是MVC的相关属性是个例外,它们是MVC中间件“内部”的特性,例如action 名称或RazorPage处理程序名称。在下一篇文章中,我将展示如何将它们添加到Serilog请求日志中。

总结

默认情况下,用Serilog的请求日志记录中间件替换ASP.NET Core基础结构日志记录时,与开发环境的默认日志记录配置相比,您会丢失一些信息。在本文中,我展示了如何通过自定义Serilog RequestLoggingOptions来添加这些附加属性。

这样的做法非常简单-您可以访问HttpContext,因此你可以检索它包含的任何可用的值,并将它们设置为IDiagnosticContext所提供的属性。这些属性将作为附加属性添加到Serilog生成的结构化日志中。在下一篇文章中,我将展示如何将MVC特定的属性值添加到请求日志中。敬请期待吧!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何从Serilog请求日志记录中排除健康检查终结点

    这是在ASP.NET Core 3.X中使用Serilog.AspNetCore系列文章的第四篇文章:。

    依乐祝
  • 如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性

    在我上篇文章中,我描述了如何配置Serilog的RequestLogging中间件以向Serilog的请求日志摘要中添加其他属性(例如请求主机名或选定的端点名称...

    依乐祝
  • 如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出

    这是该系列的第一篇文章:在ASP.NET Core 3.0中使用Serilog.AspNetCore。

    依乐祝
  • 在asp.net web api 2 (ioc autofac) 使用 Serilog 记录日志

    Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog。 在我个人的asp.net web api 2 基础框架(Gith...

    solenovex
  • ASP.NET Core使用Elasticsearch记录API请求响应日志实战演练

    跟着阿笨一起玩NET
  • .NET Core 基于 Grafana Loki 日志初体验

    Loki是一个轻量级的日志系统,受到Prometheus项目的启发,由Grafana团队设计和开发,所以在Grafana中是原生支持的,具有可水平扩展,高度可用...

    全球技术精选
  • 用ASP.NET Core 2.0 建立规范的 REST API -- DELETE, UPDATE, PATCH 和 Log

    本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblog...

    solenovex
  • .NET下使用 Seq结构化日志系统

        综合考虑,第三点肯定是不靠谱的,第一点成本太高,公司本来就比较忙,那就只能去找一个现成的了…

    喝茶去
  • 如何激发团队潜能?

    每个技术人员最终可能都会走上管理岗位,从最初的开发 Leader、到部门负责人、甚至到 CTO,这每一个角色的转变,都需要付出巨大的努力去进行思维的转变。最近读...

    oec2003

扫码关注云+社区

领取腾讯云代金券