Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makale şunlar için geçerlidir: ✔️ .NET Core 2.1 ve sonraki sürümleri ✔️ .NET Framework 4.5 ve sonraki sürümleri
.NET uygulamaları, dağıtılmış izleme telemetrisi System.Diagnostics.Activity oluşturmak için API kullanılarak izlenebilir. Bazı izlemeler standart .NET kitaplıklarında yerleşiktir, ancak kodunuzu daha kolay tanınabilir hale getirmek için daha fazlasını eklemek isteyebilirsiniz. Bu eğitimde, yeni özel dağıtılmış izleme araçları ekleyeceksiniz. Bu araç tarafından üretilen telemetri kaydı hakkında daha fazla bilgi edinmek için koleksiyon öğreticisine bakın.
Önkoşullar
- .NET Core 2.1 SDK veya sonraki bir sürüm
İlk uygulamayı oluşturma
İlk olarak, OpenTelemetry kullanarak telemetri toplayan ancak henüz herhangi bir izlemesi olmayan örnek bir uygulama oluşturacaksınız.
dotnet new console
.NET 5 ve üzerini hedefleyen uygulamalar zaten gerekli dağıtılmış izleme API'lerine sahiptir. Eski .NET sürümlerini hedefleyen uygulamalar için System.Diagnostics.DiagnosticSource NuGet paketi sürüm 5 veya üzerini ekleyin. Netstandard'ı hedefleyen kitaplıklar için, paketin hala desteklenen ve kitaplığınızın ihtiyaç duyduğu API'leri içeren en eski sürümüne başvurmanızı öneririz.
dotnet add package System.Diagnostics.DiagnosticSource
Telemetriyi toplamak için kullanılacak OpenTelemetry ve OpenTelemetry.Exporter.Console NuGet paketlerini ekleyin.
dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.Console
Oluşturulan Program.cs içeriğini şu örnek kaynakla değiştirin:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System;
using System.Threading.Tasks;
namespace Sample.DistributedTracing
{
class Program
{
static async Task Main(string[] args)
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample"))
.AddSource("Sample.DistributedTracing")
.AddConsoleExporter()
.Build();
await DoSomeWork("banana", 8);
Console.WriteLine("Example work done");
}
// All the functions below simulate doing some arbitrary work
static async Task DoSomeWork(string foo, int bar)
{
await StepOne();
await StepTwo();
}
static async Task StepOne()
{
await Task.Delay(500);
}
static async Task StepTwo()
{
await Task.Delay(1000);
}
}
}
Uygulamanın henüz herhangi bir izleme aracı yok, bu yüzden görüntülenecek iz bilgisi yok.
> dotnet run
Example work done
En iyi yöntemler
Bu örnekteki OpenTelemetry gibi dağıtılmış izleme telemetrisini toplamak için yalnızca uygulama geliştiricilerin isteğe bağlı bir üçüncü taraf kitaplığına başvurması gerekir. .NET kitaplık yazarları, .NET çalışma zamanının bir parçası olan System.Diagnostics.DiagnosticSource'taki API'leri özel olarak kullanabilir. Bu, uygulama geliştiricisinin telemetri toplamak için hangi kitaplığı veya satıcıyı kullanacağı konusunda tercihlerinden bağımsız olarak kitaplıkların çok çeşitli .NET uygulamalarında çalışmasını sağlar.
Temel enstrümantasyon ekleme
Uygulamalar ve kitaplıklar, dağıtılmış izleme araçlarını System.Diagnostics.ActivitySource ve System.Diagnostics.Activity sınıflarını kullanarak ekler.
ActivitySource
İlk olarak activitysource örneğini oluşturun. ActivitySource, Activity nesnelerini oluşturmak ve başlatmak için API'ler sağlar. Yukarıdaki Main() ve using System.Diagnostics; yönergelerine static ActivitySource değişkenini using ekleyin.
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Sample.DistributedTracing
{
class Program
{
private static ActivitySource source = new ActivitySource("Sample.DistributedTracing", "1.0.0");
static async Task Main(string[] args)
{
// ...
En iyi yöntemler
ActivitySource'u bir kez oluşturun, statik değişkende depolayın ve gerektiğinde bu örneği kullanın. Her kitaplık veya kitaplık alt bileşeni kendi kaynağını oluşturabilir (ve genellikle oluşturmalıdır). Uygulama geliştiricilerinin kaynaklarda Etkinlik telemetrisini bağımsız olarak etkinleştirip devre dışı bırakabilmeyi takdir edeceğini düşünüyorsanız, mevcut bir kaynağı yeniden kullanmak yerine yeni bir kaynak oluşturmayı göz önünde bulundurun.
Oluşturucuya geçirilen kaynak adı, diğer kaynaklarla çakışmaları önlemek için benzersiz olmalıdır. Aynı derleme içinde birden çok kaynak varsa, derleme adını ve isteğe bağlı olarak bir bileşen adını içeren hiyerarşik bir ad kullanın. Örneğin,
Microsoft.AspNetCore.Hosting. Bir derleme ikinci ve bağımsız bir derlemede kod için izleme ekliyorsa, adın kodu izlenen derlemeyi değil ActivitySource'u tanımlayan derlemeyi temel alması gerekir.Sürüm parametresi isteğe bağlıdır. Kitaplığın birden çok sürümünü serbest bırakmanız ve izlemeli telemetride değişiklik yapmanız durumunda sürümü sağlamanızı öneririz.
Uyarı
OpenTelemetry, alternatif 'tracer' ve 'Span' terimlerini kullanır. .NET'te 'ActivitySource', İzleme'nin uygulanmasıdır ve Etkinlik ise 'Span' uygulamasıdır. .NET'in Aktivite türü, OpenTelemetry belirtiminden çok önce ortaya çıkmış olup, .NET ekosistemi ve .NET uygulama uyumluluğu içinde tutarlılık sağlamak için özgün .NET adlandırması korunmaktadır.
Etkinlik
Etkinlik nesnelerini anlamlı iş birimleri etrafında başlatmak ve durdurmak için ActivitySource nesnesini kullanın. DoSomeWork() öğesini burada gösterilen kodla güncelleştirin:
static async Task DoSomeWork(string foo, int bar)
{
using (Activity activity = source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
}
}
Uygulamayı çalıştırdığınızda artık günlüğe kaydedilen yeni Etkinlik gösterilir:
> dotnet run
Activity.Id: 00-f443e487a4998c41a6fd6fe88bae644e-5b7253de08ed474f-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:36:51.4720202Z
Activity.Duration: 00:00:01.5025842
Resource associated with Activity:
service.name: MySample
service.instance.id: 067f4bb5-a5a8-4898-a288-dec569d6dbef
Notlar
ActivitySource.StartActivity etkinliği aynı anda oluşturur ve başlatır. Listelenen kod düzeni,
usingbloğunu kullanarak bloğu çalıştırdıktan sonra oluşturulan Activity nesnesini otomatik olarak yok eder. Activity nesnesinin atılması, nesneyi durdurur, bu yüzden kodun açıkça Activity.Stop() çağırmasına gerek yoktur. Bu, kodlama düzenini basitleştirir.ActivitySource.StartActivity etkinliği kaydeden dinleyici olup olmadığını dahili olarak belirler. Kayıtlı dinleyici yoksa veya ilgilenmeyen dinleyiciler varsa,
StartActivity()geri dönernullve Activity nesnesini oluşturmaktan kaçının. Bu, kod deseninin sık çağrılan işlevlerde kullanılmaya devam edebilmesi için bir performans iyileştirmesidir.
İsteğe bağlı: Etiketleri doldurma
Etkinlikler, işin tanılama için yararlı olabilecek parametrelerini depolamak için yaygın olarak kullanılan Etiketler adlı anahtar-değer verilerini destekler. Bunları dahil etmek için güncelleştirin DoSomeWork() :
static async Task DoSomeWork(string foo, int bar)
{
using (Activity activity = source.StartActivity("SomeWork"))
{
activity?.SetTag("foo", foo);
activity?.SetTag("bar", bar);
await StepOne();
await StepTwo();
}
}
> dotnet run
Activity.Id: 00-2b56072db8cb5a4496a4bfb69f46aa06-7bc4acda3b9cce4d-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:37:31.4949570Z
Activity.Duration: 00:00:01.5417719
Activity.TagObjects:
foo: banana
bar: 8
Resource associated with Activity:
service.name: MySample
service.instance.id: 25bbc1c3-2de5-48d9-9333-062377fea49c
Example work done
En iyi yöntemler
- Yukarıda belirtildiği gibi,
activitytarafından ActivitySource.StartActivity'e döndürülen değer null olabilir. C# dilindeki null birleşim işleci?.,activitynull değilse Activity.SetTag çağırmak için kullanışlı bir kısayoldur. Davranış, yazma işlemiyle aynıdır:
if(activity != null)
{
activity.SetTag("foo", foo);
}
OpenTelemetry, yaygın uygulama çalışması türlerini temsil eden Etkinliklerde Etiketler'i ayarlamak için bir dizi önerilen kural sağlar.
İşlevleri yüksek performanslı gereksinimlerle izliyorsanız, Activity.IsAllDataRequested Etkinlikler'i dinleyen kodlardan herhangi birinin Etiketler gibi yardımcı bilgileri okumayı amaçlayıp amaçlamadığını gösteren bir ipucudur. Eğer hiçbir dinleyici okumazsa, araçlı kodun üzerine CPU döngüleri harcamasına gerek yoktur. Kolaylık olması için bu örnek bu iyileştirmeyi uygulamaz.
İsteğe bağlı: Olay ekleme
Olaylar, Etkinliklere rastgele ek tanılama verileri akışı ekleyebilen zaman damgasına sahip iletilerdir. Etkinliğe bazı olaylar ekleyin:
static async Task DoSomeWork(string foo, int bar)
{
using (Activity activity = source.StartActivity("SomeWork"))
{
activity?.SetTag("foo", foo);
activity?.SetTag("bar", bar);
await StepOne();
activity?.AddEvent(new ActivityEvent("Part way there"));
await StepTwo();
activity?.AddEvent(new ActivityEvent("Done now"));
}
}
> dotnet run
Activity.Id: 00-82cf6ea92661b84d9fd881731741d04e-33fff2835a03c041-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:39:10.6902609Z
Activity.Duration: 00:00:01.5147582
Activity.TagObjects:
foo: banana
bar: 8
Activity.Events:
Part way there [3/18/2021 10:39:11 AM +00:00]
Done now [3/18/2021 10:39:12 AM +00:00]
Resource associated with Activity:
service.name: MySample
service.instance.id: ea7f0fcb-3673-48e0-b6ce-e4af5a86ce4f
Example work done
En iyi yöntemler
- Olaylar, iletilene kadar bellek içi bir listede depolanır ve bu da bu mekanizmayı yalnızca mütevazı sayıda olayın kaydedilmesi için uygun hale getirir. Büyük veya ilişkisiz bir olay hacmi için, ILogger gibi bu göreve odaklanan bir günlük API'sini kullanmak daha iyidir. ILogger ayrıca, uygulama geliştiricisinin dağıtılmış izlemeyi kullanmayı tercih edip etmediğine bakılmaksızın günlük bilgilerinin kullanılabilir olmasını sağlar. ILogger, etkin Etkinlik Kimliklerinin otomatik olarak yakalanmasını destekler, böylece bu API aracılığıyla günlüğe kaydedilen iletiler dağıtılmış izlemeyle yine de ilişkilendirilebilir.
İsteğe bağlı: Durum ekle
OpenTelemetry, her Etkinliğin çalışmanın başarılı/başarısız sonucunu temsil eden bir Durum bildirmesine olanak tanır. .NET'in bu amaçla kesin olarak belirlenmiş bir API'si vardır:
ActivityStatusCode değerleri ya Unset, Ok veya Error olarak temsil edilir.
Durumu ayarlamak için DoSomeWork() öğesini güncelleştirin:
static async Task DoSomeWork(string foo, int bar)
{
using (Activity activity = source.StartActivity("SomeWork"))
{
activity?.SetTag("foo", foo);
activity?.SetTag("bar", bar);
await StepOne();
activity?.AddEvent(new ActivityEvent("Part way there"));
await StepTwo();
activity?.AddEvent(new ActivityEvent("Done now"));
// Pretend something went wrong
activity?.SetStatus(ActivityStatusCode.Error, "Use this text give more information about the error");
}
}
İsteğe bağlı: Ek Etkinlikler ekleme
Etkinlikler, daha büyük bir iş biriminin bölümlerini açıklamak için iç içe yerleştirilebilir. Bu, kodun hızlı yürütülmeyebilecek bölümleri veya belirli dış bağımlılıklardan gelen hataları daha iyi yerelleştirmek için değerli olabilir. Bu örnek her yöntemde bir Activity kullansa da, bunun nedeni yalnızca ek kodun en aza indirgenmiş olmasıdır. Daha büyük ve daha gerçekçi bir projede, her yöntemde bir Etkinlik kullanmak çok fazla ayrıntılı iz kaydı oluşturacağı için önerilmez.
Bu ayrı adımlar etrafında daha fazla izleme eklemek için StepOne ve StepTwo'yi güncelleştirin:
static async Task StepOne()
{
using (Activity activity = source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}
static async Task StepTwo()
{
using (Activity activity = source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
}
> dotnet run
Activity.Id: 00-9d5aa439e0df7e49b4abff8d2d5329a9-39cac574e8fda44b-01
Activity.ParentId: 00-9d5aa439e0df7e49b4abff8d2d5329a9-f16529d0b7c49e44-01
Activity.DisplayName: StepOne
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:40:51.4278822Z
Activity.Duration: 00:00:00.5051364
Resource associated with Activity:
service.name: MySample
service.instance.id: e0a8c12c-249d-4bdd-8180-8931b9b6e8d0
Activity.Id: 00-9d5aa439e0df7e49b4abff8d2d5329a9-4ccccb6efdc59546-01
Activity.ParentId: 00-9d5aa439e0df7e49b4abff8d2d5329a9-f16529d0b7c49e44-01
Activity.DisplayName: StepTwo
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:40:51.9441095Z
Activity.Duration: 00:00:01.0052729
Resource associated with Activity:
service.name: MySample
service.instance.id: e0a8c12c-249d-4bdd-8180-8931b9b6e8d0
Activity.Id: 00-9d5aa439e0df7e49b4abff8d2d5329a9-f16529d0b7c49e44-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:40:51.4256627Z
Activity.Duration: 00:00:01.5286408
Activity.TagObjects:
foo: banana
bar: 8
otel.status_code: ERROR
otel.status_description: Use this text give more information about the error
Activity.Events:
Part way there [3/18/2021 10:40:51 AM +00:00]
Done now [3/18/2021 10:40:52 AM +00:00]
Resource associated with Activity:
service.name: MySample
service.instance.id: e0a8c12c-249d-4bdd-8180-8931b9b6e8d0
Example work done
Hem StepOne'da hem de StepTwo'da SomeWork'e atıfta bulunan bir ParentId vardır, buna dikkat edin. Konsol, iç içe geçmiş iş ağaçlarının harika bir görselleştirmesi değildir, ancak Zipkin gibi birçok GUI görüntüleyici bunu Gantt grafiği olarak gösterebilir:
İsteğe bağlı: ActivityKind
Etkinlikler, etkinliğin, üst öğesi ve alt öğeleri arasındaki ilişkiyi açıklayan bir Activity.Kind özelliğine sahiptir. Varsayılan olarak, tüm yeni Etkinlikler Internal olarak ayarlanır ve bu, uzak üst veya alt öğe içermeyen bir uygulama içindeki dahili bir işlem olan Etkinlikler için uygundur. ActivitySource.StartActivity üzerinde kind parametresi kullanılarak diğer türler ayarlanabilir. Diğer seçenekler için bkz System.Diagnostics.ActivityKind. .
İsteğe bağlı: Bağlantılar
Toplu işleme sistemlerinde iş gerçekleştiğinde, tek bir Etkinlik aynı anda birçok farklı istek adına çalışmayı temsil edebilir ve bunların her birinin kendi izleme kimliği (trace-id) vardır. Etkinlik tek bir üst öğesi olacak şekilde sınırlandırılmış olsa da, System.Diagnostics.ActivityLink kullanarak ek izleme kimliklerine bağlanabilir. Her ActivityLink, bağlanılmakta olan Etkinlikle ilgili kimlik bilgilerini depolayan bir ActivityContext ile doldurulur. ActivityContext, işlem içindeyken Etkinlik nesnelerinden Activity.Context kullanılarak alınabilir veya serileştirilmiş kimlik bilgileri ActivityContext.Parse(String, String) kullanılarak ayrıştırılabilir.
void DoBatchWork(ActivityContext[] requestContexts)
{
// Assume each context in requestContexts encodes the trace-id that was sent with a request
using(Activity activity = s_source.StartActivity(name: "BigBatchOfWork",
kind: ActivityKind.Internal,
parentContext: default,
links: requestContexts.Select(ctx => new ActivityLink(ctx))
{
// do the batch of work here
}
}
Olaylar ve Etiketlerin isteğe bağlı olarak eklenebilmesine karşın, bağlantılar StartActivity() sırasında eklenmeli ve sonrasında değiştirilemez olmalıdır.
Önemli
OpenTelemetry belirtimine göre, bağlantı sayısı için önerilen sınır 128'dir. Ancak, bu sınırın uygulanmadığını unutmayın.