收集分散式追蹤
本文適用於:✔️.NET Core 2.1 和更新版本 ✔️ .NET Framework 4.5 和更新版本
檢測的程式碼可以建立 Activity 物件做為分散式追蹤的一部分,但必須將這些物件中的資訊收集到集中式儲存體中,以便稍後能檢閱整個追蹤。 在本教學課程中,您將以不同的方式收集分散式追蹤遙測,使其能在需要診斷應用程式問題時派上用場。 如果您需要新增檢測,請參閱檢測教學課程。
使用 OpenTelemetry 收集追蹤
OpenTelemetry 是 Cloud Native Computing Foundation 支援的廠商中立開放原始碼專案,旨在標準化雲端原生軟體遙測的產生和收集。 在這些範例中,您會收集分散式追蹤資訊並將其顯示在主控台上。 若要了解如何設定 OpenTelemetry 以將資訊傳送到其他地方,請參閱 OpenTelemetry 使用者入門指南。
ASP.NET 範例
必要條件
- .NET Core 7.0 SDK 或更新版本
建立範例應用程式
首先,建立新的 ASP.NET Web 應用程式來作為示範應用程式。
dotnet new webapp
此應用程式會顯示網頁,但若瀏覽該網頁,您會發現未收集任何分散式追蹤資訊。
設定收集
若要使用 OpenTelemetry,您必須將參考新增至數個 NuGet 套件。
dotnet add package OpenTelemetry --version 1.4.0-rc1
dotnet add package OpenTelemetry.Exporter.Console --version 1.4.0-rc1
dotnet add package OpenTelemetry.Extensions.Hosting --version 1.4.0-rc1
dotnet add package OpenTelemetry.Instrumentation.AspNetCore --version 1.0.0-rc9.10
注意
撰寫本文時,1.4.0 候選版 1 組建是可用的最新版 OpenTelemetry。 一旦最終版本可供使用,請改用該版本。
接下來,修改 Program.cs 中的原始程式碼,使其看起來像這樣:
using OpenTelemetry;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddOpenTelemetry()
.WithTracing(builder =>
{
builder.AddAspNetCoreInstrumentation();
builder.AddConsoleExporter();
}).StartWithHost();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
執行應用程式,並使用網頁瀏覽器來瀏覽至裝載的網頁。 現在您已啟用 OpenTelemetry 分散式追蹤,您應該會看到列印至主控台的瀏覽器網頁要求相關資訊:
Activity.TraceId: 9c4519ce65a667280daedb3808d376f0
Activity.SpanId: 727c6a8a6cff664f
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName: /
Activity.Kind: Server
Activity.StartTime: 2023-01-08T01:56:05.4529879Z
Activity.Duration: 00:00:00.1048255
Activity.Tags:
net.host.name: localhost
net.host.port: 5163
http.method: GET
http.scheme: http
http.target: /
http.url: http://localhost:5163/
http.flavor: 1.1
http.user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76
http.status_code: 200
Resource associated with Activity:
service.name: unknown_service:demo
所有 OpenTelemetry 組態都會發生在以 builder.Services.AddOpenTelemetry()
開頭的新來源行中。 您已使用 .WithTracing(...)
來啟用分散式追蹤。 AddAspNetCoreInstrumentation()
已啟用 OpenTelemetry 來收集 ASP.NET Core 網頁伺服器所產生的所有分散式追蹤活動,且 AddConsoleExporter()
會指示 OpenTelemetry 將該資訊傳送至主控台。 對於較重要的應用程式,您可以新增更多檢測程式庫,以收集資料庫查詢或輸出 HTTP 要求的追蹤。 您也可以將主控台匯出工具取代為適用於 Jaeger、Zipken 或其他所選監視服務的匯出工具。
主控台應用程式範例
必要條件
- .NET Core 2.1 SDK 或更新版本
建立範例應用程式
您必須先產生分散式追蹤遙測,才可以收集這些遙測。 此檢測通常位於程式庫中,但為了簡單起見,您將建立一個小型應用程式,其中包含一些使用 StartActivity 的檢測範例。 此時未發生任何收集動作,而且 StartActivity() 沒有副作用,並傳回 null。 如需詳細資訊,請參閱檢測教學課程。
dotnet new console
目標為 .NET 5 和更新版本的應用程式已經包含必要的分散式追蹤 API。 針對以舊 .NET 版本為目標的應用程式,請新增 System.Diagnostics.DiagnosticSource NuGet 套件 第 5 版或更新版本。
dotnet add package System.Diagnostics.DiagnosticSource
以下列範例來源取代產生的 Program.cs 內容:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Sample.DistributedTracing
{
class Program
{
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
static async Task Main(string[] args)
{
await DoSomeWork();
Console.WriteLine("Example work done");
}
static async Task DoSomeWork()
{
using (Activity a = s_source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
}
}
static async Task StepOne()
{
using (Activity a = s_source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}
static async Task StepTwo()
{
using (Activity a = s_source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
}
}
}
執行應用程式還不會收集任何追蹤資料:
> dotnet run
Example work done
設定收集
新增 OpenTelemetry.Exporter.Console NuGet 套件。
dotnet add package OpenTelemetry.Exporter.Console
使用其他 OpenTelemetry using
指示詞更新 Program.cs:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
更新 Main()
以建立 OpenTelemetry TracerProvider:
public static async Task Main()
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample"))
.AddSource("Sample.DistributedTracing")
.AddConsoleExporter()
.Build();
await DoSomeWork();
Console.WriteLine("Example work done");
}
現在應用程式會收集分散式追蹤資訊,並將其顯示至主控台:
> dotnet run
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-6081a9b8041cd840-01
Activity.ParentId: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: StepOne
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:46.8649754Z
Activity.Duration: 00:00:00.5069226
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-d2b283db91cf774c-01
Activity.ParentId: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: StepTwo
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:47.3838737Z
Activity.Duration: 00:00:01.0142278
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:46.8634510Z
Activity.Duration: 00:00:01.5402045
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Example work done
來源
在範例程式碼中,您已叫用 AddSource("Sample.DistributedTracing")
,讓 OpenTelemetry 擷取 ActivitySource (已存在於程式碼中) 所產生的活動:
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
您可以從任何 ActivitySource 擷取遙測,方法是使用來源的名稱呼叫 AddSource()
。
出口商
主控台匯出工具有助於提供快速範例或進行本機開發,但在生產部署中,您可能會想要將追蹤傳送至集中式存放區。 OpenTelemetry 支援使用不同匯出工具的各種目的地。 如需設定 OpenTelemetry 的詳細資訊,請參閱 OpenTelemetry 使用者入門指南。
使用 Application Insights 收集追蹤
為 ASP.NET 或 ASP.NET Core 應用程式設定 Application Insights SDK 之後,或啟用無程式碼檢測,就會自動擷取分散式追蹤遙測。
如需詳細資訊,請參閱 Application Insights 分散式追蹤文件。
注意
目前,Application Insights 僅支援收集特定的已知活動檢測,並且會忽略新的使用者新增活動。 Application Insights 提供 TrackDependency 作為廠商專屬 API,可新增自訂分散式追蹤資訊。
使用自訂邏輯收集追蹤
開發人員可以免費為活動追蹤資料建立自己的自訂收集邏輯。 此範例會使用 .NET 所提供的 System.Diagnostics.ActivityListener API 收集遙測,並將其列印到主控台。
必要條件
- .NET Core 2.1 SDK 或更新版本
建立範例應用程式
首先,您將建立一個範例應用程式,其中包含一些分散式追蹤檢測,但不會收集任何追蹤資料。
dotnet new console
目標為 .NET 5 和更新版本的應用程式已經包含必要的分散式追蹤 API。 針對以舊 .NET 版本為目標的應用程式,請新增 System.Diagnostics.DiagnosticSource NuGet 套件 第 5 版或更新版本。
dotnet add package System.Diagnostics.DiagnosticSource
以下列範例來源取代產生的 Program.cs 內容:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Sample.DistributedTracing
{
class Program
{
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
static async Task Main(string[] args)
{
await DoSomeWork();
Console.WriteLine("Example work done");
}
static async Task DoSomeWork()
{
using (Activity a = s_source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
}
}
static async Task StepOne()
{
using (Activity a = s_source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}
static async Task StepTwo()
{
using (Activity a = s_source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
}
}
}
執行應用程式還不會收集任何追蹤資料:
> dotnet run
Example work done
新增程式碼以收集追蹤
使用下列程式碼更新 Main():
static async Task Main(string[] args)
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;
Console.WriteLine(" {0,-15} {1,-60} {2,-15}", "OperationName", "Id", "Duration");
ActivitySource.AddActivityListener(new ActivityListener()
{
ShouldListenTo = (source) => true,
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllDataAndRecorded,
ActivityStarted = activity => Console.WriteLine("Started: {0,-15} {1,-60}", activity.OperationName, activity.Id),
ActivityStopped = activity => Console.WriteLine("Stopped: {0,-15} {1,-60} {2,-15}", activity.OperationName, activity.Id, activity.Duration)
});
await DoSomeWork();
Console.WriteLine("Example work done");
}
輸出現在會包含記錄:
> dotnet run
OperationName Id Duration
Started: SomeWork 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-c447fb302059784f-01
Started: StepOne 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-a7c77a4e9a02dc4a-01
Stopped: StepOne 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-a7c77a4e9a02dc4a-01 00:00:00.5093849
Started: StepTwo 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-9210ad536cae9e4e-01
Stopped: StepTwo 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-9210ad536cae9e4e-01 00:00:01.0111847
Stopped: SomeWork 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-c447fb302059784f-01 00:00:01.5236391
Example work done
設定 DefaultIdFormat 和 ForceDefaultIdFormat 為選擇性,但有助於確保範例在不同的 .NET 執行階段版本上產生類似的輸出。 .NET 5 預設會使用 W3C TraceContext 識別碼格式,但舊版 .NET 預設為使用 Hierarchical 識別碼格式。 如需詳細資訊,請參閱活動識別碼。
System.Diagnostics.ActivityListener 會用來在活動存留期期間接收回呼。
- ShouldListenTo - 每個活動都與 ActivitySource 相關聯,其可作為活動的命名空間和產生者。 此回呼會針對程序中的每個 ActivitySource 叫用一次。 如果您想要執行取樣或收到此來源所產生活動的啟動/停止事件通知,則會傳回 true。
- Sample - 根據預設,StartActivity 不會建立 Activity 物件,除非某些 ActivityListener 指出應該對其進行取樣。 傳回 AllDataAndRecorded 表示應該建立活動、IsAllDataRequested 應設定為 true,而且 ActivityTraceFlags 會設定 Recorded 旗標。 已檢測的程式碼會看到 IsAllDataRequested,這是接聽程式想要確保標籤和事件等輔助活動資訊已填入的提示。 Recorded 旗標會在 W3C TraceContext 識別碼中編碼,而且會提示分散式追蹤中包含的程序在此追蹤中取樣。
- ActivityStarted 和 ActivityStopped 會在分別啟動和停止活動時呼叫。 這些回呼會提供記錄活動相關資訊或可能修改活動的機會。 當活動剛啟動時,大部分的資料可能仍然不完整,而且會在活動停止之前填入。
建立 ActivityListener 並填入回呼之後,呼叫 ActivitySource.AddActivityListener(ActivityListener) 會起始叫用回呼。 呼叫 ActivityListener.Dispose() 以停止回呼的流程。 請注意,在多執行緒程式碼中,您可能會在執行 Dispose()
時或甚至在其傳回後不久,收到進行中的回呼通知。