被忽略的TraceId,可以用起來了


前言

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

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

 

TraceID作用和組成

TraceID標記了 瀏覽器發起的某個請求, 這個id可在服務端從接收請求到 響應請求中流轉,甚至接力傳遞給下游應用中流轉,用於唯一標記和定外這次請求。

一般用於定位請求日志

  ASP.Net Core 基於中間件管道處理請求, 根據需要記錄日志; 生產出故障時,在數量龐大的日志記錄中追蹤某個請求完整的處理鏈顯得很有必要(這個深有體會)。

針對單體程序,ASP.Net Core為我們提供了HttpContext.TraceIdentifier屬性, 這個TraceId由{ConnectionId}:{Request Number}組成,理論上這個id標記了位於某Http連接上的某次請求。

① 為什么由 {ConnectionId}:{Request Number}組成?

默認大部分讀者知曉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, 現在着重聊一下使用方式和衍生知識點

ASP.NET Core使用TraceId

搭配Nlog記錄TraceId

① 啟用NLog日志

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

public class Program { public static void Main(string[] args) { var webHost = WebHost.CreateDefaultBuilder(args)
                     .ConfigureAppConfiguration((hostingContext, configureDelagate) => {
                         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 {
    public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); }
}

③ 配置Nlog 顯示TraceId

   TraceId在Nlog 是以Layout Renderer形式表達的:

更多的Renderer參考。下面的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即可追蹤微服務的請求流

ASP.NET Core分布式TraceId:CorrelationId

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

  隆重介紹輪子 CorrelationId: https:/github.com/stevejgordon/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的作用和一般組成,衍生出ASP. NETCore  單體和分布式程序中 TraceId 的使用方式, 希望對大家在日志排障時有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM