Logging Itu Berantakan
(loggingsucks.com)- Dalam sistem terdistribusi modern, pendekatan logging lama memiliki keterbatasan struktural sehingga gagal menyampaikan kebenaran
- Log masih dirancang dengan asumsi lingkungan server tunggal ala 2005, sehingga kehilangan konteks permintaan yang melewati banyak layanan, database, dan cache
- Pencarian string sederhana tidak memahami struktur, relasi, dan korelasi, sehingga menyulitkan penemuan akar masalah
- Solusinya adalah menyimpan satu ‘Wide Event (atau Canonical Log Line)’ yang memuat seluruh konteks untuk setiap permintaan
- Dengan ini, log berubah dari sekadar teks menjadi aset data yang bisa dianalisis
Masalah mendasar dalam logging
- Log lama dibuat dengan asumsi era server monolitik, sehingga tidak mencerminkan arsitektur layanan terdistribusi modern
- Satu permintaan bisa melewati banyak layanan, DB, cache, dan queue, tetapi log masih dicatat berdasarkan perspektif satu server
- Dalam contoh log, satu permintaan menghasilkan 13 baris, sehingga dengan 10.000 pengguna serentak, muncul 130.000 baris per detik, namun sebagian besar tidak bermakna
- Saat masalah terjadi, yang dibutuhkan adalah konteks, tetapi log saat ini tidak memilikinya
Batas pencarian string
- Ketika pengguna melaporkan “pembayaran tidak berhasil”, mencari log berdasarkan email atau user_id pun sulit memberi hasil yang berguna karena tidak ada struktur yang konsisten
- ID pengguna yang sama bisa dicatat dalam puluhan bentuk seperti
user-123,user_id=user-123,{"userId":"user-123"}
- ID pengguna yang sama bisa dicatat dalam puluhan bentuk seperti
- Format log antarlayanan berbeda-beda sehingga pelacakan event yang saling terkait menjadi mustahil
- Masalah intinya adalah log dirancang berfokus pada penulisan (write), bukan dioptimalkan untuk query
Definisi konsep inti
- Structured Logging: cara mencatat dalam bentuk key-value (JSON) alih-alih string
- Cardinality: jumlah nilai unik dalam sebuah field; misalnya
user_idsangat tinggi - Dimensionality: jumlah field dalam sebuah event log; makin banyak, makin besar peluang analisis
- Wide Event / Canonical Log Line: satu event log tunggal yang kaya konteks per permintaan
- Sebagian besar sistem logging membatasi data berkardinalitas tinggi karena masalah biaya, padahal justru itulah yang paling berguna untuk debugging
Batasan OpenTelemetry
- OpenTelemetry (OTel) adalah sekumpulan protokol dan SDK yang hanya menyediakan standar untuk pengumpulan dan pengiriman data
- Namun OTel tidak melakukan hal-hal berikut
- Tidak menentukan apa yang harus dicatat ke log
- Tidak otomatis menambahkan konteks bisnis seperti tingkat langganan atau nilai keranjang belanja
- Tidak mengubah cara berpikir developer tentang logging
- Bahkan dengan library yang sama, pengalaman debugging akan sangat berbeda antara instrumentasi yang sengaja menambahkan konteks dan instrumentasi yang sekadar dasar
- OTel hanyalah sarana pengangkutan (plumbing); apa yang dialirkan tetap harus diputuskan developer
Pendekatan Wide Event / Canonical Log Line
- Logging harus keluar dari pendekatan berpusat pada “apa yang dilakukan kode” dan mulai mencatat “apa yang terjadi pada permintaan”
- Untuk setiap permintaan, buat satu event yang luas di tingkat layanan
- Dapat mencakup lebih dari 50 field seperti permintaan, pengguna, pembayaran, error, dan environment
- Contoh JSON mencakup seluruh konteks debugging seperti
user_id,subscription_tier,service_version, danerror_code - Dengan ini, satu pencarian saja cukup untuk analisis langsung, misalnya menemukan penyebab kegagalan pembayaran pada pengguna premium
Pemanfaatan query pada Wide Event
- Wide Event diperlakukan sebagai query data terstruktur, bukan pencarian teks sederhana
- Debugging setingkat analisis real-time dimungkinkan dengan data berdimensi tinggi dan berkardinalitas tinggi
- Contoh: query seperti “agregasikan tingkat kegagalan pembayaran pengguna premium selama 1 jam terakhir berdasarkan kode error” bisa dijalankan seketika
Pola implementasi
- Bangun event sepanjang seluruh siklus hidup permintaan, lalu keluarkan sekali saja di akhir
- Di middleware, inisialisasi field dasar seperti
request_id,timestamp,method, danpath - Di handler, tambahkan secara bertahap informasi pengguna, keranjang, pembayaran, dan error
- Di middleware, inisialisasi field dasar seperti
- Pada akhirnya, catat satu event JSON tunggal dengan
logger.info(event)
Mengendalikan biaya dengan sampling
- Jika mencatat lebih dari 50 field per permintaan, biaya bisa melonjak sehingga diperlukan sampling
- Sampling acak sederhana berisiko melewatkan error
- Strategi Tail Sampling yang diusulkan
- Error (seperti 500) selalu disimpan
- Permintaan lambat (di atas p99) selalu disimpan
- Pengguna VIP atau sesi dengan flag tertentu selalu disimpan
- Sisanya hanya diambil sampel acak 1–5%
- Dengan ini, penghematan biaya dan pelestarian event penting bisa dicapai sekaligus
Meluruskan kesalahpahaman umum
- Structured Logging ≠ Wide Event: format JSON saja tidak cukup; konteks adalah inti utamanya
- Menggunakan OpenTelemetry ≠ observability lengkap: yang distandarkan hanya pengumpulan; apa yang dicatat tetap tanggung jawab developer
- Tidak sama dengan tracing: tracing menunjukkan alur antarservice, sedangkan Wide Event memberi konteks di dalam service
- Pemisahan bahwa log untuk debugging dan metrics untuk dashboard tidak lagi perlu — Wide Event memenuhi kedua kebutuhan itu
- Anggapan bahwa data berkardinalitas tinggi itu mahal sudah usang; database modern seperti ClickHouse dan BigQuery dapat menanganinya secara efisien
Dampak penerapan Wide Event
- Debugging berubah dari ekskavasi (archaeology) menjadi analitik (analytics)
- Dari pendekatan grep pada log 50 service untuk mencari “kegagalan pembayaran pengguna”,
menjadi analisis berbasis satu query seperti “lihat tingkat kegagalan pembayaran pengguna premium menurut kode error” - Hasil akhirnya, log berubah dari alat yang mengatakan kebohongan menjadi aset data yang mengatakan kebenaran
1 komentar
Komentar Hacker News
Tulisannya sulit dibaca dan terasa seperti dibantu AI. Meski begitu, pesannya tetap bernilai, dan akan lebih baik jika dibuat lebih ringkas
Beberapa hal yang belakangan ini saya pikirkan adalah sebagai berikut.
Untuk topik ini, mustahil tidak menyebut Charity Majors. Dia sudah lebih dari 10 tahun menyebarkan konsep “wide events” dan “observability”, dan membangun Honeycomb.io di atas filosofi itu.
Sekarang pendekatan ini bisa diterapkan dengan berbagai alat. Yang penting adalah menangkap wide event menggunakan structured logs atau traces, lalu memakai tool dengan visualisasi kaya seperti deret waktu dan histogram
Saya setuju dengan sebagian argumen tulisan itu, tetapi ada jebakan dalam pendekatan yang hanya menyisakan satu wide event. Jika exception atau timeout terjadi di tengah request, bisa saja tidak ada apa pun yang tersisa.
Log bawaan framework bahasa atau log dependensi juga akan terlewat.
Karena itu, ini lebih baik dipakai sebagai lapisan tambahan di atas log yang sudah ada. Gunakan ID pada level request/session dan agregasikan di tempat seperti ClickHouse
log.error(data)danwide_event.attach(error, data)pada dasarnya sama sajaPresentasi dan contoh interaktif-nya sangat bagus. Tetapi pada akhirnya, inti ceritanya bisa diringkas menjadi “tambahkan tag terstruktur ke log”.
Saya merasa wide log tidak memberi manfaat yang sepadan dibanding kompleksitas dan penurunan keterbacaan yang ditimbulkannya.
Kalau cukup dengan
grep "uid=user-123" application.log, apakah memang perlu sampai menambahkan metode pengiriman pengguna juga?(Sebagai catatan, checkbox tidak berfungsi di browser Brave Android)
grep '"uid": "user-123"'. Opsi--contextjuga bisa dipakai untuk melihat baris di sekitarnyaSaya pernah menangani sistem di lingkungan manufaktur semikonduktor dengan ribuan peserta message bus. Log yang keluar mencapai 300~400MB per jam, tetapi grep dan tool CLI saja sudah cukup untuk mengelolanya.
Log hanyalah deret waktu dari event, sedangkan analisis detail dilakukan dengan kueri Oracle. Log adalah alat untuk memahami hubungan sebab-akibat dari suatu kejadian
Log menjelaskan “kapan dan apa yang terjadi”, sedangkan “mengapa” dicari dari kombinasi kode, data, dan event
Secara pribadi saya merasa antarmuka seperti ELK stack kurang nyaman untuk eksplorasi yang intuitif. Log penting untuk dibaca sambil diikuti secara naluriah
Saran di akhir tulisan, “log semua error, exception, dan request yang lambat”, adalah gagasan yang berbahaya.
Misalnya, jika dependensi melambat, volume log bisa meledak 100 kali lipat.
Dalam kondisi gangguan, layanan justru harus melakukan lebih sedikit pekerjaan agar pemulihan lebih mudah, tetapi ledakan log malah bisa memicu kegagalan berantai
Makin besar volume log, rasio sampling otomatis menyesuaikan sehingga sistem tidak kelebihan beban
trace_id mod 100 == 0Dalam software modern, sulit menjelaskan sepenuhnya “apa yang terjadi” hanya dengan satu log.
Karena itu diperlukan korelasi vertikal (Vertical correlation) dan korelasi horizontal (Horizontal correlation).
Antar lapisan atas-bawah dalam stack harus berbagi nilai correlation yang sama, dan saat ada komunikasi antarsistem, korelasi antarpihak juga diperlukan.
Menambahkan nilai seperti ini ke API atau protokol memang sulit, tetapi jika transaction ID sudah dirancang sejak awal, penelusuran menyeluruh jadi memungkinkan
Saya rasa mendaftarkan domain terpisah hanya untuk satu tulisan itu kurang berkelanjutan.
Karena harus membayar biaya perpanjangan setiap tahun, menurut saya lebih baik memakai blog pribadi atau subdomain.
Misalnya bentuk seperti logging-sucks.boristane.com
Terkait klaim bahwa “log adalah peninggalan era monolitik”, saya merasa log lokal masih tetap relevan.
Fungsi aslinya memang mencatat percakapan proses lokal, dan untuk memahami situasi di server lain kita perlu transaction tracing.
Dengan melihat log di titik yang tepat saja, kita bisa sampai ke akar masalah
Log yang kaya konteks bisa digabungkan dengan engine analitik untuk membantu perbaikan produk juga
Saya setuju dengan pernyataan “log-lah apa yang terjadi pada request, bukan apa yang dilakukan kode”, tetapi penulis tampak kurang berpengalaman.
Saya menyebutnya “bug parts logging”, dan menurut saya harus mencakup sinyal awal seperti jalur pemrosesan, jumlah kemunculan, dan waktu.
Logging berbeda dari metrik atau audit. Jika logging gagal, pemrosesan tetap harus berjalan, tetapi kegagalan audit bersifat fatal.
Seperti konsep “historian” pada sistem SCADA, kita perlu membedakan observables dan evaluatives.
Misalnya, event rinci dari sensor bahan bakar berguna untuk diagnosis, tetapi tidak perlu untuk menjawab pertanyaan “apakah bisa sampai ke tujuan”.
Pada akhirnya, yang penting adalah memperjelas apa yang akan diamati, dan apa yang akan dievaluasi
Cara penyimpanan, transformasi, dan query-nya bisa berbeda, tetapi titik konsumsi dan mekanismenya dapat dirancang sama.
Dengan begitu desain sistem menjadi lebih sederhana, dan log yang disimpan jangka panjang pun bisa diproses ulang di kemudian hari