Ana içeriğe geç

Real-Time Telemetry ile Performans Analizi

Gerçek zamanlı telemetri, uygulamanın anlık durumunu izleyerek proaktif müdahale imkanı sağlar; eksik veya gecikmeli telemetri sorunların büyümesine yol açar.


1. Metrikleri Batch Olarak Göndermek

Yanlış Kullanım: Metrikleri uzun aralıklarla toplu göndermek.

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddPrometheusExporter());

// prometheus.yml
// scrape_interval: 60s  → 1 dakikalık gecikme, anlık sorunlar kaçar

İdeal Kullanım: Kısa aralıklarla scrape ve push yapın.

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddOtlpExporter(options =>
        {
            options.Endpoint = new Uri("http://otel-collector:4317");
            options.ExportProcessorType = ExportProcessorType.Simple;
            options.PeriodicExportingMetricReaderOptions = new()
            {
                ExportIntervalMilliseconds = 10_000 // 10 saniye
            };
        }));

2. Runtime Metriklerini İzlememek

Yanlış Kullanım: Sadece HTTP metriklerini toplamak.

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddAspNetCoreInstrumentation());
// GC, ThreadPool, Memory bilgisi yok

İdeal Kullanım: Runtime ve process metriklerini de toplayın.

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddAspNetCoreInstrumentation()
        .AddHttpClientInstrumentation()
        .AddRuntimeInstrumentation()
        .AddProcessInstrumentation()
        .AddMeter("Microsoft.AspNetCore.Hosting")
        .AddMeter("Microsoft.AspNetCore.Server.Kestrel")
        .AddPrometheusExporter());

// dotnet-counters ile anlık izleme (development)
// dotnet-counters monitor --process-id <pid> --counters
//   System.Runtime,
//   Microsoft.AspNetCore.Hosting,
//   Microsoft.AspNetCore.Http.Connections

3. Custom Metrik Oluşturmamak

Yanlış Kullanım: Sadece framework metriklerine güvenmek.

// Sadece varsayılan HTTP istek metrikleri
// İş metriği yok: sipariş/dk, ödeme başarı oranı, stok durumu

İdeal Kullanım: İş mantığına özel metrikler tanımlayın.

public class BusinessMetrics
{
    private readonly Counter<long> _ordersProcessed;
    private readonly Histogram<double> _orderValue;
    private readonly ObservableGauge<int> _queueDepth;

    public BusinessMetrics(IMeterFactory meterFactory, IQueueService queueService)
    {
        var meter = meterFactory.Create("Business");

        _ordersProcessed = meter.CreateCounter<long>(
            "business.orders.processed", "order", "İşlenen sipariş sayısı");

        _orderValue = meter.CreateHistogram<double>(
            "business.orders.value", "TRY", "Sipariş tutarı dağılımı");

        _queueDepth = meter.CreateObservableGauge(
            "business.queue.depth",
            () => queueService.GetPendingCount(),
            "item", "Bekleyen iş sayısı");
    }

    public void RecordOrder(decimal amount, string paymentMethod)
    {
        _ordersProcessed.Add(1, new("payment_method", paymentMethod));
        _orderValue.Record((double)amount);
    }
}

4. Health Check’leri Metriklerle İlişkilendirmemek

Yanlış Kullanım: Health check ve metrikler ayrı yaşam döngüsünde.

builder.Services.AddHealthChecks()
    .AddSqlServer(connectionString);

// Health check sonuçları metrik olarak izlenmiyor

İdeal Kullanım: Health check sonuçlarını metrik olarak yayınlayın.

builder.Services.AddHealthChecks()
    .AddSqlServer(connectionString, name: "database")
    .AddRedis(redisConnectionString, name: "redis")
    .AddUrlGroup(new Uri("https://api.external.com"), name: "external-api");

// Health check metrikleri
public class HealthCheckMetricsPublisher : IHealthCheckPublisher
{
    private readonly ObservableGauge<int> _healthGauge;

    public HealthCheckMetricsPublisher(IMeterFactory meterFactory)
    {
        var meter = meterFactory.Create("HealthChecks");
        _healthGauge = meter.CreateObservableGauge<int>("health.status", () => _lastResults);
    }

    private List<Measurement<int>> _lastResults = new();

    public Task PublishAsync(HealthReport report, CancellationToken ct)
    {
        _lastResults = report.Entries.Select(e => new Measurement<int>(
            e.Value.Status == HealthStatus.Healthy ? 1 : 0,
            new KeyValuePair<string, object?>("check", e.Key)
        )).ToList();

        return Task.CompletedTask;
    }
}

builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Period = TimeSpan.FromSeconds(30);
});
builder.Services.AddSingleton<IHealthCheckPublisher, HealthCheckMetricsPublisher>();

5. Live Dashboard Kullanmamak

Yanlış Kullanım: .NET Aspire Dashboard’u veya dotnet-monitor’ı kullanmamak.

// Sadece uzak monitoring araçlarına bağımlı
// Geliştirme sırasında anlık telemetri görülemiyor

İdeal Kullanım: Development’ta Aspire Dashboard ile anlık izleme yapın.

// .NET Aspire Dashboard (standalone)
// docker run -p 18888:18888 -p 4317:18889 mcr.microsoft.com/dotnet/aspire-dashboard:latest

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddAspNetCoreInstrumentation()
        .AddOtlpExporter())
    .WithMetrics(metrics => metrics
        .AddAspNetCoreInstrumentation()
        .AddRuntimeInstrumentation()
        .AddOtlpExporter())
    .UseOtlpExporter(OtlpExportProtocol.Grpc,
        new Uri("http://localhost:4317"));

// http://localhost:18888 adresinden trace, metrik ve log görüntüleme