1. Kenapa Log Saja Tidak Cukup
Pengguna melapor: "checkout lambat, sekitar 8 detik" Log Layanan Pesanan : "memproses pesanan p-1001" ... 8,2 detik Log Layanan Stok : "cek stok" ... 0,1 detik Log Layanan Harga : "hitung diskon" ... 0,2 detik Log Layanan Pembayaran : "tagih kartu" ... 0,3 detik Total yang terlihat: 0,6 detik. Lalu 7,6 detik sisanya ke mana?
Tanpa tracing, Anda hanya punya potongan-potongan terpisah tanpa tahu urutan, hubungan induk-anak, dan celah waktu di antaranya. Tracing menyusun potongan itu menjadi satu lini masa utuh.
2. Trace, Span, dan Hubungan Induk-Anak
Trace ID: 4bf92f3577b34da6a3ce929d0e0e4736 ├─ POST /checkout 8,20 dtk [Gateway] │ ├─ POST /pesanan 8,15 dtk [Layanan Pesanan] │ │ ├─ SELECT pengguna 0,02 dtk [PostgreSQL] │ │ ├─ GET /stok/cek 0,10 dtk [Layanan Stok] │ │ ├─ GET /harga/hitung 0,20 dtk [Layanan Harga] │ │ ├─ ⚠ SELECT riwayat_pesanan 7,50 dtk [PostgreSQL] <-- INI │ │ └─ POST /pembayaran 0,30 dtk [Layanan Pembayaran] │ └─ serialisasi respons 0,05 dtk
Ketemu: sebuah kueri database tanpa indeks. Tanpa tracing, menemukan ini bisa memakan waktu berhari-hari.
| Istilah | Arti |
|---|---|
| Trace | Seluruh perjalanan satu permintaan lintas semua layanan |
| Span | Satu satuan pekerjaan: panggilan HTTP, kueri DB, pemrosesan pesan |
| Trace ID | Pengenal 16 byte, sama untuk seluruh perjalanan |
| Span ID | Pengenal 8 byte untuk satu span |
| Parent Span ID | Yang membentuk struktur pohon |
| Attribute | Pasangan kunci-nilai: http.method, db.statement, pengguna.id |
| Event | Penanda waktu di dalam span, misal "cache miss" |
3. Context Propagation — Bagian yang Paling Sering Rusak
Agar trace tersambung, konteksnya harus ikut mengalir bersama setiap panggilan. Standarnya adalah header W3C Trace Context.
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
│ │ │ │
│ │ │ └─ flag (01 = direkam)
│ │ └─ parent span id
│ └─ trace id
└─ versi
tracestate: vendor1=nilai,vendor2=nilai (opsional, khusus vendor)
Propagasi otomatis biasanya berjalan mulus untuk HTTP dan gRPC. Yang sering putus adalah saat pesan masuk ke antrian. Bila Anda menerbitkan ke RabbitMQ atau Kafka tanpa menyisipkan traceparent ke header pesan, consumer akan memulai trace yang benar-benar baru — dan hubungan sebab-akibatnya hilang. Sisipkan konteks ke header pesan saat menerbitkan, dan ekstrak kembali saat mengonsumsi.
4. OpenTelemetry — Standar Netral Vendor
Aplikasi (SDK OpenTelemetry)
│ protokol OTLP
▼
OpenTelemetry Collector ← satu titik untuk memproses semuanya
│ │ │
▼ ▼ ▼
Tempo Jaeger Prometheus / Loki / vendor komersial
- Aplikasi tidak perlu tahu tujuan akhirnya. Ganti backend cukup dengan mengubah konfigurasi Collector, tanpa deploy ulang seluruh layanan.
- Tempat menyaring data sensitif sebelum keluar dari jaringan Anda.
- Tempat mengatur sampling secara terpusat.
- Buffer saat backend sedang tidak tersedia.
- Menambahkan atribut seragam seperti nama kluster, wilayah, dan lingkungan.
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
processors:
batch:
timeout: 5s
memory_limiter:
limit_mib: 512
attributes:
actions:
- key: pengguna.email # jangan pernah kirim PII keluar
action: delete
exporters:
otlp/tempo:
endpoint: tempo:4317
prometheus:
endpoint: 0.0.0.0:8889
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, attributes, batch]
exporters: [otlp/tempo]
5. Sampling — Anda Tidak Bisa Menyimpan Semuanya
| Strategi | Cara kerja | Catatan |
|---|---|---|
| Head sampling | Diputuskan di awal, misal simpan 10% acak | Murah, tapi trace yang error bisa ikut terbuang |
| Tail sampling | Diputuskan setelah trace selesai | Bisa menyimpan semua yang error dan lambat; butuh memori di Collector |
| Berbasis aturan | Selalu simpan endpoint kritis, sampel jarang untuk health check | Paling praktis di produksi |
Simpan 100% trace yang mengandung error atau melebihi ambang latensi, dan 1–5% dari trace normal. Anda tetap punya gambaran statistik dari sampel, sekaligus memiliki bukti lengkap untuk setiap kejadian yang benar-benar penting.
6. Menghubungkan Tiga Pilar
METRIK (Prometheus) -> "ada apa?" Tingkat error naik ke 5% │ exemplar: trace_id ▼ TRACE (Tempo) -> "di mana?" Layanan Pembayaran, span 7,5 dtk │ trace_id ▼ LOG (Loki) -> "kenapa?" "connection pool exhausted"
{
"waktu": "2026-07-28T10:15:32Z",
"level": "error",
"layanan": "pembayaran",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"pesan": "kolam koneksi habis",
"pesanan_id": "p-1001"
}
Dengan ini, dari satu trace yang lambat Anda bisa langsung melompat ke semua log yang dihasilkan permintaan itu — di seluruh layanan sekaligus. Inilah yang mengubah investigasi insiden dari berjam-jam menjadi beberapa menit.
7. Metrik yang Perlu Dipantau: Metode RED
R - Rate : jumlah permintaan per detik E - Errors : jumlah permintaan yang gagal per detik D - Duration : distribusi lama pemrosesan (p50, p95, p99) Untuk sumber daya, pakai metode USE: U - Utilization : persentase pemakaian S - Saturation : panjang antrian E - Errors : jumlah kesalahan
Latensi rata-rata 200 ms terdengar bagus. Tetapi bila p99 adalah 8 detik, satu dari seratus permintaan sangat buruk — dan pengguna yang membuka sepuluh halaman punya peluang besar merasakannya. Selalu pantau persentil, bukan rata-rata. Untuk sistem yang serius, pantau juga p99,9.
8. Kesalahan Umum
- Kardinalitas metrik meledak. Jangan pernah menjadikan ID pengguna, ID pesanan, atau URL lengkap sebagai label metrik — itu membuat Prometheus kehabisan memori. Informasi berkardinalitas tinggi tempatnya di trace dan log, bukan metrik.
- Log tanpa struktur. Log berbentuk kalimat bebas tidak bisa dikueri. Gunakan JSON dengan field yang konsisten.
- Data pribadi di dalam span. Email, nomor kartu, dan token tidak boleh masuk ke atribut span. Saring di Collector.
- Instrumentasi hanya di batas HTTP. Span yang tidak mencakup kueri database dan panggilan cache menyembunyikan justru bagian yang paling sering menjadi biang keladi.
- Alert pada gejala, bukan penyebab. Beri alert pada hal yang dirasakan pengguna (tingkat error, latensi), bukan pada "CPU 80%" yang belum tentu berarti apa-apa.