Observability: Logging, Metrics, dan Tracing dalam Sistem Terdistribusi

Bayangkan sebuah request pengguna yang gagal di aplikasi e-commerce: checkout tiba-tiba error 500. Di arsitektur monolitik lama, engineer tinggal membuka satu file log di satu server dan menemukan stack trace-nya dalam hitungan menit. Tapi di arsitektur microservices modern, satu request checkout bisa melewati belasan service berbeda — service auth, service inventory, service payment, service notifikasi — yang masing-masing berjalan di container terpisah, bisa jadi di region berbeda, dengan log tersebar di puluhan instance yang scaling naik-turun secara dinamis. Mencari akar masalah dengan cara lama (SSH ke server, grep log manual) menjadi mustahil. Inilah alasan observability menjadi salah satu disiplin paling penting dalam rekayasa sistem terdistribusi modern — bukan sekadar "nice to have", tapi prasyarat untuk bisa mengoperasikan sistem kompleks dengan percaya diri.
Observability vs Monitoring: Apa Bedanya?
Kedua istilah ini sering dipakai bergantian, padahal maknanya berbeda secara filosofis. Monitoring adalah praktik mengumpulkan metrik yang sudah kita tahu penting, lalu membuat alert ketika nilainya melewati ambang batas — misalnya "beri tahu saya jika CPU usage di atas 80%" atau "beri tahu saya jika response time p99 di atas 500ms". Monitoring menjawab pertanyaan yang sudah kita antisipasi sebelumnya.
Observability adalah properti sistem yang memungkinkan kita memahami kondisi internalnya hanya dari output eksternal (logs, metrics, traces) — termasuk menjawab pertanyaan yang belum pernah kita pikirkan sebelumnya. Istilah ini dipinjam dari teori kontrol (control theory), di mana sebuah sistem disebut "observable" jika kondisi internalnya bisa disimpulkan dari pengamatan output-nya saja. Dalam konteks software, observability yang baik memungkinkan engineer bertanya "kenapa latensi endpoint checkout naik khusus untuk pengguna dari region Jakarta yang memakai metode pembayaran QRIS pada jam 2 siang tadi?" — pertanyaan spesifik yang tidak mungkin diantisipasi lewat dashboard monitoring biasa, tapi bisa dijawab lewat eksplorasi data observability secara ad-hoc.
Singkatnya: monitoring memberi tahu apakah ada masalah, observability membantu memahami kenapa masalah itu terjadi — bahkan untuk skenario yang belum pernah terpikirkan sebelumnya.
Tiga Pilar Observability
Secara tradisional, observability dibangun di atas tiga jenis data (sering disebut "tiga pilar"), yang masing-masing punya kekuatan dan keterbatasan berbeda.
1. Logs (Catatan Peristiwa)
Log adalah catatan diskrit dari suatu peristiwa yang terjadi pada waktu tertentu — biasanya berupa teks atau data terstruktur yang mencatat "apa yang terjadi". Log memberikan detail paling kaya konteks, tapi juga paling mahal untuk disimpan dan dicari dalam skala besar. Log modern idealnya berbentuk structured logging (JSON) alih-alih teks bebas, agar mudah diquery dan diagregasi:
{
"timestamp": "2026-08-09T07:12:33.481Z",
"level": "error",
"service": "payment-service",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"message": "Payment gateway timeout",
"order_id": "ORD-88213",
"payment_method": "qris",
"gateway": "xendit",
"duration_ms": 5023,
"http_status": 504
}
Perhatikan field trace_id dan span_id — inilah kunci untuk menghubungkan log dengan pilar observability lainnya, yang akan dibahas lebih lanjut di bagian korelasi.
2. Metrics (Data Numerik Teragregasi)
Metrics adalah representasi numerik dari suatu ukuran yang diambil sepanjang interval waktu — misalnya jumlah request per detik, penggunaan memori, atau latensi rata-rata. Berbeda dari log yang mencatat setiap peristiwa individual, metrics sudah teragregasi sejak awal (counter, gauge, histogram), sehingga jauh lebih murah disimpan dan divisualisasikan dalam jangka panjang, meski kehilangan detail konteks per-request.
Empat tipe metrik dasar yang umum di sistem seperti Prometheus:
- Counter — nilai yang hanya bertambah, misalnya total request yang diterima.
- Gauge — nilai yang bisa naik-turun, misalnya jumlah koneksi aktif saat ini.
- Histogram — distribusi nilai dalam bucket, misalnya distribusi latensi request (berapa banyak request yang selesai di bawah 100ms, 500ms, 1s, dst).
- Summary — mirip histogram tapi menghitung quantile langsung di sisi client.
3. Traces (Jejak Perjalanan Request)
Trace merekam perjalanan satu request tunggal saat melewati berbagai service dalam sistem terdistribusi. Satu trace terdiri dari banyak span — setiap span merepresentasikan satu unit kerja (misalnya satu pemanggilan fungsi, satu query database, atau satu HTTP call ke service lain), lengkap dengan waktu mulai, durasi, dan metadata terkait. Trace inilah yang memungkinkan kita melihat waterfall diagram: request masuk ke API gateway (5ms) → memanggil auth-service (12ms) → memanggil inventory-service (230ms, ternyata di sinilah bottleneck-nya) → memanggil payment-service (45ms) → response dikembalikan.
Structured Logging dalam Praktik
Migrasi dari log teks bebas ke structured logging adalah salah satu investasi observability dengan ROI tertinggi karena implementasinya relatif sederhana tapi dampaknya besar terhadap kemampuan debugging. Prinsip praktis structured logging yang baik:
- Selalu sertakan level log yang konsisten (debug, info, warn, error, fatal) agar mudah difilter.
- Sertakan trace_id di setiap log yang berkaitan dengan pemrosesan request, agar log dari berbagai service bisa dikorelasikan dalam satu request yang sama.
- Hindari logging data sensitif (password, token, nomor kartu kredit) — ini pelanggaran keamanan yang sering terlewat, terutama saat logging payload request/response mentah.
- Gunakan field yang konsisten antar service — misalnya semua service memakai nama field
user_id, bukan campuranuserId,uid, danuser_iddi service berbeda, karena inkonsistensi ini menyulitkan query lintas service. - Log peristiwa penting, bukan setiap baris kode. Over-logging (misalnya log di setiap iterasi loop) menciptakan noise yang justru menyulitkan menemukan sinyal penting saat debugging insiden nyata.
Metrics dengan Prometheus
Prometheus adalah salah satu sistem metrics open-source paling populer, bekerja dengan model pull-based — server Prometheus secara berkala melakukan scrape ke endpoint /metrics yang diekspos aplikasi. Berikut contoh instrumentasi sederhana pada aplikasi Node.js/Express memakai library prom-client:
const client = require('prom-client');
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Durasi request HTTP dalam detik',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.05, 0.1, 0.3, 0.5, 1, 2, 5],
});
app.use((req, res, next) => {
const end = httpRequestDuration.startTimer();
res.on('finish', () => {
end({
method: req.method,
route: req.route ? req.route.path : 'unknown',
status_code: res.statusCode,
});
});
next();
});
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
});
Dengan histogram di atas, kita bisa membuat query PromQL untuk menghitung latensi p95 per endpoint dalam 5 menit terakhir:
histogram_quantile(0.95,
rate(http_request_duration_seconds_bucket[5m])
)
Metrik seperti inilah yang biasanya divisualisasikan di Grafana sebagai dashboard, dan dijadikan dasar alerting — misalnya mengirim notifikasi Slack ketika p95 latency melewati 1 detik selama lebih dari 3 menit berturut-turut.
Distributed Tracing dengan OpenTelemetry
OpenTelemetry (sering disingkat OTel) telah menjadi standar industri untuk instrumentasi observability, menggantikan standar-standar proprietary sebelumnya (seperti OpenTracing dan OpenCensus yang akhirnya melebur menjadi OTel). Keunggulan utamanya adalah vendor-neutral — kita bisa mengirim data trace yang sama ke Jaeger, Zipkin, Datadog, atau backend lain tanpa mengubah kode instrumentasi.
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://otel-collector:4318/v1/traces',
}),
instrumentations: [getNodeAutoInstrumentations()],
serviceName: 'payment-service',
});
sdk.start();
Untuk instrumentasi manual pada bagian kode yang butuh detail lebih spesifik (misalnya proses bisnis kompleks di dalam satu fungsi), kita bisa membuat span secara eksplisit:
const tracer = require('@opentelemetry/api').trace.getTracer('payment-service');
async function processPayment(order) {
return tracer.startActiveSpan('process-payment', async (span) => {
span.setAttribute('order.id', order.id);
span.setAttribute('payment.method', order.paymentMethod);
try {
const result = await callPaymentGateway(order);
span.setStatus({ code: 1 }); // OK
return result;
} catch (err) {
span.recordException(err);
span.setStatus({ code: 2, message: err.message }); // ERROR
throw err;
} finally {
span.end();
}
});
}
Arsitektur OTel modern biasanya melibatkan OpenTelemetry Collector sebagai perantara: aplikasi mengirim data ke collector, lalu collector yang bertanggung jawab melakukan sampling, filtering, batching, dan meneruskan data ke satu atau beberapa backend observability sekaligus — memisahkan urusan instrumentasi aplikasi dari urusan operasional platform observability.
Membangun Observability Stack: Pilihan Populer
| Kebutuhan | Open Source | Managed/Komersial |
|---|---|---|
| Logs | Loki, Elasticsearch (ELK) | Datadog Logs, AWS CloudWatch Logs |
| Metrics | Prometheus + Grafana | Datadog Metrics, Amazon Managed Prometheus |
| Traces | Jaeger, Tempo | Datadog APM, Honeycomb, New Relic |
| Instrumentasi | OpenTelemetry SDK | Vendor SDK proprietary (biasanya lebih mudah setup awal) |
Kombinasi populer di kalangan tim yang mengelola infrastruktur sendiri adalah "LGTM stack": Loki (logs), Grafana (visualisasi), Tempo (traces), dan Prometheus untuk Metrics — semuanya dibangun oleh Grafana Labs dan dirancang saling terintegrasi mulus dari awal, termasuk kemampuan lompat langsung dari satu log entry ke trace terkait hanya dengan satu klik di dashboard Grafana.
Korelasi Antar Pilar: Kunci Observability yang Sesungguhnya
Memiliki logs, metrics, dan traces secara terpisah belum cukup — kekuatan sesungguhnya observability muncul ketika ketiganya bisa saling berkorelasi. Skenario nyata: dashboard Grafana menunjukkan lonjakan error rate pada metric (pilar metrics) → engineer klik pada titik lonjakan tersebut dan langsung diarahkan ke daftar trace yang error pada rentang waktu itu (pilar traces) → dari salah satu trace, engineer klik span yang bermasalah dan langsung melihat log detail yang berkaitan dengan trace_id tersebut (pilar logs) — semua dalam satu alur investigasi tanpa perlu berpindah tool atau menyalin-tempel timestamp secara manual.
Untuk mencapai korelasi ini, prasyarat teknisnya adalah:
- Setiap log entry menyertakan
trace_iddanspan_idyang sama dengan trace yang sedang berjalan saat log tersebut ditulis. - Metrics diberi label (misalnya
service_name,route) yang konsisten dengan atribut yang dipakai di span trace, sehingga query lintas pilar bisa memakai kriteria yang sama. - Backend observability yang dipakai (Grafana, Datadog, dsb) mendukung "exemplars" — metadata pada titik data metric yang menaut langsung ke trace_id spesifik yang berkontribusi pada nilai metric tersebut.
Sampling: Menyeimbangkan Detail dan Biaya
Merekam trace untuk 100% request pada sistem dengan traffic tinggi bisa jadi sangat mahal, baik dari sisi biaya penyimpanan maupun overhead performa. Karena itu strategi sampling menjadi penting:
- Head-based sampling — keputusan sampling diambil di awal (misalnya "rekam 10% dari semua request secara acak"), sederhana tapi berisiko melewatkan trace yang justru penting (misalnya request yang error, yang jumlahnya sedikit dibanding total traffic).
- Tail-based sampling — keputusan sampling diambil setelah trace lengkap selesai diproses, sehingga bisa memprioritaskan menyimpan trace yang error atau lambat secara penuh, sementara trace yang normal/cepat di-sample lebih rendah. Lebih kompleks secara infrastruktur (butuh buffering di collector) tapi jauh lebih berguna untuk debugging.
Alerting yang Efektif: Dari Data Menjadi Tindakan
Mengumpulkan logs, metrics, dan traces tidak ada artinya jika tidak diterjemahkan menjadi alert yang tepat sasaran. Salah satu masalah paling umum di tim yang baru membangun observability adalah alert fatigue — terlalu banyak notifikasi yang membuat tim mulai mengabaikan semuanya, termasuk yang benar-benar kritikal. Beberapa prinsip alerting yang sehat:
- Setiap alert harus actionable. Jika sebuah alert menyala tapi tidak ada tindakan jelas yang perlu diambil, alert tersebut seharusnya dihapus atau diubah menjadi metric yang dipantau di dashboard saja, bukan mengganggu tidur on-call engineer di tengah malam.
- Alert berdasarkan symptom, bukan cause. Alih-alih membuat alert terpisah untuk setiap kemungkinan penyebab (CPU tinggi, memory tinggi, disk penuh), fokuskan alert pada dampak yang dirasakan pengguna (error rate naik, latensi naik) — root cause bisa dieksplorasi lewat traces dan logs setelah alert menyala, bukan didefinisikan di alert itu sendiri.
- Gunakan multi-window, multi-burn-rate alerting untuk SLO. Pendekatan yang dipopulerkan Google SRE ini membandingkan laju konsumsi error budget dalam beberapa jendela waktu berbeda (misalnya 5 menit dan 1 jam sekaligus) untuk membedakan lonjakan sesaat yang tidak kritikal dari tren penurunan kualitas yang benar-benar butuh respons cepat.
- Tetapkan severity level yang jelas. Alert P1 (membangunkan on-call tengah malam) harus benar-benar berbeda ambang batasnya dari alert P3 (cukup dilihat besok pagi saat jam kerja) — mencampur keduanya di channel notifikasi yang sama mempercepat terjadinya alert fatigue.
- Sertakan konteks langsung di pesan alert — tautan langsung ke dashboard relevan, runbook penanganan, dan query log yang sudah difilter, agar engineer yang menerima alert tidak perlu memulai investigasi dari nol.
Best Practices dan Kesalahan Umum
- Instrumentasi sejak awal, bukan setelah insiden besar terjadi. Tim yang baru memasang observability setelah outage besar biasanya kesulitan mendiagnosis root cause dari insiden yang sudah lewat karena data historisnya tidak lengkap.
- Jangan hanya memantau "apakah service hidup" (uptime), tapi juga "apakah service bekerja dengan benar". Health check yang hanya mengecek proses berjalan tidak akan mendeteksi masalah seperti query database yang lambat atau cache yang selalu miss.
- Hindari cardinality eksplosif pada metrics label. Menambahkan label seperti
user_idpada metric Prometheus (yang punya jutaan nilai unik) bisa membuat database time-series membengkak drastis dan memperlambat query — gunakan label dengan kardinalitas rendah dan terbatas sepertistatus_codeatauroute. - Definisikan SLI/SLO secara eksplisit (Service Level Indicator/Objective), misalnya "99.9% request selesai di bawah 300ms dalam periode 30 hari", agar data observability punya tujuan konkret, bukan sekadar dashboard tanpa arah.
- Latih tim melakukan "game day" atau simulasi insiden secara berkala untuk memastikan observability stack benar-benar bisa dipakai efektif saat insiden nyata terjadi, bukan cuma terlihat bagus di demo.
Kesimpulan
Observability adalah investasi yang baru terasa nilainya secara penuh pada momen paling genting: ketika sistem produksi bermasalah dan tim harus menemukan akar masalah secepat mungkin. Tiga pilarnya — logs untuk detail konteks per-peristiwa, metrics untuk tren teragregasi jangka panjang, dan traces untuk memahami perjalanan request lintas service — masing-masing punya peran yang tidak saling menggantikan. Kekuatan sesungguhnya baru muncul ketika ketiganya dirancang untuk saling berkorelasi lewat trace_id yang konsisten, didukung standar terbuka seperti OpenTelemetry yang membebaskan tim dari lock-in vendor tertentu. Bagi tim yang mengelola sistem terdistribusi, membangun observability yang matang bukan sekadar praktik operasional yang baik, melainkan prasyarat mendasar untuk bisa mengoperasikan sistem kompleks dengan percaya diri dan merespons insiden secara cepat dan tepat sasaran.

Ditulis oleh
@nopal
Ruang Iklan Tersedia
Hubungi Admin untuk menempatkan banner iklan atau Adsense Anda di sini.
Bagaimana pendapat Anda tentang artikel ini?
Komentar Pembaca (0)
Belum ada komentar. Jadilah yang pertama!