Sdílet prostřednictvím


Distribuované trasování v knihovnách System.Net

Distribuované trasování je diagnostická technika, která technikům pomáhá lokalizovat chyby a problémy s výkonem v aplikacích, zejména v těch, které jsou rozloženy na více počítačů nebo procesů. Tato technika sleduje požadavky prostřednictvím aplikace tím, že vzájemně korelací práce prováděnou různými komponentami a odděluje je od jiné práce, kterou může aplikace provádět pro souběžné požadavky. Například požadavek na typickou webovou službu může nejprve přijímat nástroj pro vyrovnávání zatížení a pak se přeposlat na proces webového serveru, který pak provede několik dotazů do databáze. Distribuované trasování umožňuje technikům rozlišit, jestli některý z těchto kroků selhal a jak dlouho jednotlivé kroky trvaly. Může také protokolovat zprávy vytvořené jednotlivými kroky při spuštění.

Trasovací systém v .NET je navržený tak, aby fungoval s OpenTelemetry (OTel) a používá OTel k exportu dat do monitorovacích systémů. Trasování v rozhraní .NET se implementuje pomocí rozhraní API System.Diagnostics, kde je jednotka práce reprezentována třídou System.Diagnostics.Activity, která odpovídá OTel úseku. OpenTelemetry definuje standardní schéma pojmenování pro rozsahy (aktivity) společně s jejich atributy (značky), označované jako sémantické konvence. Telemetrie .NET používá existující sémantické konvence, kdykoli je to možné.

Poznámka

Termíny zahrnují a aktivity jsou synonymem v tomto článku. V kontextu kódu .NET odkazují na instanci System.Diagnostics.Activity. Nezaměňujte rozpětí OTel s System.Span<T>.

Spropitné

Úplný seznam všech předdefinovaných aktivit společně se značkami a atributy najdete v tématu předdefinované aktivity v rozhraní .NET.

Instrumentace

Pro generování trasování jsou knihovny System.Netinstrumentované s integrovanými zdroji ActivitySource, které vytvářejí objekty Activity ke sledování provedené práce. Aktivity se vytvářejí pouze v případě, že se k odběru ActivitySourcepřihlásí posluchači.

Integrovaná instrumentace se vyvinula s verzemi .NET.

  • V .NET 8 a starších verzích je instrumentace omezena pouze na vytvoření prázdné aktivity požadavku HTTP klienta . To znamená, že uživatelé musejí spoléhat na knihovnu OpenTelemetry.Instrumentation.Http k naplnění aktivity informacemi (například značkami) potřebnými k generování užitečných stop.
  • .NET 9 rozšířil instrumentaci generováním názvu, stavu, informací o výjimce a nejdůležitějších značek podle sémantických konvencí klienta HTTP aktivitě požadavku klienta HTTP. To znamená, že na platformě .NET 9 nebo novější lze vynechat závislost OpenTelemetry.Instrumentation.Http, pokud nejsou vyžadovány pokročilejší funkce, jako je obohacení .
  • Rozhraní .NET 9 také zavedlo experimentální trasování připojení, přidávání nových aktivit napříč knihovnami System.Net za účelem podpory diagnostiky problémů s připojením.

Shromažďujte trasování System.Net

Na nejnižší úrovnije kolekce trasování podporována prostřednictvím metody AddActivityListener, která registruje ActivityListener objekty obsahující uživatelsky definovanou logiku.

Jako vývojář aplikací byste ale pravděpodobně chtěli spoléhat na bohatý ekosystém založený na funkcích poskytovaných sadou OpenTelemetry .NET SDK ke shromažďování, exportu a monitorování trasování.

  • Chcete-li získat základní znalosti o sběru tras pomocí OTel, podívejte se na naši příručku k sběru tras pomocí OpenTelemetry.
  • Pro shromažďování a monitorování trasování v produkčním prostředí můžete použít OpenTelemetry s Prometheus, Grafana a Jaeger nebo s Azure Monitor a Application Insights. Tyto nástroje jsou ale poměrně složité a mohou být nevhodné k použití v době vývoje.
  • Pro shromažďování a monitorování trasování v době vývoje doporučujeme použít platformu .NET Aspire, které poskytuje jednoduchý, ale rozšiřitelný způsob, jak začít v aplikaci s distribuovaným trasováním a diagnostikovat problémy lokálně.
  • Je také možné opakovaně používat projekt výchozích hodnot služby Aspire bez orchestrace Aspire. Toto je užitečný způsob, jak v projektech ASP.NET představit a nakonfigurovat trasování a metriky OpenTelemetry.

