Sdílet prostřednictvím


Příklad: Použití OpenTelemetry s prometheus, Grafana a Jaeger

Tento příklad používá Prometheus pro shromažďování metrik, Grafana k vytvoření řídicího panelu a Jaeger k zobrazení distribuovaného trasování.

1. Vytvoření projektu

Vytvořte jednoduchý projekt webového rozhraní API pomocí šablony ASP.NET Core Empty v sadě Visual Studio nebo pomocí následujícího příkazu .NET CLI:

dotnet new web

2. Přidání metrik a definic aktivit

Následující kód definuje novou metriku (greetings.count) pro počet volání rozhraní API a nový zdroj aktivity (OtPrGrYa.Example).

// Custom metrics for the application
var greeterMeter = new Meter("OtPrGrYa.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");

// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OtPrGrJa.Example");

3. Vytvoření koncového bodu rozhraní API

app.MapGet("/", SendGreeting);
async Task<String> SendGreeting(ILogger<Program> logger)
{
    // Create a new Activity scoped to the method
    using var activity = greeterActivitySource.StartActivity("GreeterActivity");

    // Log a message
    logger.LogInformation("Sending greeting");

    // Increment the custom counter
    countGreetings.Add(1);

    // Add a tag to the Activity
    activity?.SetTag("greeting", "Hello World!");

    return "Hello World!";
}

Poznámka:

Definice rozhraní API nepoužívá nic specifického pro OpenTelemetry. K pozorovatelnosti používá rozhraní .NET API.

4. Odkaz na balíčky OpenTelemetry

Pomocí Správce balíčků NuGetu nebo příkazového řádku přidejte následující balíčky NuGet:

<ItemGroup>
    <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.9.0-beta.2" />
    <PackageReference Include="OpenTelemetry.Exporter.Zipkin" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
</ItemGroup>

Poznámka:

Používejte nejnovější verze, protože se rozhraní API OTel neustále vyvíjejí.

5. Konfigurace OpenTelemetry se správnými poskytovateli

var tracingOtlpEndpoint = builder.Configuration["OTLP_ENDPOINT_URL"];
var otel = builder.Services.AddOpenTelemetry();

// Configure OpenTelemetry Resources with the application name
otel.ConfigureResource(resource => resource
    .AddService(serviceName: builder.Environment.ApplicationName));

// Add Metrics for ASP.NET Core and our custom metrics and export to Prometheus
otel.WithMetrics(metrics => metrics
    // Metrics provider from OpenTelemetry
    .AddAspNetCoreInstrumentation()
    .AddMeter(greeterMeter.Name)
    // Metrics provides by ASP.NET Core in .NET 8
    .AddMeter("Microsoft.AspNetCore.Hosting")
    .AddMeter("Microsoft.AspNetCore.Server.Kestrel")
    .AddPrometheusExporter());

// Add Tracing for ASP.NET Core and our custom ActivitySource and export to Jaeger
otel.WithTracing(tracing =>
{
    tracing.AddAspNetCoreInstrumentation();
    tracing.AddHttpClientInstrumentation();
    tracing.AddSource(greeterActivitySource.Name);
    if (tracingOtlpEndpoint != null)
    {
        tracing.AddOtlpExporter(otlpOptions =>
         {
             otlpOptions.Endpoint = new Uri(tracingOtlpEndpoint);
         });
    }
    else
    {
        tracing.AddConsoleExporter();
    }
});

Tento kód používá instrumentaci ASP.NET Core k získání metrik a aktivit z ASP.NET Core. Také zaregistruje a ActivitySource zprostředkovatele pro metriky Metrics a trasování.

Kód používá pro metriky exportér Prometheus, který k hostování koncového bodu používá ASP.NET Core, takže je potřeba přidat také:

// Configure the Prometheus scraping endpoint
app.MapPrometheusScrapingEndpoint();

6. Spusťte projekt.

Spusťte projekt a pak přejděte k rozhraní API pomocí prohlížeče nebo curl.

curl -k http://localhost:7275

Pokaždé, když požádáte o stránku, zvýší se počet provedených pozdravů. Ke koncovému bodu metrik můžete přistupovat pomocí stejné základní adresy URL s cestou /metrics.

6.1 Výstup protokolu

Příkazy protokolování z kódu jsou výstupem pomocí ILogger. Ve výchozím nastavení je poskytovatel konzoly povolený, aby se výstup směroval do konzoly.

Existuje několik možností, jak se protokoly dají výchozí přenos dat z .NET:

  • stdout a stderr výstup se přesměruje na soubory protokolů systémy kontejnerů, jako je Kubernetes.
  • Mezi knihovny protokolování, které se budou integrovat s ILoggerem, patří Serilog nebo NLog.
  • Použití zprostředkovatelů protokolování pro OTel, jako je OTLP nebo vývozce azure Monitoru, viz níže.

