TraceID在AspNETCore日誌排障中的應用

前言

  .NetCore日誌,相信你們多少都接觸過,博客園有關 ① AspNetCore依賴注入第三方日誌組件   ②第三方日誌組件Nlog,Serilog 應用方法的博文層出不窮。git

結合程序的部署結構,本文分單體和微服務聊一聊AspNetCore中追蹤日誌流的方法。github

TraceId

  AspNetCore程序基於Pipeline和中間件處理請求, 根據須要記錄日誌; 生產出故障時,在數量龐大的日誌記錄中追蹤某個請求完整的處理鏈顯得頗有必要(這個深有體會)。web

針對單體程序,AspNetCore貼心的爲咱們提供了HttpContext.TraceIdentifier屬性, 這個TraceId由{ConnectionId};{Request Number}組成,理論上這個id標記了位於某Http鏈接上的某次請求。json

① 爲何由 {ConnectionId}:{Request Number}組成?app

默認大部分讀者知曉Http1.1 一個鏈接上可發起多個Http請求框架

② TraceId 中ConnectionId 有Kestrel從{0-9,a-z}中生成, 具體方式可參考:https://github.com/aspnet/KestrelHttpServer/blob/a48222378b8249a26b093b5b835001c7c7b45815/src/Kestrel.Core/Internal/Infrastructure/CorrelationIdGenerator.cs分佈式

ok, 如今着重聊一下應用方式和衍生知識點ide

① 啓用NLog日誌微服務

  添加  <PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" />ui

public class Program
    {
        public static void Main(string[] args)
        {
            var webHost = WebHost.CreateDefaultBuilder(args)
                     .ConfigureAppConfiguration((hostingContext, configureDelagate) =>
                     {
                         //configureDelegate默認會按照以下順序加載ChainedConfiguration、appsetting.*.json,Environment、CommandLine
                         configureDelagate.AddJsonFile($"appsettings.secrets.json", optional: true, reloadOnChange: true);
                     })
                     .ConfigureLogging((hostingContext, loggingBuilder) =>
                     {
                         loggingBuilder.AddConsole().AddDebug();
                     })
                     .UseNLog()       // 默認會找工做目錄下nlog.config配置文件
                     .UseStartup<Startup>()
                     .Build();
            webHost.Run();
        }
    }

很明顯,Nlog要在Pipeline中自由獲取HttpContext屬性,這裏須要註冊 IHttpContextAccessor

public class Startup
{
    // rest of the code omitted for brevity
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }
    // rest of the code omitted for brevity
}

② 配置Nlog 以支持 TraceId

實際上nlog支持記錄不少HttpContext信息,詳情請關注https://nlog-project.org/config/?tab=layout-renderers

 下面的Nlog配置文件呈現了TraceId & User_Id, (業務上的UserId能幫助咱們在茫茫日誌中快速縮小日誌)

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  autoReload="true" throwExceptions="false"  internalLogFile="internal-nlog.txt">
  <variable name="logDir" value="logs/${date:format=yyyyMMdd}" />     <!-- 日誌存儲文件夾-->
  <variable name="format" value="${date:format=yy/MM/dd HH\:mm\:ss} [${level}].[${logger}].[${aspnet-TraceIdentifier}].[${aspnet-user-identity}]${newline}${message} ${exception:format=tostring}" />
  <targets>
    <target name="info"
           xsi:type="File"
           layout="${format}"
           fileName="${logDir}/info.log"
           encoding="utf-8"/>
  </targets>   
  <rules>
    <logger name="*" minlevel="Info" writeTo="info" />
  </rules>
</nlog>

 結果以下:

以上是在單體程序內根據traceid追蹤請求流的方法。

進一步思考,在微服務中,各服務獨立造成TraceId,在初始階段生成 TraceId 並在各微服務中保持該Traceid便可追蹤微服務的請求流。

CorrelationId

這裏首先假設你的微服務/ 分佈式服務已經部署ELK 等日誌幾種採集處理框架,沒有部署ELK也可將多個服務的日誌寫到同一個物理文件夾。

  隆重介紹輪子CorrelationId

CorrelationId是經過自定義Header來標記TraceId概念

  •   CorrelationId 在首次收到請求時自定義名爲【X-Correlation-ID】 的請求頭,在本服務Response寫入該Header 

  •   後置服務檢測到請求頭中包含該Header, 將該CorrelationId做爲本服務的TraceId 向後流轉

這樣在集中日誌中,能經過某TraceID追蹤微服務/分佈式 全鏈路請求處理日誌。

使用方式也至關簡單:

// Install-Package CorrelationId -Version 2.1.0

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddCorrelationId();
}

通常在全部請求處理Middleware以前註冊 CorrelationId, 這樣在全部中間件就能獲取到 TraceId:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   app.UseCorrelationId();

   if (env.IsDevelopment())
   {
      app.UseDeveloperExceptionPage();
   }

   app.UseMvc();
}

打算應用該TraceId追蹤全流程請求日誌的服務都須要包含 中間件。

Ok, 本文由淺入深TraceID在單體程序和 分佈式程序中的應用, 但願對你們在日誌排障時有所幫助。

相關文章
相關標籤/搜索