Metric adalah angka yang diukur berulang-ulang dan disimpan bersama waktunya, jadi deretan titik yang membentuk grafik (time series). Monitoring artinya memantau angka-angka itu terus-menerus. Bayangin dasbor mobil. Odometer cuma bisa naik: total kilometer sejak mobil dibuat. Speedometer naik turun: kecepatan saat ini. Dan buku catatan perjalanan yang mengelompokkan perjalanan menurut lamanya: berapa yang di bawah 15 menit, berapa yang di bawah 30 menit. Tiga alat itu persis tiga jenis metric: counter, gauge, dan histogram.
Log menceritakan satu kejadian, error tracking mengelompokkan error. Metrics menjawab pertanyaan "seberapa banyak" dan "seberapa cepat" untuk semua request sekaligus, dengan biaya kecil: satu angka per metric, bukan satu baris per request.
🧪 Tebakan cepat: dari 100 request
GET /catatanterakhir, 97 selesai dalam 17 sampai 104 ms, dan 3 butuh 2,4 detik karena query dingin. Rata-ratanya sekitar 45 ms, 115 ms, atau 2,4 detik? Dan p50-nya? Jawabannya ada di bagian "Kenapa rata-rata berbohong".
Tiga jenis metric
| Jenis | Sifatnya | Contoh di catatan-api |
|---|---|---|
| counter | cuma naik, kembali ke 0 saat app restart | http_requests_total: request yang sudah dilayani |
| gauge | naik dan turun, yang penting nilainya sekarang | http_requests_in_flight: request yang sedang diproses, memori terpakai |
| histogram | menghitung berapa nilai jatuh di tiap bucket | http_request_duration_seconds: durasi request |
Angka counter sendiri gak berguna; 18.342 request sejak kapan? Yang dibaca kecepatannya: selisih dua pengukuran dibagi jarak waktunya. Histogram menyimpan hitungan per batas atas (le, less or equal): berapa request di bawah 0,05 detik, di bawah 0,1 detik, dan seterusnya. Dari situ persentil diperkirakan.
Persentil: p50, p95, p99
pX adalah durasi yang gak dilewati oleh X% request. p95 = 75 ms artinya 95 dari 100 request selesai dalam 75 ms atau kurang. p50 juga disebut median: titik tengah. Cara menghitungnya (metode nearest rank):
function calculatePercentile(values, percentile) {
const sorted = [...values].sort((a, b) => a - b); // salinan, urut naik
const index = Math.ceil((percentile * sorted.length) / 100) - 1;
return sorted[index];
}
| Panggilan | Urutan | Posisi | Hasil |
|---|---|---|---|
calculatePercentile([10, 20, 30, 40, 50], 50) |
10 20 30 40 50 | ceil(2,5) - 1 = 2 | 30 |
calculatePercentile([10, 20, 30, 40, 50], 95) |
10 20 30 40 50 | ceil(4,75) - 1 = 4 | 50 |
calculatePercentile([5, 3, 1, 4, 2], 20) |
1 2 3 4 5 | ceil(1) - 1 = 0 | 1 |
[...values]membuat salinan, jadi array milik pemanggil gak ikut teracak olehsort.(a, b) => a - bwajib. Tanpa pembanding,sortmengurutkan angka sebagai teks:[3, 25, 100].sort()jadi[100, 25, 3].Math.ceilmembulatkan ke atas posisi versi manusia (ke-1 sampai ke-n), lalu- 1mengubahnya jadi index array yang mulai dari 0.
Prometheus menghitung persentil dari bucket histogram dengan histogram_quantile, jadi hasilnya perkiraan, tapi artinya sama.
Kenapa rata-rata berbohong
Ini 100 request di Lab, sebelum dan sesudah 3 di antaranya kena query dingin 2,4 detik:
| rata-rata | p50 | p95 | p99 | |
|---|---|---|---|---|
| tanpa request lambat | 45,0 ms | 43 ms | 68 ms | 80 ms |
| 3 request 2.400 ms | 115,5 ms | 43 ms | 75 ms | 2.400 ms |
Rata-ratanya 115,5 ms dan p50-nya tetap 43 ms. Itu jawaban tebakannya. Padahal gak ada satu request pun yang butuh 115 ms: 97 request di bawah 105 ms, dan 3 request 2.400 ms. Rata-rata mencampur dua kelompok jadi angka yang gak menggambarkan siapa pun. p50 gak bergeser, karena median gak peduli seberapa lambat ekornya. p99 yang menangkapnya: lebih dari 1 dari 100 user menunggu 2,4 detik. Karena itu latency dipantau di p95 dan p99, ditemani p50.
RED, USE, dan four golden signals
Supaya gak tenggelam di ratusan metric, ada tiga daftar pegangan:
- RED, untuk service seperti catatan-api: Rate (request per detik), Errors (persen request yang gagal), Duration (p95 dan p99 durasi).
- USE, untuk resource seperti CPU, memori, disk
web-1, dan pool koneksi database: Utilization (seberapa sibuk), Saturation (seberapa banyak yang antre), Errors. - Four golden signals dari buku SRE Google, gabungan keduanya: latency, traffic, errors, saturation.
Monitoring menjawab pertanyaan yang sudah kamu tahu sebelumnya: "apakah error rate di atas 5%?", lewat dashboard dan alert. Observability adalah kemampuan menjawab pertanyaan baru yang belum terpikir: "kenapa cuma request user di Surabaya yang lambat?", dengan menggabungkan metrics, log, dan trace. Trace dibahas di pelajaran OpenTelemetry Fundamentals dan Distributed Tracing.
Prometheus: scrape /metrics
catatan-api menyediakan semua angkanya di satu halaman, /metrics, dengan library prom-client:
const client = require("prom-client");
client.collectDefaultMetrics(); // memori, CPU, event loop Node
const requests = new client.Counter({ name: "http_requests_total", help: "Total HTTP requests", labelNames: ["method", "route", "status_code"] });
const inFlight = new client.Gauge({ name: "http_requests_in_flight", help: "Requests being handled right now" });
const duration = new client.Histogram({ name: "http_request_duration_seconds", help: "Request duration in seconds", labelNames: ["route"], buckets: [0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5] });
app.use((req, res, next) => {
inFlight.inc();
const end = duration.startTimer();
res.on("finish", () => {
const route = req.route ? req.route.path : req.path;
requests.inc({ method: req.method, route, status_code: res.statusCode });
end({ route });
inFlight.dec();
});
next();
});
app.get("/metrics", async (req, res) => {
res.set("Content-Type", client.register.contentType);
res.end(await client.register.metrics());
});
Prometheus lalu datang mengambil halaman itu setiap 15 detik. Ini disebut scrape, model pull: app gak mengirim apa-apa, Prometheus yang menarik. Config-nya di prometheus.yml, dengan Prometheus jalan sebagai service lain di Compose yang sama:
scrape_configs:
- job_name: catatan-api
scrape_interval: 15s
static_configs:
- targets: ["app:3000"] # path default: /metrics
Sebagian isi /metrics yang ditarik:
# TYPE http_requests_total counter
http_requests_total{method="GET",route="/catatan",status_code="200"} 18342
# TYPE http_requests_in_flight gauge
http_requests_in_flight 3
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05",route="/catatan"} 72
http_request_duration_seconds_bucket{le="0.1",route="/catatan"} 99
http_request_duration_seconds_bucket{le="+Inf",route="/catatan"} 100
15 detik kemudian counter-nya 18.524, jadi kecepatannya (18.524 - 18.342) / 15 = 12,1 request per detik. Di PromQL, bahasa query Prometheus, itu rate(http_requests_total[1m]). Grafana lalu menggambar angka-angka Prometheus jadi dashboard. Prometheus + Grafana adalah pasangan open source paling umum untuk ini; cara memasangnya ada di pelajaran Grafana & Prometheus Setup.
⚠️ Jebakan yang sering ketemu
- Memantau latency dengan rata-rata. Tiga request lambat menaikkan rata-rata 2,5 kali lipat tanpa menunjukkan siapa yang lambat. Pakai p50, p95, p99.
- Label yang nilainya tak terbatas.
route: "/catatan/812"atauuserIdbikin satu time series per catatan atau per user, sampai Prometheus kehabisan memori. Pakai pola route"/catatan/:id". - Membaca angka counter mentah. Yang penting kecepatannya, lewat
rate(). Dan/metricsjangan ikut dibuka ke internet lewat nginx. - Di latihan:
sort()tanpa pembanding, atau lupa- 1. Tanpa(a, b) => a - b, angka diurutkan sebagai teks. Tanpa- 1, p95 dari lima angka menunjuk index 5, yangundefined.
TL;DR: Metric adalah angka yang diukur berkala jadi time series. Counter cuma naik (dibaca dengan rate()), gauge naik turun (nilainya sekarang), histogram menghitung nilai per bucket untuk persentil. pX = durasi yang gak dilewati X% request; dengan nearest rank: urutkan salinannya pakai (a, b) => a - b, ambil index Math.ceil(percentile * n / 100) - 1. Rata-rata berbohong untuk latency: 3 request 2,4 detik membuat rata-rata 115,5 ms padahal p50 tetap 43 ms, dan cuma p99 (2.400 ms) yang menangkap ekornya. RED (rate, errors, duration) untuk service, USE (utilization, saturation, errors) untuk resource, four golden signals: latency, traffic, errors, saturation. Monitoring mengecek masalah yang sudah dikenal, observability membantu memahami masalah baru. Prometheus men-scrape /metrics tiap 15 detik, Grafana menggambarnya jadi dashboard.