6.2 Přístup k metrikám

K metrikám můžete přistupovat pomocí koncového /metrics bodu.

curl -k https://localhost:7275/
Hello World!

curl -k https://localhost:7275/metrics
# TYPE greetings_count counter
# HELP greetings_count Counts the number of greetings
greetings_count 1 1686894204856

# TYPE current_connections gauge
# HELP current_connections Number of connections that are currently active on the server.
current_connections{endpoint="127.0.0.1:7275"} 1 1686894204856
current_connections{endpoint="[::1]:7275"} 0 1686894204856
current_connections{endpoint="[::1]:5212"} 1 1686894204856
...

Výstupem metrik je snímek metrik v době, kdy se koncový bod požaduje. Výsledky jsou poskytovány ve formátu expozice Prometheus, který je člověk čitelný, ale lépe pochopit Prometheus. Toto téma je popsáno v další fázi.

6.3 Přístup k trasování

Pokud se podíváte na konzolu pro server, zobrazí se výstup exportéru trasování konzoly, který vypíše informace v čitelné podobě člověka. Měla by se zobrazit dvě aktivity, jedna z vašich vlastních ActivitySourcea druhá z ASP.NET Core:

Activity.TraceId:            2e00dd5e258d33fe691b965607b91d18
Activity.SpanId:             3b7a891f55b97f1a
Activity.TraceFlags:         Recorded
Activity.ParentSpanId:       645071fd0011faac
Activity.ActivitySourceName: OtPrGrYa.Example
Activity.DisplayName:        GreeterActivity
Activity.Kind:               Internal
Activity.StartTime:          2023-06-16T04:50:26.7675469Z
Activity.Duration:           00:00:00.0023974
Activity.Tags:
    greeting: Hello World!
Resource associated with Activity:
    service.name: OTel-Prometheus-Grafana-Jaeger
    service.instance.id: e1afb619-bc32-48d8-b71f-ee196dc2a76a
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.5.0

Activity.TraceId:            2e00dd5e258d33fe691b965607b91d18
Activity.SpanId:             645071fd0011faac
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName:        /
Activity.Kind:               Server
Activity.StartTime:          2023-06-16T04:50:26.7672615Z
Activity.Duration:           00:00:00.0121259
Activity.Tags:
    net.host.name: localhost
    net.host.port: 7275
    http.method: GET
    http.scheme: https
    http.target: /
    http.url: https://localhost:7275/
    http.flavor: 1.1
    http.user_agent: curl/8.0.1
    http.status_code: 200
Resource associated with Activity:
    service.name: OTel-Prometheus-Grafana-Jaeger
    service.instance.id: e1afb619-bc32-48d8-b71f-ee196dc2a76a
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.5.0

První je vnitřní vlastní aktivita, kterou jste vytvořili. Druhý je vytvořen ASP.NET pro požadavek a obsahuje značky pro vlastnosti požadavku HTTP. Uvidíte, že oba mají stejnou TraceId, která identifikuje jednu transakci a v distribuovaném systému lze použít ke korelaci trasování z každé služby zapojené do transakce. ID se přenášejí jako hlavičky HTTP. ASP.NET Core přiřadí TraceId , pokud není k dispozici, když obdrží požadavek. HttpClient obsahuje záhlaví ve výchozím nastavení u odchozích požadavků. Každá aktivita má kombinaci SpanIdTraceId a SpanId jedinečně identifikuje jednotlivé aktivity. Aktivita Greeter je nadřazená aktivitě HTTP prostřednictvím jeho ParentSpanId, která se mapuje na SpanId aktivitu HTTP.

V pozdější fázi tato data předáte do Jaegeru, abyste mohli vizualizovat distribuované trasování.

7. Shromažďování metrik pomocí nástroje Prometheus

Prometheus je shromažďování metrik, agregace a databázový systém časových řad. Nakonfigurujete ho s koncovými body metriky pro každou službu a pravidelně se šrotují hodnoty a ukládají je v databázi časových řad. Pak je můžete analyzovat a zpracovávat podle potřeby.

Data metrik, která jsou zpřístupněná ve formátu Prometheus, jsou snímkem metrik procesu k určitému bodu v čase. Pokaždé, když se do koncového bodu metriky odešle požadavek, nahlásí aktuální hodnoty. Zatímco aktuální hodnoty jsou zajímavé, stávají se cennější v porovnání s historickými hodnotami, aby viděly trendy a zjistily, jestli jsou hodnoty neobvyklé. Služby mají obvykle špičky využití v závislosti na denním nebo světovém čase, jako je například nákupní špička svátků. Porovnáním hodnot s historickými trendy můžete zjistit, jestli jsou neobvyklé nebo jestli se metrika v průběhu času pomalu zhoršuje.

