Örnek: Prometheus, Grafana ve Jaeger ile OpenTelemetry kullanma
Bu örnekte ölçüm koleksiyonu için Prometheus, pano oluşturmak için Grafana ve dağıtılmış izlemeyi göstermek için Jaeger kullanılır.
1. Projeyi oluşturma
Visual Studio'da ASP.NET Core Empty şablonunu veya aşağıdaki .NET CLI komutunu kullanarak basit bir web API'si projesi oluşturun:
dotnet new web
2. Ölçüm ve etkinlik tanımları ekleme
Aşağıdaki kod, API'nin çağrılma sayısı için yeni bir ölçüm (greetings.count
) ve yeni bir etkinlik kaynağı (OtPrGrYa.Example
) tanımlar.
// 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. API uç noktası oluşturma
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!";
}
Not
API tanımı OpenTelemetry'ye özgü bir şey kullanmaz. Gözlemlenebilirlik için .NET API'lerini kullanır.
4. OpenTelemetry paketlerine başvurun
Aşağıdaki NuGet paketlerini eklemek için NuGet Paket Yöneticisi veya komut satırını kullanın:
<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>
Not
OTel API'leri sürekli geliştikçe en son sürümleri kullanın.
5. OpenTelemetry'yi doğru sağlayıcılarla yapılandırın
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")
// Metrics provided by System.Net libraries
.AddMeter("System.Net.Http")
.AddMeter("System.Net.NameResolution")
.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();
}
});
Bu kod, ASP.NET Core'dan ölçümleri ve etkinlikleri almak için ASP.NET Core izlemesini kullanır. Ayrıca ve sağlayıcılarını Metrics
ActivitySource
sırasıyla ölçümler ve izleme için kaydeder.
Kod, uç noktayı barındırmak için ASP.NET Core kullanan Ölçümler için Prometheus dışarı aktarmayı kullanır, bu nedenle şunları da eklemeniz gerekir:
// Configure the Prometheus scraping endpoint
app.MapPrometheusScrapingEndpoint();
6. Projeyi çalıştırma
Projeyi çalıştırın ve ardından tarayıcı veya curl ile API'ye erişin.
curl -k http://localhost:7275
Sayfayı her istediğinizde, yapılan karşılama sayısı artacaktır. yolu /metrics
ile aynı temel URL'yi kullanarak ölçüm uç noktasına erişebilirsiniz.
6.1 Günlük çıkışı
Koddaki günlük deyimleri kullanılarak ILogger
çıkıştır. Varsayılan olarak, çıktının konsola yönlendirilmesi için Konsol Sağlayıcısı etkinleştirilir.
Günlüklerin .NET'ten nasıl çıkarılacağına ilişkin birkaç seçenek vardır:
stdout
vestderr
çıkışı Kubernetes gibi kapsayıcı sistemleri tarafından günlük dosyalarına yönlendirilir.- Bunlar, ILogger ile tümleştirilecek günlük kitaplıklarını kullanarak Serilog veya NLog içerir.
- OtLP veya Azure İzleyici dışarıyı vereni gibi OTel için günlüğe kaydetme sağlayıcılarının kullanılması aşağıda daha ayrıntılı olarak gösterilmiştir.
6.2 Ölçümlere erişme
Uç noktayı kullanarak /metrics
ölçümlere erişebilirsiniz.
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
...
Ölçüm çıkışı, uç nokta istenildiğinde ölçümlerin anlık görüntüsüdür. Sonuçlar, insan tarafından okunabilir ancak Prometheus tarafından daha iyi anlaşılabilen Prometheus edat biçiminde sağlanır. Bu konu bir sonraki aşamada ele alınmıştır.
6.3 İzlemeye erişme
Sunucunun konsoluna bakarsanız, bilgileri okunabilir bir biçimde veren konsol izlemesini veren çıktıyı görürsünüz. Bu, biri özel ActivitySource
ve diğeri de ASP.NET Core'dan iki etkinlik göstermelidir:
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
Birincisi, oluşturduğunuz iç özel etkinliktir. İkincisi, istek için ASP.NET tarafından oluşturulur ve HTTP isteği özellikleri için etiketler içerir. Her ikisinin de tek bir işlemi tanımlayan aynı TraceId
öğesine sahip olduğunu ve dağıtılmış bir sistemde bir işlemde yer alan her hizmetten gelen izlemeleri ilişkilendirmek için kullanılabileceğini göreceksiniz. Kimlikler HTTP üst bilgileri olarak iletilir. ASP.NET Core, istek aldığında hiçbiri yoksa bir atar TraceId
. HttpClient
, giden isteklerde varsayılan olarak üst bilgileri içerir. Her etkinliğin, her etkinliği benzersiz olarak tanımlayan ve SpanId
birleşimi TraceId
olan bir SpanId
değeri vardır. Etkinliğin Greeter
üst öğesi, http etkinliğininkiyle ParentSpanId
eşlenen SpanId
aracılığıyla HTTP etkinliğine yönlendirilir.
Sonraki bir aşamada, dağıtılmış izlemeleri görselleştirmek için bu verileri Jaeger'a aktaracaksınız.
7. Prometheus ile ölçüm toplama
Prometheus bir ölçüm koleksiyonu, toplama ve zaman serisi veritabanı sistemidir. Bunu her hizmetin ölçüm uç noktalarıyla yapılandırdığınızda, değerleri düzenli aralıklarla kazır ve zaman serisi veritabanında depolar. Daha sonra bunları gerektiği gibi çözümleyebilir ve işleyebilirsiniz.
Prometheus biçiminde kullanıma sunulan ölçüm verileri, işlemin ölçümlerinin belirli bir noktaya anlık görüntüsüdür. Ölçüm uç noktasına her istek yapıldığında geçerli değerleri bildirir. Geçerli değerler ilgi çekici olsa da, eğilimleri görmek ve değerlerin anormal olup olmadığını algılamak için geçmiş değerlerle karşılaştırıldığında daha değerli hale gelirler. Genellikle hizmetler, tatil alışverişleri gibi günün saatlerine veya dünya etkinliklerine göre kullanım artışları gösterir. Değerleri geçmiş eğilimlerle karşılaştırarak, bunların anormal olup olmadığını veya bir ölçümün zaman içinde yavaş yavaş kötüleşmesi durumunu algılayabilirsiniz.
İşlem, bu ölçüm anlık görüntülerinin geçmişini depolamaz. Bu özelliğin işleme eklenmesi yoğun kaynak kullanımlı olabilir. Ayrıca, dağıtılmış bir sistemde genellikle her düğümün birden çok örneğine sahip olursunuz, bu nedenle tüm ölçümlerden ölçümleri toplamak ve ardından bunların geçmiş değerleriyle karşılaştırmak istersiniz.
7.1 Prometheus'u yükleme ve yapılandırma
Platformunuz için Prometheus'ı indirin https://prometheus.io/download/ ve indirmenin içeriğini ayıklayın.
Http uç noktasının bağlantı noktası numarasını almak için çalışan sunucunuzun çıktısının en üstüne bakın. Örneğin:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7275
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5212
HTTP kazıma uç noktanızın bağlantı noktasını belirtmek ve daha düşük bir kazıma aralığı ayarlamak için Prometheus YAML yapılandırma dosyasını değiştirin. Örneğin:
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"]
Prometheus'ı başlatın ve üzerinde çalıştığı bağlantı noktasının çıkışını (genellikle 9090) arayın:
>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
Bu URL'yi tarayıcınızda açın. Prometheus kullanıcı arabiriminde artık ölçümlerinizi sorgulayabilmeniz gerekir. Kullanılabilir tüm ölçümleri gösteren ölçüm gezginini açmak için aşağıdaki görüntüde vurgulanan düğmeyi kullanın.
Değerlerin greetings_count
grafiğini görmek için ölçümü seçin.
8. Ölçüm panosu oluşturmak için Grafana kullanın
Grafana, Prometheus veya diğer veri kaynaklarını temel alan panolar ve uyarılar oluşturabilen bir pano oluşturma ürünüdür.
Platformunuzun yönergelerini izleyerek Grafana'nın https://grafana.com/oss/grafana/ OSS sürümünü indirin ve yükleyin. Grafana yüklendikten sonra genellikle 3000 numaralı bağlantı noktasında çalıştırılır, bu nedenle tarayıcınızda açın http://localhost:3000
. Oturum açmanız gerekir; varsayılan kullanıcı adı ve parola her ikisi de admin
olur.
Hamburger menüsünden bağlantıları seçin ve ardından uç nokta türünüzü seçmek için metni prometheus
girin. Yeni bir veri kaynağı eklemek için Prometheus veri kaynağı oluştur'u seçin.
Aşağıdaki özellikleri ayarlamanız gerekir:
- Prometheus sunucusu URL'si:
http://localhost:9090/
bağlantı noktasını uygun şekilde değiştirme
Yapılandırmayı doğrulamak için Kaydet ve Test'i seçin.
Başarılı iletisi aldıktan sonra bir pano yapılandırabilirsiniz. Başarı iletisi için açılan pencerede gösterilen pano oluşturma bağlantısına tıklayın.
Görselleştirme Ekle'yi seçin ve ardından veri kaynağı olarak yeni eklediğiniz Prometheus veri kaynağını seçin.
Pano paneli tasarımcısı görünmelidir. Ekranın alt yarısında sorguyu tanımlayabilirsiniz.
greetings_count
Ölçümleri seçin ve ardından sonuçları görmek için Sorguları Çalıştır'ı seçin.
Grafana ile istediğiniz sayıda ölçümü izleyecek gelişmiş panolar tasarlayabilirsiniz.
.NET'teki her ölçüm, verileri bölümlendirmek için kullanılabilecek anahtar-değer çiftleri olan ek boyutlara sahip olabilir. ASP.NET ölçümlerinin tümü sayaç için geçerli olan bir dizi boyuta sahiptir. Örneğin, sayacı Microsoft.AspNetCore.Hosting
aşağıdaki current-requests
boyutlara sahiptir:
Öznitelik | Type | Açıklama | Örnekler | İletişim durumu |
---|---|---|---|---|
method |
string |
HTTP isteği yöntemi. | GET ; POST ; HEAD |
Her zaman |
scheme |
string |
Kullanılan protokolü tanımlayan URI düzeni. | http ; https |
Her zaman |
host |
string |
İsteği alan yerel HTTP sunucusunun adı. | localhost |
Her zaman |
port |
int |
İsteği alan yerel HTTP sunucusunun bağlantı noktası. | 8080 |
Varsayılan değilse eklenir (http için 80 veya https için 443) |
Grafana'daki grafikler genellikle her benzersiz boyut bileşimine göre bölümlenir. Boyutlar Grafana sorgularında verileri filtrelemek veya toplamak için kullanılabilir. Örneğin, grafiğini çizerseniz current_requests
, değerlerin her boyut bileşimine göre bölümlendiğini görürsünüz. Yalnızca konağa göre filtrelemek için bir işlemi Sum
ekleyin ve etiket değeri olarak kullanın host
.
9. Jaeger ile dağıtılmış izleme
6. adımda, dağıtılmış izleme bilgilerinin konsola açık olduğunu gördünüz. Bu bilgiler, etkinliklerle çalışma birimlerini izler. Bir isteğin işlenmesini temsil eden ASP.NET gibi bazı etkinlikler platform tarafından otomatik olarak oluşturulur ve kitaplıklar ve uygulama kodu da etkinlikler oluşturabilir. Selamlama örneği bir Greeter
etkinlik içerir. Etkinlikler , SpanId
ve ParentId
etiketleri kullanılarak TraceId
ilişkilendirilir.
Dağıtılmış sistemdeki her işlem kendi etkinlik bilgileri akışını oluşturur ve ölçümler gibi, her işlem için yapılan işi görselleştirmek için etkinlikleri toplamak, depolamak ve ilişkilendirmek için bir sisteme ihtiyacınız vardır. Jaeger, bu koleksiyonu ve görselleştirmeyi etkinleştirmeye yönelik açık kaynak bir projedir.
Platformunuz için Jaeger'ın en son ikili dağıtım arşivini adresinden https://www.jaegertracing.io/download/indirin.
Ardından indirmeyi kolayca erişebileceğiniz yerel bir konuma ayıklayın. jaeger-all-in-one(.exe) yürütülebilir dosyasını çalıştırın:
./jaeger-all-in-one --collector.otlp.enabled
gRPC aracılığıyla OTLP trafiğini dinlediği bağlantı noktasını bulmak için konsol çıkışına bakın. Örneğin:
{"level":"info","ts":1686963686.3854616,"caller":"otlpreceiver@v0.78.2/otlp.go:83","msg":"Starting GRPC server","endpoint":"0.0.0.0:4317"}
Bu çıkış, 0.0.0.0:4317
üzerinde dinlediğini bildirir, böylece bu bağlantı noktasını OTLP dışarı aktarıcınızın hedefi olarak yapılandırabilirsiniz.
AppSettings.json
Projemizin dosyasını açın ve varsa bağlantı noktasını değiştirerek aşağıdaki satırı ekleyin.
"OTLP_ENDPOINT_URL" : "http://localhost:4317/"
Özellik değişikliğini alabilmesi ve izleme bilgilerini Jaeger'a yönlendirmeye başlayabilmesi için karşılama işlemini yeniden başlatın.
Artık Jaeger kullanıcı arabirimini http://localhost:16686/
bir web tarayıcısından görebilmeniz gerekir.
İzlemelerin listesini görmek için Hizmet açılan listesinden öğesini seçinOTel-Prometheus-grafana-Jaeger
. İzleme seçildiğinde, bu izlemenin bir parçası olarak etkinliklerin gantt grafiği gösterilmelidir. İşlemlerin her birine tıklanması, etkinlik hakkında daha fazla ayrıntı gösterir.
Dağıtılmış bir sistemde, tüm işlemlerden izlemeleri aynı Jaeger yüklemesine göndermek istiyorsunuz, böylece işlemlerle sistem arasında bağıntı kurmasını sağlayabilirsiniz.
Uygulamanızın kendisine HTTP çağrıları yapmasını sağlayarak biraz daha ilginç hale getirebilirsiniz.
Uygulamaya fabrika
HttpClient
eklemebuilder.Services.AddHttpClient();
İç içe tebrik çağrıları yapmak için yeni bir uç nokta ekleme
app.MapGet("/NestedGreeting", SendNestedGreeting);
Uç noktayı uygulayarak aynı zamanda izleyebileceğiniz HTTP çağrıları yapmalarını sağlayın. Bu durumda yapay bir döngüde (yalnızca tanıtım senaryoları için geçerlidir) kendisine geri çağrır.
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"); } }
Her düzey önceki çağrının yanıtını beklediğinden istekler için piramit şeklinde daha ilginç bir grafik elde edilir.