Shromažďování trasování pomocí .NET Aspire

Shromažďovat stopy a metriky v ASP.NET aplikacích je jednoduché pomocí .NET Aspire. .NET Aspire je sada rozšíření .NET, která usnadňují vytváření a práci s distribuovanými aplikacemi. Jednou z výhod použití rozhraní .NET Aspire je, že telemetrie je integrovaná pomocí knihoven OpenTelemetry pro .NET.

Výchozí šablony projektů pro .NET Aspire obsahují ServiceDefaults projekt. Každá služba v řešení .NET Aspire má odkaz na projekt Výchozí služby. Služby ji používají k nastavení a konfiguraci OTelu.

Šablona projektu Výchozí nastavení služby zahrnuje balíčky OTel SDK, ASP.NET, HttpClient a Runtime Instrumentation. Tyto komponenty instrumentace jsou nakonfigurovány v souboru Extensions.cs. Pro podporu vizualizace telemetrie na řídicím panelu Aspire zahrnuje projekt Výchozí nastavení služby také ve výchozím nastavení exportér OTLP.

Řídicí panel Aspire je navržený tak, aby do místního ladicího cyklu přinesl pozorování telemetrie, což vývojářům umožňuje zajistit, aby aplikace vytvářely telemetrii. Vizualizace telemetrie také pomáhá diagnostikovat tyto aplikace místně. Schopnost sledovat volání mezi službami je stejně užitečná v době ladění jako v produkčním prostředí. Řídicí panel .NET Aspire se spustí automaticky při F5 projektu AppHost ze sady Visual Studio nebo dotnet run projektu AppHost z příkazového řádku.

řídicího panelu Aspire

Další informace o rozhraní .NET Aspire najdete tady:

Opětovné použití projektu Service Defaults bez orchestrace .NET Aspire

Projekt Aspire Service Defaults poskytuje snadný způsob konfigurace OTel pro ASP.NET projekty, i v případě, že nepoužíváte zbytek rozhraní .NET Aspire, jako je AppHost pro orchestraci. Projekt Výchozí nastavení služby je k dispozici jako šablona projektu prostřednictvím sady Visual Studio nebo dotnet new. Nakonfiguruje OTel a nastaví vývozce OTLP. Pak můžete použít proměnné prostředí OTel ke konfiguraci koncového bodu OTLP, kam budete odesílat telemetrii, a k zadání vlastností prostředků pro aplikaci.

Postup použití ServiceDefaults mimo rozhraní .NET Aspire:

  1. Přidejte do řešení projekt ServiceDefaults pomocí příkazu Přidat nový projekt v sadě Visual Studio nebo použijte dotnet new:

    dotnet new aspire-servicedefaults --output ServiceDefaults
    
  2. Odkazujte na projekt ServiceDefaults z aplikace ASP.NET. Ve Visual Studio vyberte Přidat>referenci projektu a vyberte projekt ServiceDefaults.

  3. Jako součást inicializace tvůrce aplikací volejte funkci nastavení OpenTelemetry ConfigureOpenTelemetry().

    var builder = WebApplication.CreateBuilder(args)
    builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults.
    var app = builder.Build();
    app.MapGet("/", () => "Hello World!");
    app.Run();
    

Úplný návod najdete v Příklad: Použití OpenTelemetry s OTLP a samostatného řídicího panelu Aspire.

Experimentální sledování připojení

