Monitoring adalah mengamati angka-angka sistem yang sedang jalan dan diberi tahu saat ada yang gak beres. Logging adalah mencatat kejadian di sistem supaya bisa dibaca belakangan. Bayangin dashboard mobil. Sekali lirik kamu tahu kecepatan, sisa bensin, dan suhu mesin, dan lampu peringatan menyala sendiri saat oli habis. Itu monitoring dan alert. Buku servis di laci yang mencatat apa yang pernah diperbaiki dan kapan, itu log. Tanpa keduanya, kamu baru tahu ada masalah saat mobilnya mogok di jalan tol, atau di dunia aplikasi, saat pengguna marah-marah di media sosial.
🧪 Tebakan cepat: jam 10.01 saat war tiket, rata-rata latency TiketNada 310 ms. Apakah pengguna baik-baik saja? Tebak dulu, jawabannya ada di bagian "Rata-rata menipu: percentile".
Tiga pilar: logs, metrics, traces
Data yang dikumpulkan dari sistem yang jalan ada tiga jenis, disebut three pillars of observability:
- Logs: catatan per kejadian. "Jam 10:02:13, service
order, pesanan Budi gagal: timeout menunggu koneksi database." Detail, tapi banyak sekali. - Metrics: angka yang dihitung terus-menerus dan disimpan per waktu (time series), misalnya jumlah request per detik atau persen error per menit. Ringkas dan murah, cocok untuk dashboard dan alert.
- Traces: jejak satu request saat melewati banyak service, lengkap dengan waktu di tiap service.
Log sebaiknya terstruktur (JSON), bukan kalimat bebas, supaya bisa difilter per field:
{"ts":"2026-10-09T10:02:13.482+07:00","level":"error","service":"order","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","route":"POST /api/orders","status":503,"duration_ms":5003,"msg":"timeout menunggu koneksi database"}
level menandai beratnya: debug (detail untuk development), info (kejadian normal), warn (perlu diperhatikan), error (operasi gagal). Jangan pernah mencatat password, token, atau nomor kartu. Cara menulis log yang baik ada di lesson Application Logging (track DevOps).
Empat golden signals
Dari semua metric yang bisa diukur, empat ini yang paling dulu dipasang untuk tiap service. Google menyebutnya four golden signals:
| Signal | Artinya | Di TiketNada |
|---|---|---|
| Latency | berapa lama request dilayani | p95 waktu response |
| Traffic | seberapa banyak permintaan | request per detik (QPS) |
| Errors | berapa yang gagal | persen response 5xx |
| Saturation | seberapa penuh resource | pemakaian connection pool database |
Ini dashboard TiketNada saat war tiket (model contoh). Database punya connection pool 100 koneksi; request yang gak kebagian koneksi menunggu, dan menyerah setelah 5 detik dengan 503.
| Menit | Traffic (QPS) | Errors | p95 latency | DB pool |
|---|---|---|---|---|
| 09:58 | 231 | 0,1% | 120 ms | 12% |
| 09:59 | 694 | 0,1% | 125 ms | 18% |
| 10:00 | 11.574 | 0,4% | 380 ms | 78% |
| 10:01 | 11.900 | 2,8% | 1.900 ms | 100% |
| 10:02 | 11.300 | 6,1% | 2.600 ms | 100% |
| 10:03 | 9.800 | 4,0% | 2.100 ms | 100% |
| 10:04 | 7.400 | 0,6% | 520 ms | 64% |
| 10:05 | 5.100 | 0,2% | 210 ms | 41% |
Cara membacanya: traffic melonjak 50 kali jam 10:00. Yang pertama mentok adalah saturation: pool penuh di 10:01. Akibatnya request antre, latency naik, lalu yang antre lebih dari 5 detik jadi error. Jam 10:03 on-call menaikkan pool jadi 300 koneksi, dan dua menit kemudian semuanya normal. Saturation sering jadi sinyal paling awal: dia naik sebelum pengguna merasakan apa-apa.
Untuk service, versi pendeknya disebut RED (Rate, Errors, Duration). Untuk resource seperti CPU, disk, atau pool, disebut USE (Utilization, Saturation, Errors).
Rata-rata menipu: percentile
Ini latency 10 request (ms): 40, 42, 45, 45, 48, 50, 52, 55, 60, 2.400. Rata-ratanya 2.837 ÷ 10 = 283,7 ms, angka yang gak dialami satu pengguna pun: sembilan orang di bawah 60 ms, satu orang menunggu 2,4 detik.
Percentile menjawab lebih jujur. Urutkan semua latency; p50 adalah nilai yang 50% request ada di bawahnya, p95 95%, p99 99%. Dari 10 request tadi: p50 = 48 ms (urutan ke-5), p90 = 60 ms (ke-9), p99 = 2.400 ms (ke-10).
Jadi jawaban tebakannya: belum tentu. Di menit 10:01, rata-rata 310 ms kelihatan wajar, tapi p95-nya 1.900 ms dan p99-nya 4.800 ms: satu dari seratus pembeli menunggu hampir 5 detik, tepat di depan batas timeout. Dashboard yang baik menampilkan p95 atau p99, bukan rata-rata.
Alert: dashboard yang bisa membangunkan orang
Gak ada yang menatap dashboard 24 jam. Alert adalah aturan yang dicek terus, dan mengirim pesan saat terpenuhi. Supaya gak berisik, aturan biasanya pakai "selama N menit".
// TiketNada, model contoh: kapan tiap alert mulai menyala
const menit = ["09:58", "09:59", "10:00", "10:01", "10:02", "10:03", "10:04", "10:05"];
const errorPct = [0.1, 0.1, 0.4, 2.8, 6.1, 4.0, 0.6, 0.2];
const p95 = [120, 125, 380, 1900, 2600, 2100, 520, 210];
const dbPool = [12, 18, 78, 100, 100, 100, 64, 41];
const aturan = [
{ nama: "DB pool di atas 90%", nilai: dbPool, batas: 90, selama: 1, aksi: "page on-call" },
{ nama: "error rate di atas 1%", nilai: errorPct, batas: 1, selama: 2, aksi: "page on-call" },
{ nama: "p95 di atas 1.000 ms", nilai: p95, batas: 1000, selama: 2, aksi: "pesan Slack" },
];
for (let i = 0; i < menit.length; i++) {
for (const a of aturan) {
let berturut = 0; // berapa menit terakhir yang melewati batas
for (let j = i; j >= 0 && a.nilai[j] > a.batas; j--) berturut++;
if (berturut === a.selama) console.log(menit[i], "ALERT:", a.nama, "->", a.aksi);
}
}
// 10:01 ALERT: DB pool di atas 90% -> page on-call
// 10:02 ALERT: error rate di atas 1% -> page on-call
// 10:02 ALERT: p95 di atas 1.000 ms -> pesan Slack
- Tiap baris
aturanpunya batas, durasi (selama), dan aksi. "Page on-call" artinya menelepon engineer yang sedang jaga. - Loop dalam menghitung
berturut: berapa menit terakhir nilainya di atas batas, tanpa putus. - Alert menyala saat
berturutpas mencapaiselama. Error 2,8% di 10:01 baru satu menit, jadi alert error menunggu sampai 10:02.
Alert yang baik actionable: yang menerima tahu harus berbuat apa, idealnya ada runbook (catatan langkah penanganan). Alert yang terlalu banyak membuat orang mengabaikan semuanya (alert fatigue). Lebih lanjut di lesson Metrics & Monitoring (track DevOps).
Trace dan correlation ID
Error di menit 10:02 muncul di service order, tapi request-nya lewat gateway dulu. Supaya semua catatan tentang satu request bisa disatukan, request diberi trace ID unik (disebut juga correlation ID) di pintu masuk, lalu ID itu diteruskan ke tiap service lewat header. Standarnya W3C Trace Context:
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
Bagian kedua (32 karakter hex) adalah trace ID. Semua log, metric, dan span dari request itu ditandai ID yang sama, jadi filter trace_id=4bf92f35... merekonstruksi perjalanannya walau melewati sepuluh service. Distributed tracing memakai ID ini untuk menggambar perjalanan satu request lewat beberapa service, sehingga kelihatan service mana yang membuatnya lambat atau error:
trace 4bf92f35... POST /api/orders 5.008 ms 503
├─ gateway 2 ms
└─ order 5.006 ms
└─ menunggu koneksi database 5.000 ms <- di sini
Alat dan cara memasangnya (OpenTelemetry, Jaeger, sampling) ada di lesson Distributed Tracing (track DevOps).
Cardinality: label yang meledak
Metric bisa diberi label, misalnya http_requests_total{route, status, instance}. Tiap kombinasi nilai label jadi time series sendiri. TiketNada punya 6 route, 5 status, dan 3 instance (app-1 sampai app-3): 6 × 5 × 3 = 90 time series. Tambahkan label user_id untuk 1.000.000 pengguna harian: 90 × 1.000.000 = 90 juta time series, dan penyimpanan metric-nya meledak. Jumlah nilai unik sebuah label disebut cardinality. Identitas seperti user_id atau request_id tempatnya di log dan trace, bukan di label metric.
🤔 Monitoring vs observability
Monitoring melacak metric yang sudah kamu tahu penting: CPU, error rate, p95, dan alert untuk masalah yang sudah kamu duga. Observability adalah kemampuan memahami kondisi di dalam sistem dari output-nya (logs, metrics, traces), termasuk untuk masalah yang belum pernah terjadi dan gak pernah kamu siapkan dashboard-nya. Monitoring menjawab "ada yang rusak?", observability membantu menjawab "kenapa?".
⚠️ Jebakan yang sering ketemu
- Melihat rata-rata latency. Rata-rata menyembunyikan ekor. Pantau p95 dan p99.
- Label high-cardinality di metric.
user_idsebagai label membuat jutaan time series. Simpan di log atau trace. - Alert untuk segalanya. Alert yang gak butuh tindakan melatih orang untuk mengabaikan alert. Tiap alert harus actionable dan punya runbook.
- Mencatat data sensitif. Password, token, dan nomor kartu di log adalah kebocoran yang menunggu waktu.
TL;DR: Monitoring = mengamati angka sistem dan diberi tahu lewat alert; logging = mencatat kejadian. Tiga pilar observability: logs (catatan per kejadian, sebaiknya JSON terstruktur), metrics (angka per waktu), dan traces (jejak satu request lewat banyak service). Pasang four golden signals: latency, traffic, errors, saturation; saat war tiket TiketNada, saturation (DB pool 100%) naik duluan di 10:01, sebelum error. Pakai percentile, bukan rata-rata: rata-rata 310 ms bisa menyembunyikan p99 4.800 ms. Alert pakai batas plus durasi, harus actionable. Trace ID (correlation ID) diteruskan lewat header traceparent supaya semua log dan span satu request bisa disatukan; distributed tracing menunjukkan service mana yang lambat. Jangan pakai label high-cardinality: tiap kombinasi label jadi time series sendiri. Monitoring melacak yang sudah diketahui, observability membantu memahami masalah baru.