.NET'te ağ ölçümleri
Ölçümler , zaman içinde bildirilen sayısal ölçümlerdir. Bunlar genellikle bir uygulamanın durumunu izlemek ve uyarılar oluşturmak için kullanılır.
.NET 8'den System.Net.Http
başlayarak ve System.Net.NameResolution
bileşenleri kullanılarak ölçümleri yayımlamak için izlenir. NET'in yeni System.Diagnostics.Metrics API'si.
Bu ölçümler, standartla tutarlı olduklarından ve Prometheusve Grafana gibi popüler araçlarla iyi çalıştıklarından emin olmak için OpenTelemetry ile işbirliği içinde tasarlanmıştır.
Ayrıca çok boyutlu olan ölçümler, verilerin analiz için kategorilere ayrılmasına izin veren etiketler (öznitelikler veya etiketler) olarak adlandırılan anahtar-değer çiftleriyle ilişkilendirilir.
İpucu
Tüm yerleşik araçların öznitelikleriyle birlikte kapsamlı bir listesi için bkz . System.Net ölçümler.
System.Net ölçümleri toplama
.NET uygulamasında ölçümleri kullanmanın iki bölümü vardır:
- İzleme: .NET kitaplıklarındaki kod ölçümler alır ve bu ölçümleri bir ölçüm adıyla ilişkilendirir. .NET ve ASP.NET Core birçok yerleşik ölçüm içerir.
- Koleksiyon: Bir .NET uygulaması, adlandırılmış ölçümleri dış depolama ve analiz için uygulamadan iletilecek şekilde yapılandırıyor. Bazı araçlar yapılandırma dosyalarını veya kullanıcı arabirimi aracını kullanarak uygulamanın dışında yapılandırma gerçekleştirebilir.
Bu bölümde, System.Net ölçümleri toplamak ve görüntülemek için çeşitli yöntemler gösterilmektedir.
Örnek uygulama
Bu öğreticinin iyiliği için, çeşitli uç noktalara paralel olarak HTTP istekleri gönderen basit bir uygulama oluşturun.
dotnet new console -o HelloBuiltinMetrics
cd ..\HelloBuiltinMetrics
öğesinin içeriğini Program.cs
aşağıdaki örnek kodla değiştirin:
using System.Net;
string[] uris = ["http://example.com", "http://httpbin.org/get", "https://example.com", "https://httpbin.org/get"];
using HttpClient client = new()
{
DefaultRequestVersion = HttpVersion.Version20
};
Console.WriteLine("Press any key to start.");
Console.ReadKey();
while (!Console.KeyAvailable)
{
await Parallel.ForAsync(0, Random.Shared.Next(20), async (_, ct) =>
{
string uri = uris[Random.Shared.Next(uris.Length)];
byte[] bytes = await client.GetByteArrayAsync(uri, ct);
await Console.Out.WriteLineAsync($"{uri} - received {bytes.Length} bytes.");
});
}
Dotnet-counters ile ölçümleri görüntüleme
dotnet-counters
geçici sistem durumu izleme ve birinci düzey performans araştırması için platformlar arası bir performans izleme aracıdır.
dotnet tool install --global dotnet-counters
.NET 8+ işlemine karşı çalışırken bağımsız dotnet-counters
değişken tarafından --counters
tanımlanan araçları etkinleştirir ve ölçümleri görüntüler. Konsolu sürekli olarak en son sayılarla yeniler:
dotnet-counters monitor --counters System.Net.Http,System.Net.NameResolution -n HelloBuiltinMetrics
OpenTelemetry ve Prometheus ile Grafana'da ölçümleri görüntüleme
Genel bakış
- Cloud Native Computing Foundation tarafından desteklenen, satıcıdan bağımsız, açık kaynak bir projedir.
- Bulutta yerel yazılımlar için telemetri oluşturmayı ve toplamayı standartlaştırır.
- .NET ölçüm API'lerini kullanarak .NET ile çalışır.
- Azure İzleyici ve birçok APM satıcısı tarafından onaylanır.
Bu öğreticide, OSS Prometheus ve Grafana projelerini kullanarak OpenTelemetry ölçümleri için kullanılabilen tümleştirmelerden biri gösterilmektedir. Ölçüm veri akışı aşağıdaki adımlardan oluşur:
.NET ölçüm API'leri örnek uygulamadaki ölçümleri kaydeder.
Uygulamada çalıştırılan OpenTelemetry kitaplığı ölçümleri toplar.
Prometheus dışarı aktarma kitaplığı, toplanan verileri bir HTTP ölçüm uç noktası aracılığıyla kullanılabilir hale getirir. 'Exporter', OpenTelemetry'nin telemetri verilerini satıcıya özgü arka uçlara ileten kitaplıkları çağıran şeydir.
Prometheus sunucusu:
- Ölçüm uç noktasını yoklar.
- Verileri okur.
- Verileri uzun süreli kalıcılık için bir veritabanında depolar. Prometheus, verileri okuma ve depolamayı bir uç noktayı kazıma olarak ifade eder.
- Farklı bir makinede çalıştırılabilir.
Grafana sunucusu:
- Prometheus'ta depolanan verileri sorgular ve web tabanlı bir izleme panosunda görüntüler.
- Farklı bir makinede çalıştırılabilir.
Örnek uygulamayı OpenTelemetry'nin Prometheus dışarı aktarmasını kullanacak şekilde yapılandırma
Örnek uygulamaya OpenTelemetry Prometheus verenine bir başvuru ekleyin:
dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener --prerelease
Not
Bu öğreticide, yazma sırasında sağlanan OpenTelemetry Prometheus desteğinin yayın öncesi derlemesi kullanılmaktadır.
OpenTelemetry yapılandırmasıyla güncelleştirme Program.cs
:
using OpenTelemetry.Metrics;
using OpenTelemetry;
using System.Net;
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("System.Net.Http", "System.Net.NameResolution")
.AddPrometheusHttpListener(options => options.UriPrefixes = new string[] { "http://localhost:9184/" })
.Build();
string[] uris = ["http://example.com", "http://httpbin.org/get", "https://example.com", "https://httpbin.org/get"];
using HttpClient client = new()
{
DefaultRequestVersion = HttpVersion.Version20
};
while (!Console.KeyAvailable)
{
await Parallel.ForAsync(0, Random.Shared.Next(20), async (_, ct) =>
{
string uri = uris[Random.Shared.Next(uris.Length)];
byte[] bytes = await client.GetByteArrayAsync(uri, ct);
await Console.Out.WriteLineAsync($"{uri} - received {bytes.Length} bytes.");
});
}
Önceki kodda:
AddMeter("System.Net.Http", "System.Net.NameResolution")
Yerleşik veSystem.Net.NameResolution
ölçümler tarafından toplanan tüm ölçümleri iletmek için OpenTelemetry'yiSystem.Net.Http
yapılandırıyor.AddPrometheusHttpListener
, Bağlantı noktasında9184
Prometheus'un ölçümleri HTTP uç noktasını kullanıma sunacak OpenTelemetry'yi yapılandırıyor.
Not
Bu yapılandırma, ölçümlerin HttpListener
yerine ile OpenTelemetry.Exporter.Prometheus.AspNetCore
dışarı aktarıldığı ASP.NET Core uygulamaları için farklılık gösterir. İlgili ASP.NET Core örneğine bakın.
Ölçümlerin toplanabilmesi için uygulamayı çalıştırın ve çalışır durumda bırakın:
dotnet run
Prometheus'ı ayarlama ve yapılandırma
Prometheus sunucusunu ayarlamak için Prometheus ilk adımlarını izleyin ve çalıştığını doğrulayın.
prometheus.yml yapılandırma dosyasını, Prometheus'un örnek uygulamanın sergilediğini ölçümler uç noktasını kazıması için değiştirin. Bölümüne aşağıdaki vurgulanmış metni scrape_configs
ekleyin:
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
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'.
static_configs:
- targets: ["localhost:9090"]
- job_name: 'OpenTelemetryTest'
scrape_interval: 1s # poll very quickly for a more responsive demo
static_configs:
- targets: ['localhost:9184']
Prometheus'ı başlatma
Yapılandırmayı yeniden yükleyin veya Prometheus sunucusunu yeniden başlatın.
OpenTelemetryTest'in Prometheus web portalının Durum>Hedefleri sayfasında UP durumunda olduğunu onaylayın.
Prometheus web portalının Graf sayfasında, ifade metin kutusuna yazın
http
ve öğesini seçinhttp_client_active_requests
.Grafik sekmesinde, Prometheus örnek uygulama tarafından yayılan sayacın değerini
http.client.active_requests
gösterir.
Grafana panosunda ölçümleri gösterme
Grafana'yı yüklemek ve prometheus veri kaynağına bağlamak için standart yönergeleri izleyin.
Üst araç çubuğundaki simgeyi + ve ardından Pano'yu seçerek grafana panosu oluşturun. Görüntülenen pano düzenleyicisinde Başlık kutusuna HTTP/1.1 Bağlan ions'ı aç ve PromQL ifade alanına aşağıdaki sorguyu girin:
sum by(http_connection_state) (http_client_open_connections{network_protocol_version="1.1"})
- Yeni panoyu kaydetmek ve görüntülemek için Uygula'yı seçin. Havuzdaki etkin ve boş http/1.1 bağlantılarının sayısını görüntüler.
Zenginleştirme
Zenginleştirme , bir ölçüme özel etiketlerin (yani özniteliklerin veya etiketlerin) eklenmesidir. Bu, bir uygulama ölçümlerle oluşturulmuş panolara veya uyarılara özel bir kategori eklemek istediğinde kullanışlıdır.
Araç, http.client.request.duration
geri çağırmaları ile kaydederek zenginleştirmeyi HttpMetricsEnrichmentContextdestekler.
Bunun düşük düzeyli bir API olduğunu ve her HttpRequestMessage
için ayrı bir geri çağırma kaydı gerektiğini unutmayın.
Geri çağırma kaydını tek bir yerde yapmanın basit bir yolu özel DelegatingHandlerbir uygulamaktır. Bu, istekleri iç işleyiciye iletilmeden ve sunucuya gönderilmeden önce kesmenize ve değiştirmenize olanak sağlar:
using System.Net.Http.Metrics;
using HttpClient client = new(new EnrichmentHandler() { InnerHandler = new HttpClientHandler() });
await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=A");
await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=B");
sealed class EnrichmentHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpMetricsEnrichmentContext.AddCallback(request, static context =>
{
if (context.Response is not null) // Response is null when an exception occurs.
{
// Use any information available on the request or the response to emit custom tags.
string? value = context.Response.Headers.GetValues("Enrichment-Value").FirstOrDefault();
if (value != null)
{
context.AddCustomTag("enrichment_value", value);
}
}
});
return base.SendAsync(request, cancellationToken);
}
}
ile IHttpClientFactory
çalışıyorsanız, öğesini kaydetmek EnrichmentHandler
için kullanabilirsinizAddHttpMessageHandler:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Net.Http.Metrics;
ServiceCollection services = new();
services.AddHttpClient(Options.DefaultName).AddHttpMessageHandler(() => new EnrichmentHandler());
ServiceProvider serviceProvider = services.BuildServiceProvider();
HttpClient client = serviceProvider.GetRequiredService<HttpClient>();
await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=A");
await client.GetStringAsync("https://httpbin.org/response-headers?Enrichment-Value=B");
Not
Performans nedenleriyle, zenginleştirme geri çağırması yalnızca araç etkinleştirildiğinde http.client.request.duration
çağrılır; başka bir deyişle ölçümleri bir şeyin toplaması gerekir.
dotnet-monitor
Bu , Prometheus ihracatçısı, veya MeterListener
olabilirMetricCollector<T>
.
IMeterFactory
ve IHttpClientFactory
tümleştirme
HTTP ölçümleri yalıtım ve test edilebilirlik göz önünde bulundurularak tasarlanmıştır. Bu özellikler, Ölçümler'i IMeterFactorybirbirinden yalıtmak için ölçümlerin özel Meter bir örnek tarafından yayımlanmasını sağlayan kullanımıyla desteklenir.
Varsayılan olarak, tüm ölçümler genel bir Meter iç tarafından kitaplığa System.Net.Http
yayılır. Bu davranış, veya HttpClientHandler.MeterFactoryöğesine özel IMeterFactory bir örnek SocketsHttpHandler.MeterFactory atanarak geçersiz kılınabilir.
Not
, Meter.Name ve SocketsHttpHandler
tarafından HttpClientHandler
yayılan tüm ölçümlere yöneliktirSystem.Net.Http
.
.NET 8+ ile Microsoft.Extensions.Http
ve IHttpClientFactory
üzerinde çalışırken, varsayılan IHttpClientFactory
uygulama içinde kayıtlı IServiceCollection örneği otomatik olarak seçer IMeterFactory
ve dahili olarak oluşturduğu birincil işleyiciye atar.
Not
.NET 8'den başlayarak yöntemi, AddHttpClient ölçüm hizmetlerini başlatmak ve varsayılan IMeterFactory uygulamayı ile IServiceCollectionkaydetmek için otomatik olarak öğesini çağırırAddMetrics. VarsayılanIMeterFactory, örnekleri ada göre önbelleğe Meter alır; yani her IServiceCollectionbiri adına sahip bir Meter örnek System.Net.Http
olacaktır.
Test ölçümleri
Aşağıdaki örnekte, xUnit, IHttpClientFactory
ve MetricCollector<T>
kullanarak NuGet paketinden birim testlerinde yerleşik ölçümlerin nasıl doğrulanması Microsoft.Extensions.Diagnostics.Testing
gösterilmektedir:
[Fact]
public async Task RequestDurationTest()
{
// Arrange
ServiceCollection services = new();
services.AddHttpClient();
ServiceProvider serviceProvider = services.BuildServiceProvider();
var meterFactory = serviceProvider.GetService<IMeterFactory>();
var collector = new MetricCollector<double>(meterFactory,
"System.Net.Http", "http.client.request.duration");
var client = serviceProvider.GetRequiredService<HttpClient>();
// Act
await client.GetStringAsync("http://example.com");
// Assert
await collector.WaitForMeasurementsAsync(minCount: 1).WaitAsync(TimeSpan.FromSeconds(5));
Assert.Collection(collector.GetMeasurementSnapshot(),
measurement =>
{
Assert.Equal("http", measurement.Tags["url.scheme"]);
Assert.Equal("GET", measurement.Tags["http.request.method"]);
});
}
Ölçümler ile EventCounters karşılaştırması
Ölçümler , özellikle çok boyutlu doğası nedeniyle EventCounters'dan daha zengin özelliklere sahiptir. Bu çok boyutluluk, Prometheus gibi araçlarda karmaşık sorgular oluşturmanıza ve EventCounters ile mümkün olmayan bir düzeyde içgörüler elde etmenize olanak tanır.
Bununla birlikte, .NET 8'den itibaren yalnızca System.Net.Http
ve System.Net.NameResolutions
bileşenleri Ölçümler kullanılarak izlenir; başka bir deyişle, veya System.Net.Security
gibi System.Net.Sockets
yığının alt düzeylerinden sayaçlara ihtiyacınız varsa EventCounters kullanmanız gerekir.
Ayrıca Ölçümler ile bunların eşleşen EventCounter'ları arasında bazı semantik farklılıklar vardır.
Örneğin, kullanırken HttpCompletionOption.ResponseContentRead
EventCounter istek gövdesinin current-requests
son baytının okunduğu ana kadar bir isteğin etkin olduğunu düşünür.
Ölçümler, http.client.active_requests
etkin istekleri sayarken yanıt gövdesini okumak için harcanan zamanı içermez.
Daha fazla ölçüme mi ihtiyacınız var?
Ölçümler aracılığıyla kullanıma sunulacak diğer yararlı bilgiler için önerileriniz varsa bir dotnet/runtime sorunu oluşturun.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin