Kenapa Counter Butuh Perlakuan Khusus
Counter hanya naik — kecuali saat aplikasi restart, ketika nilainya kembali ke nol. Bila Anda menghitung selisih secara naif, restart akan menghasilkan angka negatif yang tidak masuk akal.
waktu nilai
14:00 1000
14:01 1200
14:02 1400
14:03 50 ← aplikasi restart!
14:04 280
Selisih naif 14:02 → 14:03 = 50 - 1400 = -1350 ❌ tidak masuk akal
rate() paham ini restart, dan menghitungnya sebagai 1400→(reset)→50Tiga Fungsi Counter
| Fungsi | Menghitung | Satuan | Kapan dipakai |
|---|---|---|---|
rate(m[5m]) | Laju rata-rata sepanjang rentang | per detik | Default. Untuk grafik & alert. |
irate(m[5m]) | Laju dari dua sampel terakhir saja | per detik | Grafik yang butuh detail lonjakan cepat |
increase(m[1h]) | Total kenaikan sepanjang rentang | jumlah absolut | "Berapa error dalam 1 jam?" |
irate() untuk alertingirate() hanya melihat dua sampel terakhir. Ia sangat sensitif dan berisik — satu lonjakan sesaat langsung terlihat sebagai puncak tajam. Alert yang dibangun di atasnya akan berbunyi terus-menerus untuk hal-hal yang sebenarnya normal, dan pada akhirnya tim akan mematikan notifikasinya (alert fatigue).
Untuk alert selalu pakai rate() dengan rentang yang cukup lebar (5m–15m) sehingga fluktuasi sesaat teredam.
Perilaku Ekstrapolasi yang Membingungkan
Ini penyebab pertanyaan "kenapa jumlah errornya 4,7 padahal error itu bilangan bulat?".
rate() dan increase() melakukan ekstrapolasi: mereka mencocokkan hasil ke rentang penuh yang Anda minta, meskipun sampel yang tersedia tidak persis menutupi rentang itu.
# scrape_interval 15s, rentang 1m -> hanya ada 4-5 sampel
increase(http_errors_total[1m]) # bisa menghasilkan 4.7, bukan 5
# Ini BUKAN bug. Prometheus mengekstrapolasi agar hasilnya
# konsisten untuk rentang waktu apa pun.- Untuk alert, angka pecahan tidak masalah — bandingkan saja dengan ambang:
increase(errors_total[5m]) > 10. - Untuk laporan yang butuh bilangan bulat, gunakan rentang yang jauh lebih besar (
[24h]) sehingga efek ekstrapolasi menjadi tidak berarti, lalu bungkus denganround(). - Jangan pernah memakai rentang yang lebih kecil dari 4× scrape_interval.
Urutan yang Benar: rate() Dulu, Baru sum()
rate(sum(http_requests_total)[5m:])
# sum() menggabungkan semua instance dulu.
# Saat SATU instance restart, jumlah gabungan
# ikut turun -> terlihat seperti reset global
# padahal instance lain baik-baik saja.sum(rate(http_requests_total[5m]))
# rate() dihitung per time series lebih dulu,
# sehingga tiap instance ditangani sendiri,
# baru hasilnya dijumlahkan.Selalu rate() di dalam, agregasi di luar. Pola sum(rate(...)) benar; rate(sum(...)) hampir selalu salah.
Fungsi Terkait Lainnya
# Untuk GAUGE (bukan counter):
delta(node_memory_MemAvailable_bytes[1h]) # perubahan mentah, boleh negatif
deriv(node_filesystem_avail_bytes[1h]) # laju perubahan per detik (regresi linear)
predict_linear(node_filesystem_avail_bytes[6h], 4*3600) # prediksi 4 jam ke depan
# Menghitung perubahan nilai
changes(process_start_time_seconds[1h]) # berapa kali aplikasi restart
resets(http_requests_total[1h]) # berapa kali counter ter-reset
# Contoh alert kapasitas yang sangat berguna:
predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[6h], 4*3600) < 0delta() dan deriv() hanya untuk GaugeKeduanya tidak menangani counter reset. Memakainya pada counter akan menghasilkan angka negatif besar setiap kali aplikasi restart, yang bisa memicu alert palsu.