天天看點

如何使用Serilog.AspNetCore記錄ASP.NET Core3.0的MVC屬性

這是在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
}
           
無論你使用

AddControllers

AddControllersWithViews

AddMvc

,或

AddMvcCore

的方式你都可以采用同樣的方式來添加全局過濾器。

有了這個配置之後,如果你調用一個MVC控制器,你在Serilog的請求日志消息中會看到額外的資料(

ActionName

ActionId

,和

RouteData

ValidationState

)記錄:

如何使用Serilog.AspNetCore記錄ASP.NET Core3.0的MVC屬性

您可以在此處将所需的任何其他資料添加到日志中。隻需注意記錄參數值-切記不要記錄敏感或個人身份資訊!

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.AspNetCore記錄ASP.NET Core3.0的MVC屬性

總結

預設情況下,當用Serilog的請求日志記錄中間件替換ASP.NET Core基礎結構中的日志記錄時,您會丢失一些資訊(與開發環境的預設配置相比)。在本文中,我将展示如何自定義Serilog,

RequestLoggingOptions

以重新添加特定于MVC的其他屬性。

要将與MVC相關的屬性添加到Serilog請求日志中,請建立一個

IActionFilter

并使用

IDiagnosticContext.Set()

來添加屬性。要将與Razor頁面相關的屬性添加到Serilog請求日志中,請在

IPageFilter

中使用

IDiagnosticContext

的相同方法建立和添加屬性。

下一節讓我們一起探讨下如何從Serilog請求記錄中排除運作狀況檢查端點。

作者:依樂祝(祝雷)

出處:https://www.cnblogs.com/yilezhu

聯系:[email protected] .NET Core實戰項目交流群:637326624 微信:jkingzhu

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。如有問題或建議,請多多賜教,非常感謝。

如何使用Serilog.AspNetCore記錄ASP.NET Core3.0的MVC屬性

繼續閱讀