engineering6 menit baca

Temuan Sentry: observabilitas, stabilitas, dan perubahan biaya memantau kode sendiri

Error produksi mengungkap ketidakcocokan skema, pemulihan transaksi yang gagal, dan log yang tidak membantu. Cara tim kecil memakai Sentry untuk memperbaiki kegagalan backend, menyiapkan pemantauan browser, dan mengendalikan noise alert.

K
Ken Jo

Dulu, tim engineering biasanya berinvestasi berlebihan dalam observabilitas—misalnya membentuk seluruh organisasi SRE untuk merangkai dasbor yang tak pernah dibaca—atau melewatkannya sama sekali hingga mengetahui layanan mati dari email pelanggan. Pada 2026, kedua ekstrem itu tidak dapat diterima. Anda perlu tahu apa yang rusak, tetapi juga perlu mengetahuinya tanpa membayar harga kelas enterprise untuk produk indie.

Panduan ini menunjukkan bagaimana integrasi Sentry mengungkap error produksi, perubahan yang kami lakukan, dan konfigurasi pemantauan untuk mengendalikan noise serta penggunaan. Kami juga melihat bagaimana alat observabilitas berkembang untuk tim engineering kecil.

Mengapa alert tidak menangkap kegagalan browser

Backend kami telah terhubung ke Sentry sejak Maret. DSN tersimpan di Google Secret Manager, secret dipasang ke Cloud Run, dan sentry_sdk.init berjalan pada setiap startup. Alert email masuk. Dari luar, semuanya tampak baik.

Namun di dalam, kondisinya berbeda. Frontend sama sekali belum terhubung ke Sentry. Exception browser, error hydration, dan kegagalan pemuatan chunk tidak terlihat. Backend juga mengirim error Python ke proyek bernama javascript-nextjs, satu-satunya proyek dalam organisasi. Stack trace menumpuk di tempat yang salah, pengelompokan tidak berguna, dan dasbor dipenuhi event dari runtime berbeda.

Menutup celah ini berarti memisahkan kegagalan browser dari error backend sebelum menangani bug satu per satu.

Apa yang ditunjukkan datanya

Kami mengambil event error selama 90 hari terakhir. Beberapa pola terlihat jelas.

Insiden lama yang sudah diperbaiki

Error paling sering dalam rentang waktu tersebut adalah Postgres StringDataRightTruncation dari endpoint pendaftaran sosial: 16 event dalam 22 detik. Penyebabnya adalah schema drift klasik: definisi model mengizinkan bio 800 karakter, tetapi kolom basis data produksi masih VARCHAR(500) dari migrasi sebelumnya. Pengguna mengirim bio sedikit lebih dari 500 karakter, lapisan Pydantic menerimanya, lalu INSERT gagal.

Migrasi untuk memperlebar kolom menjadi 800 sudah ditulis dan diterapkan keesokan paginya. Namun masalah dasarnya—model dan skema DB dapat berbeda tanpa diketahui sampai berdampak pada pelanggan—masih terbuka.

Kami melakukan dua hal. Pertama, kami memperketat skema permintaan pendaftaran sosial dengan max_length eksplisit untuk email, nama tampilan, dan token, sehingga masukan yang tidak wajar mengembalikan 422 dengan rapi dan tidak sampai ke basis data. Kedua, kami memperluas skrip integritas DB agar membandingkan information_schema.columns.character_maximum_length dengan panjang yang diharapkan aplikasi. Jika migrasi berikutnya memperpendek kolom hingga di bawah panjang yang dapat dihasilkan model, pemeriksaan integritas pada deployment berikutnya akan gagal.

Sesi yang tidak dapat di-rollback

Lebih jauh dalam daftar, ada rangkaian error: satu OperationalError: server closed the connection unexpectedly pada POST /v1/upload, disusul serangkaian PendingRollbackError dari jalur kode yang sama. Postgres memutus koneksi di tengah kueri, sesi SQLAlchemy menjadi tidak valid, lalu layanan unggah mencoba menyimpan hasil parsial di atas sesi tersebut. Semua operasi berikutnya dalam sesi itu ikut gagal.

Perbaikannya kecil, tetapi urutannya mudah keliru. Saat pipeline unggah menangkap exception, hal pertama yang kini dilakukan adalah db.rollback()—dibungkus try/except tersendiri agar rollback yang gagal tidak menutupi error awal. Setelah itu, logika penyimpanan parsial berjalan dengan sesi yang bersih.

Log yang menghapus informasinya sendiri

Handler penyelesaian WebSocket mencatat exception yang tertangkap dengan err=%s. Untuk kebanyakan exception, hasilnya berguna. Namun beberapa tipe exception memiliki __str__ yang mengembalikan string kosong, sehingga yang tercatat hanya err=. Event Sentry memberi tahu bahwa penyimpanan gagal tanpa menjelaskan alasannya.

Mengganti pencatatan dengan logger.exception(...) dan err=%r tidak memerlukan biaya, dan membuat setiap event selanjutnya memiliki konteks yang jelas.

Noise yang tidak ingin kami bayar

Item lain dalam antrean bukan bug. uvloop sesekali mengeluarkan RuntimeError: unable to perform operation on <TCPTransport closed=True> ketika klien terputus di tengah SSL. Ini perilaku yang benar, bukan sesuatu yang perlu diperbaiki; pada kuota gratis 5.000 error per bulan, event tersebut membuang anggaran. Kami menambahkan filter before_send untuk membuang pola exception/nilai tersebut. Di frontend, kami menerapkan pendekatan serupa untuk noise browser seperti ResizeObserver loop limit exceeded.

