Seorang pengguna membuka tiket: aplikasi seluler terasa lambat. Anda memeriksa dasbor Anda. Utilisasi CPU datar. Tingkat kesalahan nol. Lampu APM Anda berwarna hijau yang meyakinkan. Backend, berdasarkan setiap ukuran yang terlihat, dalam kondisi sehat. Namun pengguna tidak salah. Kelambatan itu nyata, dan hal itu terjadi di suatu tempat di koridor panjang yang gelap antara perangkat Android dan server Anda.
Masalahnya adalah sebagian besar alat observabilitas berhenti di batas aplikasi. Mereka mengukur apa yang terjadi setelah framework Anda mengurai sebuah permintaan. Mereka melacak kueri database, cache hits, dan panggilan layanan downstream. Apa yang mereka lewatkan adalah mekanika dari permintaan itu sendiri: waktu yang dihabiskan panggilan OkHttp di dalam stack HTTP Android, transit melalui jaringan seluler yang tidak stabil, negosiasi handshake TLS, dan penantian sunyi yang terjadi di dalam antrean kernel sebelum kode Anda sempat berjalan. Celah-celah ini menelan milidetik—atau bahkan detik penuh—sementara APM Anda tetap diam.
Enkripsi membuat kebutaan ini menjadi sempurna. Aplikasi Android modern mengarahkan segalanya melalui BoringSSL. Pada saat paket mencapai stack jaringan kernel, header HTTP sudah terenkripsi. tcpdump standar atau network hook hanya melihat rekaman TLS yang buram. Anda dapat mengamati bahwa lalu lintas sedang mengalir, tetapi Anda tidak dapat membacanya. Anda tentu tidak dapat menghubungkan segmen TCP tingkat kernel tertentu kembali ke panggilan API pengguna tertentu. Konteks trace yang Anda butuhkan terjebak di dalam ciphertext.
eBPF mengubah persamaannya karena ia memungkinkan Anda melakukan instrumentasi sistem dari dalam ke luar tanpa mengubah kode aplikasi Anda. Alih-alih meminta aplikasi Anda untuk melaporkan latensinya sendiri, Anda melampirkan program kecil langsung ke kernel dan ke library userspace yang kritis. Program-program ini mengamati peristiwa saat terjadi, mengekstrak apa yang Anda butuhkan, dan mengirimkannya ke ring buffer. Tidak ada bloat SDK di dalam APK Android Anda selain header yang ringan, dan tidak ada agen instrumentasi yang menulis ulang kelas backend Anda.
Pengaturan Empat Bagian
Membangun pipeline ini melibatkan empat lapisan observasi yang berbeda.
1. Jangkar traceparent. Pada perangkat Android, Anda menambahkan interceptor OkHttp yang menyuntikkan header W3C traceparent ke dalam setiap permintaan keluar. Ini adalah satu-satunya perubahan yang diperlukan di sisi seluler, dan perubahannya minimal. Header tersebut berjalan di dalam payload terenkripsi hingga ke backend Anda. Karena berada di dalam lapisan HTTP, ia tetap bertahan di dalam plaintext yang akhirnya dibuka oleh mesin TLS.
2. Waktu kedatangan TCP. Pada host backend, Anda menggunakan hook eBPF Traffic Control yang terpasang pada antarmuka jaringan. Program-program ini berjalan saat segmen TCP individu tiba. Mereka menangkap nomor urutan dan timestamp di tepian (edge). Anda sekarang tahu dengan tepat kapan bit meninggalkan kabel dan memasuki mesin Anda, jauh sebelum aplikasi Anda membaca satu byte pun.
3. Probe dekripsi. Backend Anda mengakhiri TLS menggunakan OpenSSL atau BoringSSL. Di sinilah arsitekturnya menjadi menarik. Menggunakan uprobes—probe userspace dinamis—Anda menempel pada SSL_write dan SSL_read di dalam library TLS. Fungsi-fungsi ini berjalan seketika saat data plaintext melewati mesin enkripsi. Program eBPF Anda membaca buffer terdekripsi tersebut, memindai header traceparent, dan mengekstraknya. Kernel kini memiliki pemetaan langsung antara aliran TCP mentah dan permintaan seluler tertentu, tanpa Anda perlu menangani sertifikat atau kunci dalam alat kustom.
4. Antrean kernel. Bahkan setelah data didekripsi dan siap, aplikasi Anda mungkin tidak langsung mengonsumsinya. Anda menempelkan kprobes ke fungsi kernel relevan yang menangani buffer socket dan peristiwa penjadwalan. Ini mengukur latensi antrean: waktu yang dihabiskan permintaan saat menunggu di ranah kernel karena proses Anda sedang berebut CPU atau sekadar belum memanggil read() yet.
Keempat sumber sinyal tersebut menulis peristiwa ke dalam ring buffer eBPF. Sebuah proses sidecar yang berjalan di userspace menguras buffer ini, mengorelasikan peristiwa berdasarkan ID traceparent, dan menyusun kembali satu lini masa yang koheren untuk setiap permintaan. Apa yang sebelumnya merupakan hamburan kebisingan kernel yang terputus-putus kini menjadi trace yang terstruktur.
Membaca Jalur Lengkap
Output yang telah disusun biasanya ditampilkan sebagai flame graph atau pohon span terstruktur yang membagi latensi menjadi empat bagian konkret:
- Waktu transit jaringan: Durasi dari saat radio Android mengirimkan byte terakhir permintaan hingga NIC backend menerimanya. Di sinilah volatilitas seluler terjadi.
- Durasi handshake TLS: Waktu yang dihabiskan untuk menegosiasikan terowongan terenkripsi. Pada jaringan yang tidak stabil, hal ini dapat jauh melampaui transfer data yang sebenarnya.
- Latensi antrean kernel: Waktu yang dihabiskan dalam buffer kernel dan antrean penjadwal (scheduler) setelah segmen tiba tetapi sebelum userspace mengonsumsinya.
- Waktu pemrosesan aplikasi: Bagian yang sebenarnya dikonsumsi oleh framework backend dan logika bisnis Anda.
Anda mungkin menemukan bahwa permintaan seluler berdurasi 800ms hanya menghabiskan 40ms di dalam parser JSON Anda. 200ms lainnya hilang dalam handshake TLS yang terhenti di koneksi yang lossy. 300ms lainnya lenyap ke dalam backlog kernel pada host yang oversubscribed. APM Anda hanya melaporkan 40ms tersebut. Tanpa visibilitas tingkat kernel, Anda akan mengoptimalkan hal yang sepenuhnya salah.
Overhead yang Benar-benar Skalabel
Agen APM tradisional mencapai visibilitas mereka dengan mencegat panggilan di dalam runtime bahasa Anda. Mereka membungkus metode, mengalokasikan objek span, dan menserialisasi data telemetri di dalam heap proses Anda. Di bawah beban kerja, overhead tersebut menumpuk dengan cepat. Biaya serialisasi meningkat. Tekanan garbage collection bertambah. Anda membayar visibilitas dengan sumber daya aplikasi Anda sendiri.
Program eBPF berjalan di dalam mesin virtual kernel dan dikompilasi JIT ke instruksi mesin asli. Sebuah verifier memeriksanya untuk keamanan sebelum dimuat. Setiap probe hanya menambah mikrodetik pada jalur tersebut, bukan milidetik. Pekerjaan berat dalam mencocokkan peristiwa dan merender grafik terjadi di sidecar, di luar hot path layanan Anda. Anda tidak membengkakkan alokasi heap. Anda tidak menambah beban serialisasi di dalam penanganan permintaan. Untuk layanan yang mengirimkan ribuan permintaan per detik, perbedaan tersebut sangat penting.
Apa yang Dibutuhkan untuk Menjalankannya
Ini bukan solusi ajaib, dan ini bukan SaaS terkelola yang bisa Anda aktifkan begitu saja. Anda memerlukan kernel backend dengan dukungan eBPF modern, termasuk informasi tipe BTF agar probe Anda dapat menelusuri struktur kernel dengan aman. Library TLS Anda harus mengekspos simbol yang dapat ditargetkan oleh uprobes; jika Anda mengirimkan biner yang terhubung secara statis (statically linked) dengan build OpenSSL yang telah dikurangi (stripped) atau dikustomisasi secara berat, Anda perlu memperhitungkan hal tersebut. Anda juga perlu memverifikasi bahwa header traceparent Anda tetap ada melewati proxy atau edge gateway apa pun antara klien seluler dan titik terminasi TLS.
Namun bagi tim yang lelah dengan tiket "seluler lambat" yang sulit dianalisis akar masalahnya, arsitektur ini menggantikan tebakan ritual dengan sinyal yang nyata. Anda berhenti berspekulasi tentang kondisi jaringan dan mulai mengukur permintaan spesifik melalui jalur yang spesifik.
Kesimpulan Utamanya
Anda tidak perlu memperlakukan lalu lintas seluler terenkripsi sebagai aliran buram (opaque stream) yang tiba-tiba menjadi terlihat setelah mencapai framework Anda. Dengan menggabungkan header OkHttp sederhana dengan probe eBPF yang ditempatkan secara strategis di backend, Anda dapat mengikuti satu permintaan dari perangkat Android melalui dekripsi TLS, antrean kernel, dan masuk ke dalam logika aplikasi Anda—tanpa menulis ulang aplikasi seluler Anda dan tanpa melakukan instrumentasi pada kode backend Anda seperti yang diminta oleh APM tradisional. Itu bukan sekadar peningkatan bertahap. Itu adalah observabilitas end-to-end di seluruh