Při řešení problémů s HttpClient nebo úzkými místy může být důležité zjistit, kde se tráví čas při odesílání požadavků HTTP. Často k problému dochází během navázání připojení HTTP, které se obvykle rozdělí na vyhledávání DNS, připojení TCP a TLS handshake.

.NET 9 zavedl experimentální trasování připojení, které přidává úsek HTTP connection setup se třemi podřízenými úseky představujícími fáze DNS, TCP a TLS při navázání připojení. Část sledování připojení v HTTP je implementována v rámci SocketsHttpHandler, což znamená, že model aktivity musí respektovat základní chování sdružování připojení.

Poznámka

V SocketsHttpHandlermají připojení a požadavky nezávislé životní cykly. Připojení ve fondu může fungovat po dlouhou dobu a obsluhovat mnoho požadavků. Pokud při vytváření požadavku není v fondu připojení okamžitě k dispozici žádné připojení, přidá se požadavek do fronty žádostí, aby čekal na dostupné připojení. Mezi čekajícími požadavky a připojeními neexistuje žádný přímý vztah. Proces připojení mohl být zahájen, když bylo k dispozici jiné připojení k použití, v takovém případě se použije uvolněné připojení. Výsledkem je, že rozsah HTTP connection setup není modelován jako podřízený rozsah HTTP client request; místo toho se používají odkazy span.

.NET 9 zavedl následující rozsahy, které umožňují shromažďování podrobných informací o připojení:

Jméno ActivitySource Popis
HTTP wait_for_connection Experimental.System.Net.Http.Connections Podřízený rozsah rozsahu HTTP client request, který představuje časový interval, během kterého požadavek čeká na dostupné připojení ve frontě požadavků.
HTTP connection_setup Experimental.System.Net.Http.Connections Představuje vytvoření připojení HTTP. Samostatný úsek kořene sledování s vlastním TraceId. HTTP client request rozsahy mohou obsahovat odkazy na HTTP connection_setup.
DNS lookup Experimental.System.Net.NameResolution Vyhledávání DNS prováděné třídou Dns.
socket connect Experimental.System.Net.Sockets Zřízení Socket spojení.
TLS handshake Experimental.System.Net.Security Handshake klienta nebo serveru TLS provedený SslStream.

Poznámka

Odpovídající názvy ActivitySource začínají předponou Experimental, protože tyto rozsahy mohou být změněny v budoucích verzích, jakmile se dozvíme více o tom, jak dobře fungují při použití v praxi.

Tyto rozsahy jsou příliš podrobné pro použití 24x7 v produkčních scénářích s vysokými úlohami – jsou hlučné a tato úroveň instrumentace není normálně nutná. Pokud se ale pokoušíte diagnostikovat problémy s připojením nebo získat hlubší přehled o tom, jak latence sítě a připojení ovlivňují vaše služby, poskytují přehledy, které je obtížné shromáždit jinými prostředky.

Pokud je povolen Experimental.System.Net.Http.Connections ActivitySource, rozsah HTTP client request obsahuje odkaz na rozsah HTTP connection_setup odpovídající připojení, obsluhující žádosti. Vzhledem k tomu, že připojení HTTP může být dlouhodobé, může to vést k mnoha odkazům na dobu trvání připojení z každé požadované aktivity. Některé monitorovací nástroje APM agresivně procházejí odkazy mezi částmi, aby vytvořily svá zobrazení, a proto zahrnutí této části může způsobit potíže, když nástroje nebyly navrženy tak, aby zpracovávaly velký počet odkazů.

Následující diagram znázorňuje chování rozsahů a jejich vztahů:

Připojení se v průběhu času zasahuje.

Návod: Použití experimentálního trasování připojení v .NET 9

