Ana içeriğe geç

Grafana ile Monitoring Dashboardları

Grafana, metrikleri görselleştirerek sistem sağlığını izlemeyi sağlar; yanlış dashboard tasarımı önemli sorunların gözden kaçmasına yol açar.


1. Tek Büyük Dashboard Oluşturmak

Yanlış Kullanım: Tüm metrikleri tek dashboard’da toplamak.

// Tek dashboard: 50+ panel, yüklenmesi yavaş, kafa karıştırıcı
// CPU, Memory, HTTP istekleri, DB sorguları, Cache, Queue, Business metrikler hepsi bir arada

İdeal Kullanım: Katmanlı dashboard yapısı oluşturun.

// Dashboard hiyerarşisi:
// 1. Overview Dashboard (üst seviye sağlık)
//    - Tüm servislerin durumu (yeşil/kırmızı)
//    - Toplam istek/hata oranı
//    - P95 latency

// 2. Service Dashboard (servis detayı)
//    - HTTP istek metrikleri (RED)
//    - Endpoint bazlı performans
//    - Dependency sağlığı

// 3. Infrastructure Dashboard (altyapı)
//    - CPU, Memory, Disk
//    - Container metrikleri
//    - Network I/O
// Her katman için doğru metrikler
builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddAspNetCoreInstrumentation()  // HTTP metrikleri
        .AddRuntimeInstrumentation()      // GC, ThreadPool
        .AddProcessInstrumentation()      // CPU, Memory
        .AddPrometheusExporter());

2. Variable Kullanmamak

Yanlış Kullanım: Her servis için ayrı dashboard oluşturmak.

// order-service-dashboard
// payment-service-dashboard
// inventory-service-dashboard
// Aynı panel yapısı tekrarlanır, bakım zorlaşır

İdeal Kullanım: Template variable ile dinamik dashboard yapın.

{
  "templating": {
    "list": [
      {
        "name": "service",
        "type": "query",
        "query": "label_values(http_server_requests_total, service_name)",
        "multi": false
      },
      {
        "name": "environment",
        "type": "query",
        "query": "label_values(http_server_requests_total, deployment_environment)",
        "current": { "text": "production" }
      }
    ]
  }
}
// Grafana panel sorgusu - variable kullanımı
rate(http_server_requests_total{service_name="$service", deployment_environment="$environment"}[5m])

3. Alert Eşiklerini Yanlış Belirlemek

Yanlış Kullanım: Sabit eşikler ile çok fazla false positive.

// Alert: CPU > 50% → her yoğun saatte uyarı gelir
// Alert: Response time > 100ms → normal varyasyonlarda bile tetiklenir
// Alert fatigue: ekip uyarıları görmezden gelmeye başlar

İdeal Kullanım: Anomali bazlı ve anlamlı eşikler kullanın.

# Grafana alert rules
- alert: HighErrorRate
  condition: rate(errors) / rate(requests) > 0.01
  for: 5m
  # %1'den fazla hata 5 dakika boyunca devam ederse

- alert: LatencyAnomaly
  condition: p95_latency > avg_over_time(p95_latency[7d]) * 2
  for: 10m
  # Son 7 günlük ortalamadan 2 kat fazla latency

- alert: SaturationWarning
  condition: container_memory_usage / container_memory_limit > 0.85
  for: 15m
  # Bellek kullanımı %85'in üzerinde

4. SLO Dashboard’u Oluşturmamak

Yanlış Kullanım: Sadece teknik metrikleri izlemek.

// Dashboard'da sadece CPU, Memory, Request count var
// "Kullanıcı deneyimi nasıl?" sorusuna cevap yok

İdeal Kullanım: SLI/SLO bazlı dashboard oluşturun.

// SLI metrikleri tanımlama
public class SloMetrics
{
    private readonly Counter<long> _totalRequests;
    private readonly Counter<long> _successfulRequests;

    public SloMetrics(IMeterFactory meterFactory)
    {
        var meter = meterFactory.Create("SLO");
        _totalRequests = meter.CreateCounter<long>("slo.requests.total");
        _successfulRequests = meter.CreateCounter<long>("slo.requests.successful");
    }

    public void Record(string sloName, bool success)
    {
        _totalRequests.Add(1, new("slo", sloName));
        if (success)
            _successfulRequests.Add(1, new("slo", sloName));
    }
}
// Grafana SLO panel sorguları
// Availability SLO: %99.9
sum(rate(slo_requests_successful_total{slo="availability"}[30d]))
/
sum(rate(slo_requests_total{slo="availability"}[30d]))

// Error Budget kalan
1 - ((1 - availability_ratio) / (1 - 0.999))

5. Data Source’ları Birleştirmemek

Yanlış Kullanım: Tek kaynak ile sınırlı görünüm.

// Sadece Prometheus metrikleri
// Log, trace ve metrik arasında bağlantı yok

İdeal Kullanım: Grafana’da çoklu data source’ları birleştirin.

# docker-compose.yml - Grafana stack
grafana:
  image: grafana/grafana:latest
  environment:
    - GF_AUTH_ANONYMOUS_ENABLED=true
  volumes:
    - ./grafana/provisioning:/etc/grafana/provisioning

# provisioning/datasources/datasources.yml
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    url: http://prometheus:9090
    isDefault: true

  - name: Jaeger
    type: jaeger
    url: http://jaeger:16686

  - name: Elasticsearch
    type: elasticsearch
    url: http://elasticsearch:9200
    jsonData:
      index: "app-*"
      timeField: "@timestamp"
// Exemplar desteği ile metrik → trace bağlantısı
builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddPrometheusExporter(options =>
        {
            options.OpenMetricsEnabled = true; // Exemplar desteği
        }));