Erfassen einer verteilten Ablaufverfolgung
Dieser Artikel gilt für: ✔️ .NET Core 2.1 und höhere Versionen ✔️ .NET Framework 4.5 und höhere Versionen
Instrumentierter Code kann Activity-Objekte als Teil einer verteilten Ablaufverfolgung erstellen, aber die Informationen in diesen Objekten müssen in einem zentralen Speicher gesammelt werden, damit die gesamte Ablaufverfolgung später überprüft werden kann. In diesem Tutorial erfassen Sie verteilte Ablaufverfolgungstelemetrie auf unterschiedliche Weise, sodass sie bei Bedarf zur Diagnose von Anwendungsproblemen zur Verfügung steht. Wenn Sie eine neue Instrumentierung hinzufügen möchten, lesen Sie das Instrumentierungstutorial.
Erfassen von Ablaufverfolgungen mithilfe von OpenTelemetry
OpenTelemetry ist ein herstellerneutrales Open-Source-Projekt, das von der Cloud Native Computing Foundation unterstützt wird und zum Ziel hat, die Generierung und Erfassung von Telemetrie für cloudnative Software zu standardisieren. In diesen Beispielen sammeln Sie Informationen zur verteilten Ablaufverfolgung und zeigen sie auf der Konsole an. Um zu erfahren, wie Sie OpenTelemetry zum Senden von Informationen an andere Ziele konfigurieren, lesen Sie den Leitfaden zu den ersten Schritten mit OpenTelemetry.
ASP.NET-Beispiel
Voraussetzungen
- .NET Core 7.0 SDK oder höher
Erstellen einer Beispielanwendung
Erstellen Sie zuerst eine neue ASP.NET-Web-App, die als Demoanwendung verwendet werden soll.
dotnet new webapp
Diese App zeigt eine Webseite an, aber beim Durchsuchen der Seite werden noch keine verteilten Ablaufverfolgungsinformationen gesammelt.
Konfigurieren der Sammlung
Um OpenTelemetry zu verwenden, müssen Sie Verweise auf verschiedene NuGet-Pakete hinzufügen.
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
Hinweis
Als dieser Artikel verfasst wurde, war der Build „1.4.0 Release Candidate 1“ die neueste verfügbare Version von OpenTelemetry. Wenn eine endgültige Version verfügbar ist, verwenden Sie diese.
Ändern Sie als Nächstes den Quellcode in Program.cs folgendermaßen:
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();
Führen Sie die App aus, und navigieren Sie in einem Webbrowser zu der Webseite, die gehostet wird. Nachdem Sie die verteilte OpenTelemetry-Ablaufverfolgung aktiviert haben, sollten in der Konsole Informationen zu den Browserwebanforderungen ausgegeben werden:
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
Die gesamte OpenTelemetry-Konfiguration erfolgt in den neuen Quellzeilen, die mit builder.Services.AddOpenTelemetry()
beginnen. Sie haben .WithTracing(...)
verwendet, um die verteilte Ablaufverfolgung zu aktivieren. AddAspNetCoreInstrumentation()
hat OpenTelemetry aktiviert, um alle Aktivitäten der verteilten Ablaufverfolgung zu sammeln, die vom ASP.NET Core-Webserver erzeugt werden, und AddConsoleExporter()
weist OpenTelemetry an, diese Informationen an die Konsole zu senden. Bei einer weniger trivialen App könnten Sie weitere Instrumentierungsbibliotheken hinzufügen, um auch die Ablaufverfolgung für Datenbankabfragen oder ausgehende HTTP-Anforderungen zu sammeln. In diesem Fall würden Sie auch die Konsolenexportfunktion durch eine Exportfunktion für Jaeger, Zipken oder einen anderen von Ihnen verwendeten Überwachungsdienst ersetzen.
Beispiel für Konsolen-App
Voraussetzungen
- .NET Core 2.1 SDK oder höher
Erstellen einer Beispielanwendung
Bevor Telemetriedaten zur verteilten Ablaufverfolgung gesammelt werden kann, müssen Sie diese Daten generieren. Diese Instrumentierung befindet sich häufig in Bibliotheken, aber der Einfachheit halber werden Sie eine kleine App erstellen, die eine Beispielinstrumentierung mit StartActivity enthält. Zu diesem Zeitpunkt findet noch keine Erfassung statt, StartActivity() hat keinen Nebeneffekt und gibt NULL zurück. Weitere Details finden Sie im Instrumentierungstutorial.
dotnet new console
Anwendungen, die auf .NET 5 und höher ausgerichtet sind, verfügen bereits über die erforderlichen verteilten Ablaufverfolgungs-APIs. Fügen Sie für Apps, die auf ältere .NET-Versionen ausgelegt sind, das NuGet-Paket System.Diagnostics.DiagnosticSource (Version 5 oder höher) hinzu.
dotnet add package System.Diagnostics.DiagnosticSource
Ersetzen Sie den Inhalt der generierten Datei „Program.cs“ durch diesen Beispielquellcode:
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);
}
}
}
}
Wenn Sie die App ausführen, werden noch keine Ablaufverfolgungsdaten erfasst:
> dotnet run
Example work done
Konfigurieren der Sammlung
Fügen Sie das NuGet-Paket OpenTelemetry.Exporter.Console hinzu.
dotnet add package OpenTelemetry.Exporter.Console
Aktualisieren Sie „Program.cs“ mit zusätzlichen using
-Anweisungen von OpenTelemetry:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
Aktualisieren Sie Main()
, um den TracerProvider von OpenTelemetry zu erstellen:
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");
}
Nun erfasst die App verteilte Ablaufverfolgungsinformationen und zeigt sie in der Konsole an:
> 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
Quellen
Im Beispielcode haben Sie AddSource("Sample.DistributedTracing")
aufgerufen, damit OpenTelemetry die Aktivitäten erfasst, die von der bereits im Code vorhandenen ActivitySource generiert werden:
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
Telemetrie von einer beliebigen ActivitySource kann durch Aufruf von AddSource()
mit dem Namen der Quelle erfasst werden.
Exporter
Der Konsolenexporter ist hilfreich für schnelle Beispiele oder die lokale Entwicklung, aber in einer Produktionsbereitstellung möchten Sie wahrscheinlich Ablaufverfolgungen an einen zentralisierten Speicher senden. OpenTelemetry unterstützt eine Vielzahl von Zielen mit unterschiedlichen Exportern. Weitere Informationen zum Konfigurieren von OpenTelemetry finden Sie im Leitfaden zu den ersten Schritten mit OpenTelemetry.
Erfassen von Ablaufverfolgungen mit Application Insights
Verteilte Ablaufverfolgungstelemetrie wird automatisch nach der Konfiguration des Application Insights SDK (für Apps mit ASP.NET oder ASP.NET Core) oder durch Aktivierung von codefreier Instrumentierung erfasst.
Weitere Informationen finden Sie in der Application Insights-Dokumentation zur verteilten Ablaufverfolgung.
Hinweis
Derzeit unterstützt Application Insights nur das Erfassen einer bestimmten bekannten Aktivitätsinstrumentierung und ignoriert neue Aktivitäten, die vom Benutzer hinzugefügt werden. Application Insights bietet TrackDependency als herstellerspezifische API zum Hinzufügen benutzerdefinierter verteilter Ablaufverfolgungsinformationen.
Erfassen von Ablaufverfolgungen mit benutzerdefinierter Logik
Entwicklern steht es frei, eigene, angepasste Erfassungslogik für Aktivitäts-Ablaufverfolgungsdaten zu erstellen. Dieses Beispiel erfasst Telemetriedaten mithilfe der System.Diagnostics.ActivityListener-API, die von .NET bereitgestellt wird, und gibt sie in der Konsole aus.
Voraussetzungen
- .NET Core 2.1 SDK oder höher
Erstellen einer Beispielanwendung
Zunächst erstellen Sie eine Beispielanwendung, die über eine verteilte Ablaufverfolgungsinstrumentierung verfügt, bei der jedoch keine Ablaufverfolgungsdaten erfasst werden.
dotnet new console
Anwendungen, die auf .NET 5 und höher ausgerichtet sind, verfügen bereits über die erforderlichen verteilten Ablaufverfolgungs-APIs. Fügen Sie für Apps, die auf ältere .NET-Versionen ausgelegt sind, das NuGet-Paket System.Diagnostics.DiagnosticSource (Version 5 oder höher) hinzu.
dotnet add package System.Diagnostics.DiagnosticSource
Ersetzen Sie den Inhalt der generierten Datei „Program.cs“ durch diesen Beispielquellcode:
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);
}
}
}
}
Wenn Sie die App ausführen, werden noch keine Ablaufverfolgungsdaten erfasst:
> dotnet run
Example work done
Hinzufügen von Code zum Erfassen der Ablaufverfolgungen
Aktualisieren Sie Main() mit diesem Code:
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");
}
Die Ausgabe enthält jetzt Protokollierung:
> 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
Das Festlegen von DefaultIdFormat und ForceDefaultIdFormat ist optional, hilft aber sicherzustellen, dass das Beispiel mit verschiedenen .NET-Laufzeitversionen ähnliche Ausgaben generiert. .NET 5 verwendet standardmäßig das W3C-TraceContext-ID-Format, aber frühere .NET-Versionen verwenden standardmäßig das Hierarchical-ID-Format. Weitere Informationen finden Sie unter Aktivitäts-IDs.
System.Diagnostics.ActivityListener wird verwendet, um Rückrufe während der Lebensdauer einer Aktivität zu empfangen.
- ShouldListenTo: Jede Aktivität ist einer ActivitySource zugeordnet, die als Namespace und Producer fungiert. Dieser Rückruf wird ein Mal für jede ActivitySource im Prozess aufgerufen. Geben Sie TRUE zurück, wenn Sie daran interessiert sind, eine Stichprobenentnahme durchzuführen oder über Start-/Stoppereignisse für von dieser Quelle generierte Aktivitäten benachrichtigt zu werden.
- Sample: Standardmäßig erstellt StartActivity kein Activity-Objekt, es sei denn, ein ActivityListener gibt an, dass es erfasst werden soll. Die Rückgabe von AllDataAndRecorded gibt an, dass die Aktivität erstellt und IsAllDataRequested auf „true“ festgelegt soll, und ActivityTraceFlags legt das Recorded-Flag fest. IsAllDataRequested kann vom instrumentierten Code als Hinweis darauf beobachtet werden, dass ein Listener sicherstellen möchte, dass zusätzliche Aktivitätsinformationen wie Tags und Ereignisse mit Daten aufgefüllt werden. Das Recorded-Flag ist in der W3C-TraceContext-ID codiert und ein Hinweis für andere an der verteilten Ablaufverfolgung beteiligte Prozesse, dass diese Ablaufverfolgung erfasst werden soll.
- ActivityStarted und ActivityStopped werden aufgerufen, wenn eine Aktivität gestartet bzw. beendet wird. Diese Rückrufe bieten die Möglichkeit, relevante Informationen zur Aktivität aufzuzeichnen oder diese ggf. zu ändern. Wenn eine Aktivität gerade erst gestartet wurde, sind viele Daten möglicherweise noch unvollständig, und werden vor dem Beenden der Aktivität aufgefüllt.
Sobald ein ActivityListener erstellt wurde und die Rückrufe aufgefüllt werden, initiiert der Aufruf von ActivitySource.AddActivityListener(ActivityListener) das Aufrufen der Rückrufe. Rufen ActivityListener.Dispose() Sie auf, um den Fluss der Rückrufe zu beenden. Beachten Sie, dass in Multithreadcode aktuell ausgeführte Rückrufbenachrichtigungen empfangen werden können, während Dispose()
ausgeführt wird, oder sogar sehr kurz nach dessen Rückgabe.