Tento proces neukládá žádnou historii těchto snímků metrik. Přidání této schopnosti do procesu může být náročné na prostředky. V distribuovaném systému máte také často více instancí každého uzlu, takže chcete mít možnost shromažďovat metriky ze všech uzlů a pak agregovat a porovnávat s jejich historickými hodnotami.

7.1 Instalace a konfigurace nástroje Prometheus

Stáhněte si Prometheus pro vaši platformu https://prometheus.io/download/ a extrahujte obsah stahování.

Podívejte se na začátek výstupu spuštěného serveru a získejte číslo portu pro koncový bod HTTP . Příklad:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:7275
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5212

Upravte konfigurační soubor YAML pro Prometheus tak, aby určil port koncového bodu pro výstřižky HTTP a nastavil nižší interval škrábání. Příklad:

  scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    scrape_interval: 1s # poll very quickly for a more responsive demo
    static_configs:
      - targets: ["localhost:5212"]

Spusťte Prometheus a vyhledejte výstup portu, na kterém běží, obvykle 9090:

>prometheus.exe
...
ts=2023-06-16T05:29:02.789Z caller=web.go:562 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090

Otevřete tuto adresu URL v prohlížeči. V uživatelském rozhraní Prometheus byste teď měli mít možnost dotazovat se na metriky. Pomocí zvýrazněného tlačítka na následujícím obrázku otevřete Průzkumníka metrik, který zobrazuje všechny dostupné metriky.

Průzkumník metrik Prometheus

Výběrem metriky greetings_count zobrazíte graf hodnot.

Graf greetings_count

8. Vytvoření řídicího panelu metrik pomocí Grafany

Grafana je produkt řídicího panelu, který může vytvářet řídicí panely a výstrahy založené na produktu Prometheus nebo jiných zdrojích dat.

Stáhněte a nainstalujte verzi OSS grafany podle https://grafana.com/oss/grafana/ pokynů pro vaši platformu. Po instalaci se Grafana obvykle spouští na portu 3000, takže otevřete http://localhost:3000 ho v prohlížeči. Budete se muset přihlásit; výchozí uživatelské jméno a heslo jsou oba admin.

V hamburgerové nabídce zvolte připojení a zadejte text prometheus , který vybere typ koncového bodu. Vyberte Vytvořit zdroj dat Prometheus a přidejte nový zdroj dat.

Připojení Grafany k prometheus

Musíte nastavit následující vlastnosti:

  • Adresa URL serveru Prometheus: http://localhost:9090/ změna portu podle potřeby

Výběrem možnosti Uložit a test ověřte konfiguraci.

Jakmile se zobrazí zpráva o úspěchu, můžete nakonfigurovat řídicí panel. Klikněte na odkaz pro vytvoření řídicího panelu zobrazený v místní nabídce pro zprávu o úspěchu.

Vyberte Přidat vizualizaci a pak zvolte zdroj dat Prometheus, který jste právě přidali jako zdroj dat.

Měl by se zobrazit návrhář panelu řídicího panelu. V dolní polovině obrazovky můžete definovat dotaz.

Dotaz Grafana s využitím greetings_count

Vyberte metriku greetings_count a pak výběrem možnosti Spustit dotazy zobrazte výsledky.

Grafana umožňuje navrhovat sofistikované řídicí panely, které budou sledovat libovolný počet metrik.

Každá metrika v .NET může mít další dimenze, což jsou páry klíč-hodnota, které je možné použít k rozdělení dat. Všechny metriky ASP.NET obsahují řadu dimenzí použitelných pro čítač. Například current-requests čítač z Microsoft.AspNetCore.Hosting má následující dimenze:

Atribut Typ Popis Příklady Přítomnost
method string Metoda požadavku HTTP. GET; POST; HEAD Always
scheme string Schéma identifikátoru URI identifikující použitý protokol. http; https Always
host string Název místního serveru HTTP, který obdržel požadavek. localhost Always
port int Port místního serveru HTTP, který obdržel požadavek. 8080 Přidání, pokud není výchozí (80 pro http nebo 443 pro https)

Grafy v Grafaně jsou obvykle rozdělené na základě každé jedinečné kombinace dimenzí. Dimenze lze použít v dotazech Grafana k filtrování nebo agregaci dat. Pokud například grafujete current_requests, zobrazí se hodnoty rozdělené na základě každé kombinace dimenzí. Pokud chcete filtrovat jenom na hostiteli, přidejte operaci Sum a použijte host ji jako hodnotu popisku.