Menyesuaikan penggunaan dengan paket gratis

Per 13 Oktober 2026, paket gratis Sentry Developer mencakup 5.000 error, 5 juta span tracing, dan 50 replay per bulan. Tracing diukur dalam span, bukan unit performa lama. Periksa batas paket terkini sebelum memilih tingkat sampling: kuota error bukan anggaran untuk semua sinyal yang dapat dikirim SDK.

Konfigurasi kami:

  • tracesSampleRate: 0 pada backend dan frontend. Tracing terdistribusi memang berguna, tetapi batas 10K unit performa per bulan dapat habis dalam satu sore yang buruk. Kami dapat mengaktifkannya dengan sampling ketat saat menyelidiki masalah tertentu.
  • profilesSampleRate: 0 pada backend, dengan alasan yang sama.
  • Session Replay dinonaktifkan pada frontend. Kode integrasi tetap tersedia, tetapi kedua sampling rate ditetapkan nol. Jika bug kritis memerlukan konteks replay, kami dapat mengubah replaysOnErrorSampleRate menjadi 0.05 selama sehari lalu menonaktifkannya lagi.
  • Filter before_send pada kedua runtime membuang event yang sudah diketahui tidak dapat ditindaklanjuti.

Perubahan backend mengurangi noise error yang dapat ditindaklanjuti, sedangkan konfigurasi SDK browser disiapkan untuk aktivasi. Keduanya merupakan tonggak yang berbeda: kode dan pengaturan sampling saja tidak membuktikan event browser masuk ke proyek yang dimaksud.

Perubahan di pasar observabilitas

Kami menyesuaikan konfigurasi dengan paket gratis karena paket gratis Sentry cukup murah hati untuk produk terkelola. Namun, perkembangan yang lebih luas juga perlu dipahami karena perhitungan ekonominya sedang berubah.

Beberapa hal bergeser dalam 12 hingga 18 bulan terakhir:

  • Standar terbuka mengurangi pekerjaan migrasi, bukan menghapus semuanya. Instrumentasi yang kompatibel dengan OTLP dapat mengurangi keterikatan pada backend pemantauan. Kueri, dasbor, aturan alert, dan fitur SDK khusus vendor tetap perlu direncanakan serta diuji saat berpindah.
  • Self-hosting mengubah perhitungan biaya. Pilihan seperti GlitchTip dan stack berbasis OTLP menawarkan jalur pemantauan lain. Bandingkan penyimpanan, backup, upgrade, dan waktu engineering dengan paket terkelola, bukan hanya tagihan VM dengan harga langganan.
  • Debugging berbantuan AI memperluas alur kerja. Seer dari Sentry mengusulkan akar masalah dan patch, sementara integrasi MCP yang diotorisasi dapat membawa konteks error ke asisten coding. Usulan perbaikan tetap perlu direproduksi dan diuji regresinya sebelum dirilis.
  • Batas paket perlu diperhatikan seperti fitur. Volume error, retensi, sampling, dan akses tim dapat memengaruhi tagihan. Mulailah dengan sinyal yang diperlukan dan anggaran event terukur, lalu bandingkan paket berdasarkan beban kerja tersebut.

Pada snapshot rilis ini, Sentry memenuhi kebutuhan pemantauan error kami saat itu. Memakai antarmuka terbuka jika tersedia memberi lebih banyak pilihan di kemudian hari, tetapi perpindahan penyedia tetap memerlukan pemeriksaan routing proyek, alert, data tersimpan, dan fitur khusus penyedia.

Pemeriksaan deployment melengkapi pemantauan

Pada snapshot artikel tanggal 17 Mei 2026, masih ada dua pekerjaan deployment:

  1. Membuat proyek Sentry Python khusus agar error backend tidak lagi dicatat di bawah javascript-nextjs. DSN diganti pada entri Secret Manager yang sama, yang sudah dibaca backend.
  2. Memasukkan DSN frontend ke pengaturan proyek Vercel agar error sisi klien mulai dikirim. Kodenya sudah ada dan diinisialisasi secara kondisional; yang masih kurang hanya variabel lingkungannya.

Untuk setiap peluncuran pemantauan, kirim event uji terkontrol dari setiap runtime dan pastikan proyek, lingkungan, pengelompokan, serta konteksnya benar sebelum menyatakan integrasi selesai. Pemisahan proyek dan variabel lingkungan adalah langkah konfigurasi, bukan bukti bahwa event telah tiba.

Mengapa ini penting

Ketika Anda tidak dapat melihat apa yang rusak, Anda bisa menginvestasikan terlalu banyak waktu pada kode defensif, atau terlalu sedikit lalu merilis bug. Keduanya mahal. Observabilitas yang terjangkau dan andal memungkinkan tim kecil bekerja seperti tim lebih besar: menangkap regresi sebelum pelanggan menyadarinya, memperbaikinya tanpa menebak-nebak, dan menggunakan waktu engineering untuk membangun hal baru.

Pelajaran pentingnya adalah memverifikasi kedua sisi: perbaikan pada aplikasi dan jalur pemantauan yang seharusnya menunjukkan regresi berikutnya.


← Kembali ke blog