Tento návod používá .NET 9 Aspire Starter App k předvedení trasování připojení, ale mělo by být snadné nastavit jej i s dalšími monitorovacími nástroji. Klíčovým krokem je povolení zdrojů aktivit.

  1. Pomocí dotnet newvytvořte startovací aplikaci .NET Aspire 9:

    dotnet new aspire-starter-9 --output ConnectionTracingDemo
    

    Nebo v prostředí Visual Studio:

    Vytvořte úvodní aplikaci .NET Aspire 9 ve Visual Studiu

  2. Otevřete Extensions.cs v projektu ServiceDefaults a upravte metodu ConfigureOpenTelemetry přidáním ActivitySources pro připojení ve zpětném volání konfigurace trasování.

    .WithTracing(tracing =>
    {
        tracing.AddAspNetCoreInstrumentation()
            // Instead of using .AddHttpClientInstrumentation()
            // .NET 9 allows to add the ActivitySources directly.
            .AddSource("System.Net.Http")
            // Add the experimental connection tracking ActivitySources using a wildcard.
            .AddSource("Experimental.System.Net.*");
    });
    
  3. Spusťte řešení. Tím by se měl otevřít .NET Aspire řídicí panel .

  4. Přejděte na stránku Počasí aplikace webfrontend a vygenerujte žádost HttpClient směrem k apiservice.

  5. Vraťte se na řídicí panel a přejděte na stránku Stopy. Otevřete trasování webfrontend: GET /weather.

    Spans HttpClient v řídicím panelu Aspire

Když provádíte požadavky HTTP s povolenou instrumentací připojení, měli byste vidět následující změny v požadavcích klientských:

  • Pokud je potřeba navázat připojení nebo pokud aplikace čeká na připojení z fondu připojení, zobrazí se další ukazatel HTTP wait_for_connection, který představuje zpoždění při čekání na připojení. To pomáhá pochopit zpoždění mezi tím, kdy je požadavek HttpClient prováděn v kódu, a kdy skutečně začíná zpracování požadavku. Na předchozím obrázku:
    • Vybraný rozsah je požadavek HttpClient.
    • Následující rozsah představuje dobu, po kterou požadavek stráví čekáním na navázání připojení.
    • Poslední žlutý úsek pochází ze zpracování požadavku v cílovém místě.
  • Rozsah HttpClient bude obsahovat odkaz na rozsah HTTP connection_setup, který představuje aktivitu pro vytvoření připojení HTTP používaného požadavkem.

Nastavení připojení v řídicím panelu Aspire

Jak bylo zmíněno dříve, rozsah HTTP connection_setup je samostatný rozsah s vlastními TraceId, protože jeho životnost je nezávislá na jednotlivých požadavcích klientů. Tento rozsah má obvykle podřízené rozsahy DNS lookup, (TCP) socket connecta TLS client handshake.

Obohacení

V některých případech je nutné rozšířit stávající funkce trasování System.Net. Obvykle to znamená vložení dalších značek nebo atributů do předdefinovaných aktivit. To se nazývá rozšiřování.

Rozhraní API pro obohacování v knihovně instrumentace OpenTelemetry

Pokud chcete do aktivity požadavku klienta HTTP přidat další značky nebo atributy, nejjednodušším přístupem je použít rozhraní API pro rozšiřování HttpClient knihovny instrumentace OpenTelemetry HttpClient a HttpWebRequest. To vyžaduje použití závislosti na balíčku OpenTelemetry.Instrumentation.Http.

Ruční obohacování

Rozšíření aktivity HTTP client request je možné implementovat ručně. K tomu potřebujete přístup k Activity.Current v kódu, který běží v oboru aktivity žádosti, před dokončením aktivity. Toto lze provést implementací IObserver<DiagnosticListener> a přihlášením tohoto prvku k AllListeners, abyste získali zpětná volání, když probíhá síťová aktivita. Ve skutečnosti je to způsob implementace instrumentační knihovny OpenTelemetry HttpClient a HttpWebRequest. Jako příklad kódu uvidíte kód předplatného v DiagnosticSourceSubscriber.cs a základní implementaci v HttpHandlerDiagnosticListener.cs, kam jsou delegována oznámení.

Potřebujete další trasování?

Pokud máte návrhy na další užitečné informace, které by mohly být odhaleny trasováním, vytvořte požadavek v dotnet/runtime.