.NET 分散式追蹤概念
分散式追蹤是一種診斷技術,幫助工程師定位應用程式中的故障和效能問題,尤其是那些可能分布在多部電腦或進程中的問題。 如需分散式追蹤用途的一般資訊,請參閱 分散式追蹤概觀。
記錄和活動
每次應用程式收到新的請求時,都可以將其與追蹤記錄關聯。 在以 .NET 撰寫的應用程式元件中,追蹤中的工作單位會以 System.Diagnostics.Activity 的實例表示,而整個追蹤會形成這些活動的樹狀結構,可能跨越許多不同的進程。 為新要求建立的第一個活動會形成追蹤樹狀結構的根,並追蹤處理要求的整體持續時間和成功/失敗。 您可以選擇性地建立子活動,將工作細分為可以個別追蹤的不同步驟。 例如,假設活動追蹤 Web 伺服器中的特定輸入 HTTP 要求,可以建立子活動來追蹤完成要求所需的每個資料庫查詢。 這可讓每個查詢獨立記錄持續時間和成功。 活動可以記錄每個工作單位的其他資訊,例如 OperationName、稱為 Tags的名稱/值組,以及 Events。 名稱會識別正在執行的工作類型、標記可以記錄工作的描述性參數,而事件是記錄時間戳診斷訊息的簡單記錄機制。
注意
分散式追蹤中工作單位的另一個常見產業名稱是 Spans。 許多年前,.NET 採用「活動」一詞,這發生在「Span」已被公認為這個概念的名稱之前。
活動標識碼
Parent-Child 分散式追蹤樹狀結構中的活動之間的關聯性是使用唯一標識元建立的。 .NET 的分散式追蹤實作支援兩種標識符配置:W3C 標準 TraceContext,這是 .NET 5+ 中的預設值,而舊版的 .NET 慣例稱為「階層式」,可供回溯相容性使用。 Activity.DefaultIdFormat 決定使用哪個 ID 方案。 在 W3C TraceContext 標準中,每個追蹤都會獲指派全域唯一的 16 位元組追蹤識別碼(Activity.TraceId),而追蹤中的每個活動都會指派唯一的 8 位元組跨度識別碼(Activity.SpanId)。 每個活動都會記錄追蹤標識碼、其本身的span-id,以及其父代的span-id(Activity.ParentSpanId)。 由於分散式追蹤可以跨進程界限追蹤工作,因此父活動和子活動可能不在相同的進程中。 追蹤標識符和父範圍標識碼的組合可以全域唯一識別父活動,無論它位於哪個進程。
Activity.DefaultIdFormat 會控制用來啟動新追蹤的 ID 格式,但根據預設,將新的活動新增至現有追蹤時會採用父活動使用的格式。 將 Activity.ForceDefaultIdFormat 設定為 true 將覆蓋此行為,並且即使父活動使用不同的識別格式,也會使用 DefaultIdFormat 來創建所有新的活動。
啟動和停止活動
進程中的每個線程都有對應的 Activity 物件,可追蹤該線程上發生的工作,可透過 Activity.Current存取。 目前的活動會自動沿著線程上的所有同步呼叫流動,並且會跟隨在其他線程上處理的異步呼叫。 如果活動 A 是線程上的目前活動,而且程式代碼會啟動新的活動 B,則 B 會成為該線程上新的目前活動。 根據預設,活動 B 也會將活動 A 視為其父系。 活動 B 稍後停止時,活動 A 將會還原為線程上的目前活動。 當活動啟動時,它會擷取目前的時間做為 Activity.StartTimeUtc。 停止時,Activity.Duration 會計算為目前時間與開始時間之間的差異。
跨進程界限協調
若要追蹤跨進程界限的工作,活動父標識碼必須透過網路傳輸,以便接收程式可以建立參考它們的活動。 使用 W3C TraceContext 識別符格式時,.NET 也會使用 標準 所建議的 HTTP 標頭來傳輸這項資訊。 使用 Hierarchical 識別符格式時,.NET 會使用自定義要求標識碼 HTTP 標頭來傳輸識別碼。 與許多其他語言執行環境不同,.NET 內建函式庫,例如 ASP.NET Web 伺服器和 System.Net.Http 能夠原生譯碼和編碼 HTTP 訊息上的活動識別符。 執行環境也瞭解如何透過同步和異步呼叫來傳遞識別碼。 這表示接收和發出 HTTP 訊息的 .NET 應用程式會自動參與流動的分散式追蹤 ID,無需應用程式開發人員或第三方函式庫相依性的特殊編碼。 第三方連結庫可能會新增透過非 HTTP 訊息通訊協定傳輸標識碼的支援,或支援 HTTP 的自定義編碼慣例。
收集痕跡
檢測的程式代碼可以建立 Activity 物件做為分散式追蹤的一部分,但是這些物件中的資訊必須在集中式持續性存放區中傳輸和串行化,以便稍後可以有效地檢閱整個追蹤。 有數個遙測集合連結庫可以執行這項工作,例如 Application Insights、OpenTelemetry,或第三方遙測或 APM 廠商所提供的連結庫。 或者,開發人員可以使用 System.Diagnostics.ActivityListener 或 System.Diagnostics.DiagnosticListener來撰寫自己的自定義活動遙測集合。 ActivityListener 支持觀察任何 Activity,無論開發人員是否對其有事先了解。 這可讓 ActivityListener 成為簡單且彈性的一般用途解決方案。 相反地,使用 DiagnosticListener 是更複雜的案例,需要已插入探針的程式碼透過叫用 DiagnosticSource.StartActivity 來選用,而且集合庫必須知道啟動程式碼時所使用的確切命名資訊。 使用 DiagnosticSource 和 DiagnosticListener 可讓建立者和接聽程序交換任意 .NET 物件,並建立自定義的資訊傳遞慣例。
採樣
為了提升高輸送量應用程式的效能,.NET 上的分散式追蹤只對部分追蹤資料進行取樣,而不是記錄所有的追蹤。 對於使用建議的 ActivitySource.StartActivity API 建立的活動,遙測收集庫可以使用 ActivityListener.Sample 回呼來控制取樣。 日誌庫可以選擇完全不建立活動物件、建立僅包含傳播分散式追蹤標識碼所需最少資訊的活動物件,或是填入完整診斷資訊的活動物件。 這些選擇會權衡增加效能額外負荷,以增加診斷公用程式。 使用叫用 Activity.Activity 和 DiagnosticSource.StartActivity 舊模式開始的活動,也可以先呼叫 DiagnosticSource.IsEnabled來支援 DiagnosticListener 取樣。 即使擷取完整的診斷資訊,.NET 實作依然設計得非常快速,加上高效能的收集器,在新式硬體上可以在微秒內完成活動的建立、填入及傳輸。 取樣可將未記錄之每個活動的檢測成本降低到小於 100 奈秒。
後續步驟
如需在 .NET 應用程式中開始使用分散式追蹤的範例程式代碼,請參閱 分散式追蹤檢測。
如需 .NET 原生發出的活動清單,請參閱 .NET中的內建活動