Pojęcia dotyczące śledzenia rozproszonego w .NET
Śledzenie rozproszone to technika diagnostyczna, która ułatwia inżynierom lokalizowanie błędów i problemów z wydajnością w aplikacjach, zwłaszcza tych, które mogą być dystrybuowane na wielu maszynach lub procesach. Zapoznaj się z Omówieniem Śledzenia Rozproszonego, aby uzyskać ogólne informacje na temat ogólnych zastosowań śledzenia rozproszonego.
Ślady i działania
Przy każdym odbiorze nowego żądania przez aplikację, można je skojarzyć z konkretnym śladem. W składnikach aplikacji napisanych na platformie .NET jednostki pracy w ramach śladu są reprezentowane przez wystąpienia System.Diagnostics.Activity, a ślad jako całość tworzy drzewo takich działań, potencjalnie obejmującego wiele różnych procesów. Pierwsza czynność utworzona dla nowego żądania tworzy korzeń drzewa śledzenia i śledzi ogólny czas trwania oraz sukces lub porażkę w obsłudze żądania. Można opcjonalnie tworzyć działania podrzędne, aby podzielić pracę na różne kroki, które można śledzić indywidualnie. Na przykład, biorąc pod uwagę działanie, które śledziło określone przychodzące żądanie HTTP na serwerze internetowym, można utworzyć działania podrzędne w celu śledzenia każdego zapytania bazy danych, które były niezbędne do ukończenia żądania. Dzięki temu czas trwania i powodzenie każdego zapytania będą rejestrowane niezależnie. Działania mogą rejestrować inne informacje dla każdej jednostki pracy, takie jak OperationName, pary nazw-wartości nazywane Tagsi Events. Nazwa identyfikuje typ wykonywanej pracy, tagi mogą rejestrować opisowe parametry pracy, a zdarzenia są prostym mechanizmem rejestrowania do rejestrowania komunikatów diagnostycznych ze znacznikami czasu.
Uwaga
Inną typową nazwą branżową jednostek pracy w śladach rozproszonych jest "Spans". Platforma .NET przyjęła termin „Activity” wiele lat temu, zanim nazwa „Span” została dobrze ugruntowana dla tej koncepcji.
Identyfikatory działań
Parent-Child relacje między działaniami w rozproszonym drzewie śledzenia są ustanawiane przy użyciu unikatowych identyfikatorów. Implementacja śledzenia rozproszonego platformy .NET obsługuje dwa schematy identyfikatorów: standard W3C TraceContext, który jest domyślny w .NET 5+, oraz starszą konwencję platformy .NET zwaną "Hierarchiczna", która jest dostępna w celu zapewnienia zgodności z poprzednimi wersjami. Activity.DefaultIdFormat określa, który schemat identyfikatorów jest używany. W standardzie TraceContext W3C, każdemu śladowi przypisany jest globalnie unikatowy 16-bajtowy identyfikator śladu (Activity.TraceId), a każdej aktywności w ramach śladu przypisany jest unikatowy 8-bajtowy identyfikator span (Activity.SpanId). Każda aktywność rejestruje identyfikator śledzenia (trace-id), własny identyfikator zakresu (span-id) oraz identyfikator zakresu elementu nadrzędnego (parent span-id) (Activity.ParentSpanId). Ponieważ rozproszone ślady mogą śledzić pracę w granicach procesu, działania nadrzędne i podrzędne mogą nie być w tym samym procesie. Kombinacja identyfikatora śledzenia i nadrzędnego identyfikatora span-id może jednoznacznie identyfikować aktywność nadrzędną globalnie, niezależnie od tego, w jakim procesie się znajduje.
Activity.DefaultIdFormat kontroluje, który format identyfikatora jest używany do uruchamiania nowych śladów, ale domyślnie dodanie nowego działania do istniejącego śladu używa tego samego formatu, jaki jest używany przez nadrzędne działanie. Ustawienie wartości Activity.ForceDefaultIdFormat na true zastępuje to zachowanie i tworzy wszystkie nowe działania z DefaultIdFormat, nawet jeśli element nadrzędny korzysta z innego formatu identyfikatora.
Uruchamianie i zatrzymywanie działań
Każdy wątek w procesie może mieć odpowiedni obiekt Działania, który śledzi pracę wykonaną w tym wątku, dostępny za pośrednictwem Activity.Current. Obecna aktywność automatycznie przemieszcza się wzdłuż wszystkich synchronicznych wywołań na wątku i śledzi asynchroniczne wywołania przetwarzane na różnych wątkach. Jeśli działanie A jest bieżącym działaniem w wątku, a kod uruchamia nowe działanie B, B staje się nowym bieżącym działaniem w tym wątku. Domyślnie Działanie B będzie również traktować Działanie A jako element nadrzędny. Gdy działanie B zostanie później zatrzymane, działanie A zostanie przywrócone jako bieżące działanie w wątku. Po uruchomieniu aktywności rejestrowany jest bieżący czas jako Activity.StartTimeUtc. Gdy się zatrzyma, Activity.Duration jest obliczana jako różnica między bieżącym czasem a czasem rozpoczęcia.
Koordynacja pomiędzy granicami procesów
Aby śledzić pracę przez granice procesów, Identyfikatory nadrzędne Aktywności muszą być przesyłane przez sieć, aby proces odbiorczy mógł tworzyć Aktywności odwołujące się do nich. W przypadku korzystania z formatu identyfikatora TraceContext W3C platforma .NET używa również nagłówków HTTP zalecanych przez standardowego do przesyłania tych informacji. W przypadku korzystania z formatu identyfikatora Hierarchical platforma .NET używa niestandardowego nagłówka HTTP identyfikatora żądania do przesyłania identyfikatora. W przeciwieństwie do wielu innych środowisk uruchomieniowych języka, biblioteki dostępne w ramach platformy .NET, takie jak serwer internetowy ASP.NET i System.Net.Http, natywnie rozumieją, jak dekodować i kodować identyfikatory aktywności w komunikatach HTTP. Środowisko uruchomieniowe wie również, jak przekazywać identyfikator przez wywołania synchroniczne i asynchroniczne. Oznacza to, że aplikacje platformy .NET, które odbierają i emitują komunikaty HTTP, uczestniczą w automatycznym przepływie rozproszonych identyfikatorów śledzenia bez specjalnego kodowania przez dewelopera aplikacji ani zależności bibliotek innych firm. Biblioteki innych firm mogą dodać obsługę przesyłania identyfikatorów za pośrednictwem protokołów komunikatów innych niż HTTP lub obsługi niestandardowych konwencji kodowania dla protokołu HTTP.
Zbieranie śladów
Instrumentowany kod może tworzyć obiekty Activity w ramach rozproszonego śledzenia, ale informacje w tych obiektach muszą być przesyłane i serializowane w scentralizowanym magazynie trwałym, aby cały ślad można było przejrzeć później. Istnieje kilka bibliotek kolekcji danych telemetrycznych, które mogą wykonać to zadanie, takie jak Application Insights, OpenTelemetrylub biblioteka dostarczana przez dostawcę telemetrii innej firmy lub dostawcy APM. Alternatywnie deweloperzy mogą tworzyć niestandardowe kolekcje telemetrii aktywności przy użyciu System.Diagnostics.ActivityListener lub System.Diagnostics.DiagnosticListener. Element ActivityListener obsługuje obserwowanie dowolnego działania niezależnie od tego, czy deweloper ma wcześniejszą wiedzę na ten temat. Dzięki temu element ActivityListener jest prostym i elastycznym rozwiązaniem ogólnego przeznaczenia. Natomiast użycie DiagnosticListener jest bardziej złożonym scenariuszem, który wymaga, aby instrumentowany kod zdecydował się na aktywację przez wywołanie DiagnosticSource.StartActivity, a biblioteka kolekcji musi znać dokładne informacje o nazewnictwie używane przez instrumentowany kod podczas jego uruchamiania. Użycie elementu DiagnosticSource i DiagnosticListener umożliwia twórcy i odbiornikowi wymianę dowolnych obiektów platformy .NET i ustanowienie niestandardowych konwencji przekazywania informacji.
Pobieranie próbek
Aby uzyskać lepszą wydajność w aplikacjach o wysokiej przepływności, śledzenie rozproszone na platformie .NET obsługuje próbkowanie tylko podzestaw śladów, a nie rejestrowanie wszystkich z nich. W przypadku działań utworzonych przy użyciu zalecanego interfejsu API ActivitySource.StartActivity biblioteki zbierające dane telemetryczne mogą kontrolować próbkowanie za pomocą wywołania zwrotnego ActivityListener.Sample. Biblioteka rejestrowania może w ogóle nie tworzyć działania, stworzyć je z minimalnymi informacjami niezbędnymi do propagowania identyfikatorów śledzenia rozproszonego lub wypełnić je pełnymi informacjami diagnostycznymi. Te wybory stanowią kompromis między większym obciążeniem wydajności a zwiększeniem użyteczności diagnostycznej. Działania, które zaczynają korzystać ze starszego wzorca wywoływania Activity.Activity i DiagnosticSource.StartActivity, mogą również obsługiwać próbkowanie DiagnosticListener, wywołując najpierw DiagnosticSource.IsEnabled. Nawet przy przechwytywaniu pełnych informacji diagnostycznych implementacja platformy .NET jest zaprojektowana w taki sposób, aby była szybka, w połączeniu z wydajnym kolektorem, Aktywność można utworzyć, wypełnić i przekazać w około mikrosekundę na nowoczesnym sprzęcie. Próbkowanie może zmniejszyć koszt instrumentacji do mniej niż 100 nanosekund dla każdego nie zarejestrowanego działania.
Następne kroki
Aby na przykład rozpocząć korzystanie ze śledzenia rozproszonego w aplikacjach .NET, zobacz Distributed Tracing Instrumentation.
Aby uzyskać listę działań emitowanych natywnie przez platformę .NET, zobacz Wbudowane działania na platformie .NET.