Przykład: używanie funkcji OpenTelemetry z rozwiązaniem Prometheus, Grafana i Jaeger
W tym przykładzie użyto rozwiązania Prometheus do zbierania metryk, narzędzia Grafana do tworzenia pulpitu nawigacyjnego i narzędzia Jaeger do wyświetlania śledzenia rozproszonego.
1. Tworzenie projektu
Utwórz prosty projekt internetowego interfejsu API przy użyciu szablonu ASP.NET Core Empty w programie Visual Studio lub następującego polecenia interfejsu wiersza polecenia platformy .NET:
dotnet new web
2. Dodawanie metryk i definicji działań
Poniższy kod definiuje nową metrykę (greetings.count
) dla liczby wywołań interfejsu API i nowego źródła działań (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. Tworzenie punktu końcowego interfejsu 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!";
}
Uwaga
Definicja interfejsu API nie używa żadnych elementów specyficznych dla biblioteki OpenTelemetry. Używa on interfejsów API platformy .NET do obserwowania.
4. Odwołanie do pakietów OpenTelemetry
Użyj Menedżer pakietów NuGet lub wiersza polecenia, aby dodać następujące pakiety 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>
Uwaga
Użyj najnowszych wersji, ponieważ interfejsy API OTel stale ewoluują.
5. Konfigurowanie biblioteki OpenTelemetry przy użyciu odpowiednich dostawców
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();
}
});
Ten kod używa instrumentacji ASP.NET Core, aby uzyskać metryki i działania z platformy ASP.NET Core. Rejestruje również Metrics
dostawców i ActivitySource
na potrzeby metryk i śledzenia odpowiednio.
Kod używa eksportera Prometheus dla metryk, który używa ASP.NET Core do hostowania punktu końcowego, dlatego należy również dodać:
// Configure the Prometheus scraping endpoint
app.MapPrometheusScrapingEndpoint();
6. Uruchamianie projektu
Uruchom projekt, a następnie uzyskaj dostęp do interfejsu API za pomocą przeglądarki lub narzędzia curl.
curl -k http://localhost:7275
Za każdym razem, gdy zażądasz strony, będzie ona zwiększać liczbę wykonanych powitań. Dostęp do punktu końcowego metryk można uzyskać przy użyciu tego samego podstawowego adresu URL ze ścieżką /metrics
.
6.1 Dane wyjściowe dziennika
Instrukcje rejestrowania z kodu są danymi wyjściowymi przy użyciu polecenia ILogger
. Domyślnie dostawca konsoli jest włączony, aby dane wyjściowe są kierowane do konsoli.
Istnieje kilka opcji, w jaki sposób dzienniki mogą być wychodzące z platformy .NET:
stdout
dane wyjściowe sąstderr
przekierowywane do plików dziennika przez systemy kontenerów, takie jak Kubernetes.- Korzystając z bibliotek rejestrowania, które zostaną zintegrowane z usługą ILogger, należą do nich serilog lub NLog.
- Korzystając z dostawców rejestrowania dla OTel, takich jak OTLP lub eksporter usługi Azure Monitor, pokazano poniżej.
6.2 Uzyskiwanie dostępu do metryk
Dostęp do metryk można uzyskać przy użyciu punktu końcowego /metrics
.
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
...
Dane wyjściowe metryk to migawka metryk w momencie żądania punktu końcowego. Wyniki są udostępniane w formacie ekspozycji Prometheus, który jest czytelny dla człowieka, ale lepiej rozumiany przez Prometheus. Ten temat został omówiony na następnym etapie.
6.3 Uzyskiwanie dostępu do śledzenia
Jeśli spojrzysz na konsolę serwera, zobaczysz dane wyjściowe eksportera śledzenia konsoli, który generuje informacje w formacie czytelnym dla człowieka. Powinno to spowodować wyświetlenie dwóch działań: jednego z niestandardowego ActivitySource
elementu , a drugiego 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
Pierwszy to wewnętrzne utworzone działanie niestandardowe. Drugi jest tworzony przez ASP.NET dla żądania i zawiera tagi właściwości żądania HTTP. Zobaczysz, że oba te elementy mają ten sam TraceId
element , który identyfikuje jedną transakcję i w systemie rozproszonym może służyć do korelowania śladów z każdej usługi zaangażowanej w transakcję. Identyfikatory są przesyłane jako nagłówki HTTP. ASP.NET Core przypisuje element TraceId
, jeśli żaden z nich nie istnieje, gdy odbiera żądanie. HttpClient
domyślnie zawiera nagłówki dla żądań wychodzących. Każde działanie ma wartość , która jest kombinacją SpanId
TraceId
i SpanId
jednoznacznie identyfikuje każde działanie. Działanie Greeter
jest nadrzędne dla działania HTTP za pośrednictwem elementu ParentSpanId
, który jest mapowany na SpanId
działanie HTTP.
W późniejszym etapie przekażesz te dane do firmy Jaeger, aby zwizualizować rozproszone ślady.
7. Zbieranie metryk za pomocą rozwiązania Prometheus
Prometheus to system bazy danych metryk, agregacji i szeregów czasowych. Konfigurujesz je przy użyciu punktów końcowych metryk dla każdej usługi i okresowo usuwa wartości i przechowuje je w bazie danych szeregów czasowych. Następnie możesz je analizować i przetwarzać zgodnie z potrzebami.
Dane metryk uwidocznione w formacie Prometheus to migawka metryk procesu w czasie. Za każdym razem, gdy żądanie zostanie wykonane do punktu końcowego metryk, będzie zgłaszać bieżące wartości. Chociaż bieżące wartości są interesujące, stają się bardziej cenne w porównaniu z wartościami historycznymi, aby zobaczyć trendy i wykryć, czy wartości są nietypowe. Często usługi mają skoki użycia na podstawie pory dnia lub wydarzeń światowych, takich jak spree zakupów świątecznych. Porównując wartości z trendami historycznymi, można wykryć, czy są one nietypowe, lub jeśli metryka powoli się pogarsza w czasie.
Proces nie przechowuje żadnej historii tych migawek metryk. Dodanie tej możliwości do procesu może być intensywnie korzystające z zasobów. Ponadto w systemie rozproszonym często masz wiele wystąpień każdego węzła, więc chcesz mieć możliwość zbierania metryk ze wszystkich z nich, a następnie agregowania i porównywania z ich wartościami historycznymi.
7.1 Instalowanie i konfigurowanie rozwiązania Prometheus
Pobierz aplikację Prometheus dla swojej platformy z https://prometheus.io/download/ witryny i wyodrębnij zawartość pobierania.
Przyjrzyj się górnej części danych wyjściowych uruchomionego serwera, aby uzyskać numer portu dla punktu końcowego HTTP . Na przykład:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7275
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5212
Zmodyfikuj plik konfiguracji YAML rozwiązania Prometheus, aby określić port punktu końcowego złomowania HTTP i ustawić niższy interwał złomowania. Na przykład:
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"]
Uruchom aplikację Prometheus i poszukaj w danych wyjściowych portu, na którym działa, zazwyczaj 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
Otwórz ten adres URL w przeglądarce. W interfejsie użytkownika rozwiązania Prometheus powinno być teraz możliwe wykonywanie zapytań dotyczących metryk. Użyj wyróżnionego przycisku na poniższej ilustracji, aby otworzyć eksploratora metryk, który pokazuje wszystkie dostępne metryki.
Wybierz metrykę greetings_count
, aby wyświetlić wykres wartości.
8. Tworzenie pulpitu nawigacyjnego metryk przy użyciu narzędzia Grafana
Grafana to produkt do tworzenia pulpitów nawigacyjnych, który może tworzyć pulpity nawigacyjne i alerty na podstawie rozwiązania Prometheus lub innych źródeł danych.
Pobierz i zainstaluj wersję systemu operacyjnego Grafana, postępując zgodnie z https://grafana.com/oss/grafana/ instrukcjami dotyczącymi platformy. Po zainstalowaniu narzędzie Grafana jest zwykle uruchamiane na porcie 3000, więc otwórz http://localhost:3000
go w przeglądarce. Musisz się zalogować; domyślna nazwa użytkownika i hasło to .admin
Z menu hamburgera wybierz połączenia, a następnie wprowadź tekst prometheus
, aby wybrać typ punktu końcowego. Wybierz pozycję Utwórz źródło danych Prometheus, aby dodać nowe źródło danych.
Należy ustawić następujące właściwości:
- Adres URL serwera Prometheus:
http://localhost:9090/
zmiana portu zgodnie z zastosowaniem
Wybierz pozycję Zapisz i testuj , aby zweryfikować konfigurację.
Po otrzymaniu komunikatu o powodzeniu możesz skonfigurować pulpit nawigacyjny. Kliknij link do tworzenia pulpitu nawigacyjnego wyświetlany w oknie podręcznym komunikatu o powodzeniu.
Wybierz pozycję Dodaj wizualizację, a następnie wybierz źródło danych Prometheus, które właśnie dodano jako źródło danych.
Powinien zostać wyświetlony projektant panelu pulpitu nawigacyjnego. W dolnej połowie ekranu można zdefiniować zapytanie.
Wybierz metryki greetings_count
, a następnie wybierz pozycję Uruchom zapytania , aby wyświetlić wyniki.
Za pomocą narzędzia Grafana możesz zaprojektować zaawansowane pulpity nawigacyjne, które będą śledzić dowolną liczbę metryk.
Każda metryka na platformie .NET może mieć dodatkowe wymiary, które są parami klucz-wartość, których można użyć do partycjonowania danych. Metryki ASP.NET wszystkie zawierają szereg wymiarów mających zastosowanie do licznika. Na przykład current-requests
licznik z Microsoft.AspNetCore.Hosting
ma następujące wymiary:
Atrybut | Type | Opis | Przykłady | Obecność |
---|---|---|---|---|
method |
string |
Metoda żądania HTTP. | GET ; POST ; HEAD |
Zawsze |
scheme |
string |
Schemat identyfikatora URI identyfikujący używany protokół. | http ; https |
Zawsze |
host |
string |
Nazwa lokalnego serwera HTTP, który odebrał żądanie. | localhost |
Zawsze |
port |
int |
Port lokalnego serwera HTTP, który odebrał żądanie. | 8080 |
Dodano wartość domyślną (80 dla protokołu HTTP lub 443 dla protokołu https) |
Wykresy w narzędziu Grafana są zwykle partycjonowane na podstawie każdej unikatowej kombinacji wymiarów. Wymiary mogą być używane w zapytaniach Grafana do filtrowania lub agregowania danych. Na przykład w przypadku wykresu current_requests
zobaczysz wartości podzielone na partycje na podstawie każdej kombinacji wymiarów. Aby filtrować tylko na hoście, dodaj operację Sum
i użyj jej host
jako wartości etykiety.
9. Śledzenie rozproszone za pomocą narzędzia Jaeger
W kroku 6 pokazano, że informacje dotyczące śledzenia rozproszonego były uwidocznione w konsoli programu . Te informacje śledzą jednostki pracy z działaniami. Niektóre działania są tworzone automatycznie przez platformę, na przykład przez ASP.NET do reprezentowania obsługi żądania, a biblioteki i kod aplikacji mogą również tworzyć działania. Przykład powitania zawiera Greeter
działanie. Działania są skorelowane przy użyciu tagów TraceId
, SpanId
i ParentId
.
Każdy proces w systemie rozproszonym tworzy swój własny strumień informacji o aktywności i takich jak metryki, potrzebny jest system do zbierania, przechowywania i korelowania działań, aby móc wizualizować pracę wykonaną dla każdej transakcji. Jaeger to projekt open source umożliwiający włączenie tej kolekcji i wizualizacji.
Pobierz najnowsze archiwum dystrybucji binarnej jaeger dla swojej platformy z witryny https://www.jaegertracing.io/download/.
Następnie wyodrębnij pobieranie do lokalizacji lokalnej, która jest łatwa do uzyskania dostępu. Uruchom plik wykonywalny jaeger-all-in-one(.exe):
./jaeger-all-in-one --collector.otlp.enabled
Przejrzyj dane wyjściowe konsoli, aby znaleźć port, w którym nasłuchuje ruchu OTLP za pośrednictwem kontrolera gRPC. Na przykład:
{"level":"info","ts":1686963686.3854616,"caller":"otlpreceiver@v0.78.2/otlp.go:83","msg":"Starting GRPC server","endpoint":"0.0.0.0:4317"}
Te dane wyjściowe informują, że nasłuchuje w systemie 0.0.0.0:4317
, aby można było skonfigurować ten port jako miejsce docelowe eksportera OTLP.
AppSettings.json
Otwórz plik dla naszego projektu i dodaj następujący wiersz, zmieniając port, jeśli ma to zastosowanie.
"OTLP_ENDPOINT_URL" : "http://localhost:4317/"
Uruchom ponownie proces powitania, aby można było pobrać zmianę właściwości i rozpocząć kierowanie informacji śledzenia do jaeger.
Teraz powinien być widoczny interfejs użytkownika jaegera w http://localhost:16686/
przeglądarce internetowej.
Aby wyświetlić listę śladów, wybierz z OTel-Prometheus-grafana-Jaeger
listy rozwijanej Usługa . Wybranie śledzenia powinno zawierać wykres gantta działań w ramach tego śladu. Kliknięcie każdej operacji spowoduje wyświetlenie dodatkowych szczegółów dotyczących działania.
W systemie rozproszonym chcesz wysyłać ślady ze wszystkich procesów do tej samej instalacji usługi Jaeger, aby mogła skorelować transakcje w całym systemie.
Możesz sprawić, że aplikacja stanie się nieco bardziej interesująca, wykonując wywołania HTTP do siebie.
HttpClient
Dodawanie fabryki do aplikacjibuilder.Services.AddHttpClient();
Dodawanie nowego punktu końcowego do tworzenia zagnieżdżonych wywołań powitania
app.MapGet("/NestedGreeting", SendNestedGreeting);
Zaimplementuj punkt końcowy, aby wykonywać wywołania HTTP, które mogą być również śledzone. W takim przypadku wywołuje się z powrotem w sztucznej pętli (dotyczy to tylko scenariuszy demonstracyjnych).
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"); } }
Powoduje to bardziej interesujący wykres z kształtem ostrosłupu dla żądań, ponieważ każdy poziom czeka na odpowiedź z poprzedniego wywołania.