語言
在 .NET 11 及之後版本中,Microsoft.Extensions.Diagnostics.Tracing API 允許你註冊 ActivityListener 實例,並使用規則來選取每個接聽程式所接收的 ActivitySource 和 Activity 實例。 在程式碼中定義規則或從 IConfiguration載入。
Important
追蹤規則僅影響透過此追蹤基礎架構註冊的監聽器。 它們不會影響不相關的 ActivityListener 執行個體,包括遙測匯出器建立和管理的監聽器。 分別設定監聽器或匯出器。
暫存器追蹤
API 可在 Microsoft.Extensions.Diagnostics 套件中使用。 參考 Microsoft.AspNetCore.App 共享框架的應用程式已經包含了組件。
請在IServiceCollection上呼叫AddTracing。 在回呼中:
- 請呼叫 AddListener 來登記每個接聽程式。 監聽者名稱在設定規則中用來識別監聽者。
- 透過 ActivityListenerBuilder 配置監聽者的取樣與通知委派。 追蹤基礎設施擁有
ShouldListenTo、來源訂閱,以及監聽器的存留期。 - 使用包含規則的設定區段呼叫 AddConfiguration。 對於名為
Tracing的區段,傳遞configuration.GetSection("Tracing")。
完整範例顯示了這三種呼叫。 .NET 主機在主機啟動時會啟動追蹤訂閱。 如果你使用依賴注入而不使用主機,請解析已註冊的 ActivitySourceFactory 來建構監聽者並啟用它們的訂閱。 完整的範例會直接解析 Factory。
設定追蹤
透過設定或程式碼來設定追蹤規則。 若無規則匹配監聽者、來源、操作與作用域,該組合的追蹤功能仍被禁用。
無需程式碼設定追蹤
對於使用設定的應用程式,可以在 appsettings.json 或其他 Tracing 中新增一個區段。 然後將該段傳遞給 AddConfiguration:
tracing.AddConfiguration(configuration.GetSection("Tracing"));
以下範例展示了支援的規則區段與規則層級:
{
"Tracing": {
"EnabledTracing": {
"Default": false,
"Contoso": true,
"Contoso.Orders": {
"Default": true,
"HealthCheck": false
},
"Contoso.*.Storage": true
},
"EnabledGlobalTracing": {
"System.Net.Http": true
},
"EnabledLocalTracing": {
"Contoso.Workers": true
},
"Console": {
"EnabledLocalTracing": {
"Contoso.Orders": {
"Submit": false
}
}
}
}
}
直接在 EnabledGlobalTracing、EnabledLocalTracing 或 EnabledTracing 章節下方加入規則。 不要新增 Rules 層級。
規則章節
根據來源範圍及規則是否針對某一個接聽程式,選擇規則區塊:
| 區段 | 符合條件的監聽器 | 比對活動來源 |
|---|---|---|
EnabledTracing |
所有已註冊的監聽器。 | 全球與在地的來源。 |
EnabledGlobalTracing |
所有已註冊的監聽器。 | 僅限全域來源。 |
EnabledLocalTracing |
所有已註冊的監聽器。 | 僅限本機來源。 |
{Listener}:EnabledTracing |
具名監聽器。 | 全球與在地的來源。 |
{Listener}:EnabledGlobalTracing |
指定的監聽器。 | 僅限全球來源。 |
{Listener}:EnabledLocalTracing |
已命名的監聽器。 | 僅限本機來源。 |
監聽者名稱與傳入的 AddListener名稱相符。 段落名稱和監聽器名稱不區分大小寫。
規則等級
在任何規則章節中,請使用以下其中一種金鑰格式:
| 鍵值表單 | 規則層級 | 比對 |
|---|---|---|
Default |
Default. | 每一個來源和操作。 |
{SourceName} |
活動來源。 | 每項來自相符來源的操作。 |
{SourceName}:Default |
活動來源。 | 每個操作都與來源比對有關。 此表單允許來源項目同時包含操作規則。 |
{SourceName}:{OperationName} |
操作。 | 來自相符來源的已命名作業。 |
將每個葉子值設定為 true 以啟用匹配,或設定為 false 以停用匹配。 例如,前述的配置:
- 預設會關閉追蹤功能。
- 啟用名稱以
Contoso開頭的來源。 - 啟用
Contoso.Orders,但停用其HealthCheck作業。 - 啟用一個以
Contoso.為開頭、以.Storage為結尾的來源模式。 - 新增僅適用於全域來源、本地來源或名為
Console的監聽者 的規則。
使用 Default 作為布林葉。 若 Default 包含操作子節點,則組態將 Default 視為字面上的活動來源名稱。
用程式碼設定追蹤
對傳遞給 AddTracing 的ITracingBuilder呼叫 EnableTracing 和 DisableTracing。
tracing.EnableTracing(sourceName: "Contoso");
tracing.DisableTracing(
sourceName: "Contoso.Orders",
operationName: "HealthCheck");
省略 sourceName, operationName或 listenerName 以匹配該層級的所有值。 預設情況下,程式化規則同時適用於全域與本地來源。 透過 scopes 引數傳遞 Local、Global 或兩者,以縮小規則範圍。
配置規則與程式化規則組成一個有序規則集。 若同樣具體的規則相衝突,則最後加入的規則獲勝。 因此,當 EnableTracing、DisableTracing 和 AddTracing 加入同樣具體的規則時,AddConfiguration 回呼中的呼叫順序也很重要。
比對活動來源名稱
來源名稱、操作名稱與接聽程式名稱皆使用不區分大小寫的序數比較。 來源名稱規則支援以下比對形式:
- 空的來源名稱會匹配所有來源。
- 不含萬用字元的來源名稱會以前綴方式比對。 例如,
Contoso匹配Contoso.Orders和ContosoPayments;匹配器不需要在前綴後加分隔符。 - 一個有一個
*萬用字元的來源名稱會對應前綴和後綴。 例如,Contoso.*.Storage匹配Contoso.Orders.Storage,但不匹配Contoso.Orders.Api。 - 名稱為
*的來源符合所有來源。
作業名稱完全一致。 他們不使用前綴比對或萬用字元比對。
套用規則優先順序
對於每個監聽者、來源、操作與範圍的組合,追蹤基礎設施會選擇一條匹配的規則。 它會依照下列順序比較配對規則:
- 針對特定接聽程式的規則優先於所有接聽程式的規則。
- 原始碼規則優先於預設規則。 若兩個來源表達式相符,則較長的表達式優先。 比較時使用運算式長度,其中包含
*萬用字元。 - 操作規則優先於原始碼層級規則。
- 僅全域或僅本地規則優先於涵蓋兩個範圍的規則。
- 當所有前述因素相等時,最後一條規則才優先。
比較止於第一個差異。 例如,聽眾專屬的預設規則優先於適用於所有聽者的來源專屬規則,因為會先評估聽者的特定性。
操作規則同時控制來源訂用項目。 當操作規則從該來源啟用至少一項操作時,監聽者會訂閱該預設停用的來源。 監聽器接著回傳 None 並跳過被停用操作的回調。
選擇全球或在地活動來源
追蹤基礎設施區分了兩種活動來源範圍:
-
全域來源是透過其建構子建立的
ActivitySource物件。EnabledGlobalTracing規則適用於這些來源。 -
本地來源是由透過依賴注入解析出的
ActivitySource所建立的ActivitySourceFactory。EnabledLocalTracing規則適用於該工廠產生的來源項目。
當你想用相依注入容器來管理來源及其追蹤監聽器時,就用 Create 它。 工廠模式的監聽器會忽略由不同工廠模式建立的本機來源。 規則 EnabledTracing 適用於兩種來源類別。
這些範圍只限制由 AddTracing 註冊的聽眾。 獨立的 ActivityListener 會使用自己的 ShouldListenTo 和抽樣回調,即使是針對由 ActivitySourceFactory 創建的活動來源。
重新載入追蹤組態
AddConfiguration 訂閱所提供設定中的變更權杖。 當 設定提供者 支援重新載入並回報變更時,追蹤基礎設施:
- 重建規則集。
- 重新整理每個已註冊監聽器的來源訂閱。
- 將更新後的規則套用於後續活動。
應用程式在重新載入後仍可繼續使用相同的 ActivitySource 實例。 後續活動則使用更新後的規則。
對於不會自動回報變更的可變提供者,請更新設定並呼叫 Reload。 完整範例使用此方法搭配記憶體內配置提供者。
處理無效設定
追蹤配置使用 TryParse 解析值。 它接受 true 和 false,不區分大小寫,並允許前後留白。 它不接受 1、 0、 yes或 on。
設定載入器會默默忽略一個不是有效布林值的葉節點值。 它也會忽略與支援的結構描述不相符的未知或格式錯誤區段。 仔細檢查關鍵名稱,因為這些情況不會產生異常。
一個來源表達式最多只能包含一個 * 萬用字元。 包含多個通配符的規則會在該規則實體化時拋出 ArgumentException,無論是在應用程式啟動時或設定重新載入後。 對於程式規則,None 也會導致 ArgumentOutOfRangeException。
執行範例程式
以下 .NET 11 主控台應用程式會建立一個啟用操作和一個停用操作。 接著更新被停用操作的規則,呼叫 Reload,並透過相同的本地 ActivitySource 再次啟動該操作。
using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.Tracing;
IConfigurationRoot configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Tracing:EnabledTracing:Default"] = "false",
["Tracing:EnabledTracing:Contoso.Orders:Default"] = "true",
["Tracing:EnabledTracing:Contoso.Orders:DisabledOperation"] = "false",
})
.Build();
ServiceCollection services = new();
services.AddTracing(tracing =>
{
tracing.AddListener("Console", listener =>
{
listener.Sample = static (ref ActivityCreationOptions<ActivityContext> _) =>
ActivitySamplingResult.AllData;
listener.SampleUsingParentId = static (ref ActivityCreationOptions<string> _) =>
ActivitySamplingResult.AllData;
listener.ActivityStarted = activity =>
Console.WriteLine($"Listener started: {activity.OperationName}");
});
tracing.AddConfiguration(configuration.GetSection("Tracing"));
});
using ServiceProvider serviceProvider = services.BuildServiceProvider();
ActivitySourceFactory factory =
serviceProvider.GetRequiredService<ActivitySourceFactory>();
using ActivitySource source = factory.Create("Contoso.Orders");
Console.WriteLine("Before reload:");
WriteResult(source, "EnabledOperation");
WriteResult(source, "DisabledOperation");
configuration["Tracing:EnabledTracing:Contoso.Orders:DisabledOperation"] = "true";
configuration.Reload();
Console.WriteLine("After reload:");
WriteResult(source, "DisabledOperation");
static void WriteResult(ActivitySource source, string operationName)
{
using Activity? activity = source.StartActivity(operationName);
string state = activity is null ? "disabled" : "enabled";
Console.WriteLine($"{operationName}: {state}");
}
Imports System.Diagnostics
Imports Microsoft.Extensions.Configuration
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Diagnostics.Tracing
Module Program
Sub Main()
Dim initialData As New Dictionary(Of String, String) From {
{"Tracing:EnabledTracing:Default", "false"},
{"Tracing:EnabledTracing:Contoso.Orders:Default", "true"},
{"Tracing:EnabledTracing:Contoso.Orders:DisabledOperation", "false"}
}
Dim configuration As IConfigurationRoot =
New ConfigurationBuilder().AddInMemoryCollection(initialData).Build()
Dim services As New ServiceCollection()
services.AddTracing(
Sub(tracing)
tracing.AddListener(
"Console",
Sub(listener)
listener.Sample = AddressOf SampleActivity
listener.SampleUsingParentId = AddressOf SampleActivityUsingParentId
listener.ActivityStarted =
Sub(activity) Console.WriteLine(
$"Listener started: {activity.OperationName}")
End Sub)
tracing.AddConfiguration(configuration.GetSection("Tracing"))
End Sub)
Using serviceProvider As ServiceProvider = services.BuildServiceProvider()
Dim factory As ActivitySourceFactory =
serviceProvider.GetRequiredService(Of ActivitySourceFactory)()
Using source As ActivitySource = factory.Create("Contoso.Orders")
Console.WriteLine("Before reload:")
WriteResult(source, "EnabledOperation")
WriteResult(source, "DisabledOperation")
configuration(
"Tracing:EnabledTracing:Contoso.Orders:DisabledOperation") = "true"
configuration.Reload()
Console.WriteLine("After reload:")
WriteResult(source, "DisabledOperation")
End Using
End Using
End Sub
Private Function SampleActivity(
ByRef options As ActivityCreationOptions(Of ActivityContext)
) As ActivitySamplingResult
Return ActivitySamplingResult.AllData
End Function
Private Function SampleActivityUsingParentId(
ByRef options As ActivityCreationOptions(Of String)
) As ActivitySamplingResult
Return ActivitySamplingResult.AllData
End Function
Private Sub WriteResult(source As ActivitySource, operationName As String)
Using activity As Activity = source.StartActivity(operationName)
Dim state As String = If(activity Is Nothing, "disabled", "enabled")
Console.WriteLine($"{operationName}: {state}")
End Using
End Sub
End Module
C# 與 Visual Basic 範例產生相同的結果:
Before reload:
Listener started: EnabledOperation
EnabledOperation: enabled
DisabledOperation: disabled
After reload:
Listener started: DisabledOperation
DisabledOperation: enabled