Kodeloka
  1. Kodeloka
  2. Kelas Prometheus
  3. Materi

Modul 8 ยท Modul 8 dari 15

Agregasi, Operator & Menghitung SLI

Menggabungkan ribuan time series menjadi angka yang bermakna, dan merangkainya menjadi indikator kualitas layanan.

Operator Agregasi

agregasipromql
sum(...)            # jumlahkan
avg(...)            # rata-rata
min(...) / max(...)
count(...)          # berapa banyak series
stddev(...) / stdvar(...)
topk(5, ...)        # 5 nilai tertinggi
bottomk(5, ...)     # 5 nilai terendah
quantile(0.95, ...) # persentil ANTAR-SERIES (bukan antar-waktu!)
count_values("versi", app_build_info)   # hitung berapa series per nilai

by vs without

by-withoutpromql
# PERTAHANKAN hanya label yang disebut
sum by (job, instance) (rate(http_requests_total[5m]))

# BUANG label yang disebut, pertahankan sisanya
sum without (instance, pod) (rate(http_requests_total[5m]))

# Tanpa keduanya: semua label hilang, hasilnya satu angka
sum(rate(http_requests_total[5m]))
๐Ÿ’ก Kapan pakai without

Gunakan without bila Anda ingin membuang satu-dua label tapi mempertahankan sisanya yang mungkin belum Anda ketahui. Contoh: menggabungkan semua pod dalam satu deployment sambil tetap mempertahankan label namespace, service, route, dan label lain yang mungkin ditambahkan tim lain nanti.

Dengan by, label baru akan hilang diam-diam; dengan without, label baru otomatis terbawa.

Operator Aritmatika & Pencocokan Label

Saat dua vektor dioperasikan, Prometheus mencocokkan series berdasarkan seluruh label yang sama persis. Bila tidak ada yang cocok, hasilnya kosong โ€” dan ini sumber frustrasi yang sangat umum.

aritmatikapromql
# Cocok karena label kedua sisi identik
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes

# TIDAK cocok โ€” label berbeda -> hasil kosong
sum by (job) (rate(a_total[5m])) / sum by (instance) (rate(b_total[5m]))

# Solusi: samakan label yang dipakai untuk agregasi
sum by (job) (rate(a_total[5m])) / sum by (job) (rate(b_total[5m]))

# Atau batasi label yang dicocokkan
rate(a_total[5m]) / on (instance) rate(b_total[5m])
rate(a_total[5m]) / ignoring (status) rate(b_total[5m])

Operator Perbandingan & Logika

perbandinganpromql
# Menyaring: hanya series yang memenuhi kondisi yang dikembalikan
node_load1 > 4

# bool: mengubah hasil menjadi 0 atau 1, semua series dipertahankan
node_load1 > bool 4

# Operator himpunan
up == 1 and on (instance) node_load1 > 4      # keduanya benar
up == 0 or absent(up)                          # salah satu benar
rate(a[5m]) unless on (instance) rate(b[5m])   # a yang TIDAK punya pasangan b
โš ๏ธ > menyaring, > bool menandai

node_load1 > 4 hanya mengembalikan instance dengan load di atas 4 โ€” instance yang sehat hilang dari hasil. Untuk grafik "berapa persen instance yang bermasalah", Anda butuh semua series tetap ada:

promql
avg(node_load1 > bool 4)   # proporsi instance dengan load > 4

Merangkai SLI (Service Level Indicator)

SLI adalah rasio "kejadian baik" dibagi "total kejadian". Inilah cara SRE mengukur kualitas layanan.

slipromql
# SLI Ketersediaan: proporsi request yang tidak error
sum(rate(http_requests_total{status!~"5.."}[30d]))
  / sum(rate(http_requests_total[30d]))

# SLI Latency: proporsi request yang lebih cepat dari 300 ms
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[30d]))
  / sum(rate(http_request_duration_seconds_count[30d]))

# Error budget tersisa (SLO 99,9%)
# 1 - (error yang sudah terjadi / error yang diizinkan)
1 - (
  sum(increase(http_requests_total{status=~"5.."}[30d]))
  / (0.001 * sum(increase(http_requests_total[30d])))
)
๐Ÿ“Œ Error budget โ€” konsep yang mengubah cara tim bekerja

SLO 99,9% berarti Anda "boleh" gagal 0,1% dari total request. Itulah error budget Anda.

  • Budget masih banyak โ†’ tim boleh rilis fitur baru dengan agresif.
  • Budget hampir habis โ†’ bekukan rilis, fokus ke stabilitas.

Ini mengubah perdebatan "kapan boleh rilis?" dari adu argumen menjadi keputusan berbasis angka.

topk untuk Investigasi

topkpromql
# 10 endpoint paling lambat
topk(10, histogram_quantile(0.95,
  sum by (le, route) (rate(http_request_duration_seconds_bucket[5m]))))

# 10 container paling boros memori
topk(10, container_memory_working_set_bytes{name!=""})

# 10 metrik dengan time series terbanyak (untuk berburu kardinalitas)
topk(10, count by (__name__)({__name__=~".+"}))

# 5 instance dengan error rate tertinggi
topk(5, sum by (instance) (rate(http_requests_total{status=~"5.."}[5m])))