Grafana current_requests podle hostitele

9. Distribuované trasování pomocí Jaegeru

V kroku 6 jste viděli, že distribuované informace o trasování byly zpřístupněny konzole. Tyto informace sledují jednotky práce s aktivitami. Některé aktivity vytváří platforma automaticky, jako je například aktivita ASP.NET, která představuje zpracování požadavku a knihoven a kódu aplikace. Příklad pozdravu obsahuje Greeter aktivitu. Aktivity jsou korelovány pomocí TraceId, SpanIda ParentId značek.

Každý proces v distribuovaném systému vytváří svůj vlastní datový proud informací o aktivitách a jako jsou metriky, potřebujete systém ke shromažďování, ukládání a korelaci aktivit, aby bylo možné vizualizovat práci provedenou pro každou transakci. Jaeger je opensourcový projekt, který umožňuje tuto kolekci a vizualizaci.

Stáhněte si nejnovější binární distribuční archiv Jaeger pro vaši platformu z https://www.jaegertracing.io/download/.

Potom extrahujte stažený soubor do místního umístění, ke kterému je snadný přístup. Spusťte spustitelný soubor jaeger-all-in-one(.exe):

./jaeger-all-in-one --collector.otlp.enabled

Projděte si výstup konzoly a najděte port, na kterém naslouchá provozu OTLP přes gRPC. Příklad:

{"level":"info","ts":1686963686.3854616,"caller":"otlpreceiver@v0.78.2/otlp.go:83","msg":"Starting GRPC server","endpoint":"0.0.0.0:4317"}

Tento výstup vám řekne, že naslouchá 0.0.0.0:4317, takže můžete tento port nakonfigurovat jako cíl pro vývozce OTLP.

AppSettings.json Otevřete soubor pro náš projekt a přidejte následující řádek a v případě potřeby změňte port.

"OTLP_ENDPOINT_URL" :  "http://localhost:4317/"

Restartujte proces pozdravu, aby mohl vyzvednout změnu vlastnosti a začít směrovat informace o trasování na Jaeger.

Teď byste měli být schopni zobrazit uživatelské rozhraní http://localhost:16686/ Jaegeru ve webovém prohlížeči.

Dotaz Jaeger pro trasování

Pokud chcete zobrazit seznam trasování, vyberte OTel-Prometheus-grafana-Jaeger v rozevíracím seznamu Služba . Výběrem trasování by se měl v rámci tohoto trasování zobrazit ganttův diagram aktivit. Kliknutím na každou operaci zobrazíte další podrobnosti o aktivitě.

Podrobnosti operace Jaeger

V distribuovaném systému chcete odesílat trasování ze všech procesů do stejné instalace Jaeger, aby mohl korelovat transakce v systému.

Aplikaci můžete trochu zajímavější tím, že ji budete volat HTTP sama.

  • HttpClient Přidání továrny do aplikace

    builder.Services.AddHttpClient();
    
  • Přidání nového koncového bodu pro volání vnořených pozdravů

    app.MapGet("/NestedGreeting", SendNestedGreeting);
    
  • Implementujte koncový bod tak, aby prováděl volání HTTP, která se dají také trasovat. V tomto případě se volá zpět v umělé smyčce (skutečně platí pouze pro ukázkové scénáře).

    async Task SendNestedGreeting(int nestlevel, ILogger<Program> logger, HttpContext context, IHttpClientFactory clientFactory)
    {
        // Create a new Activity scoped to the method
        using var activity = greeterActivitySource.StartActivity("GreeterActivity");
    
        if (nestlevel <= 5)
        {
            // Log a message
            logger.LogInformation("Sending greeting, level {nestlevel}", nestlevel);
    
            // Increment the custom counter
            countGreetings.Add(1);
    
            // Add a tag to the Activity
            activity?.SetTag("nest-level", nestlevel);
    
            await context.Response.WriteAsync($"Nested Greeting, level: {nestlevel}\r\n");
    
            if (nestlevel > 0)
            {
                var request = context.Request;
                var url = new Uri($"{request.Scheme}://{request.Host}{request.Path}?nestlevel={nestlevel - 1}");
    
                // Makes an http call passing the activity information as http headers
                var nestedResult = await clientFactory.CreateClient().GetStringAsync(url);
                await context.Response.WriteAsync(nestedResult);
            }
        }
        else
        {
            // Log a message
            logger.LogError("Greeting nest level {nestlevel} too high", nestlevel);
            await context.Response.WriteAsync("Nest level too high, max is 5");
        }
    }
    

Výsledkem je zajímavější graf s jehlanovým tvarem požadavků, protože každá úroveň čeká na odpověď z předchozího volání.

Výsledky vnořené závislosti Jaeger