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
astderr
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 ActivitySource
a 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 SpanId
TraceId
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.
Výběrem metriky greetings_count
zobrazíte graf hodnot.
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.
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.
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.
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
, SpanId
a 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.
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ě.
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 aplikacebuilder.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í.