Episode ini membahas observability di produksi: logging, tracing, dan monitoring untuk aplikasi C++, analisis crash dump dan post-mortem debugging, release engineering dengan versioning dan packaging, serta maintenance best practices dan dokumentasi.

Aplikasi yang berjalan di produksi harus bisa "dilihat" dari dalam. Saat terjadi masalah, kalian tidak bisa mencolokkan debugger ke server produksi — yang tersisa hanyalah log, metric, dan crash dump. Kemampuan mengamati aplikasi inilah yang disebut observability.
Episode 22 membahas dukungan produksi untuk aplikasi C++: logging terstruktur dengan level yang tepat, tracing dan monitoring dengan metric, analisis crash dump dan post-mortem debugging, release engineering dengan versioning dan packaging, serta maintenance dan dokumentasi yang berkelanjutan.
Log yang baik punya level (trace, debug, info, warning, error) dan format terstruktur. Jangan memakai std::cout untuk log produksi — library logging seperti spdlog memberi level, format, dan sink ke file atau network. Log terstruktur dalam JSON mudah diproses oleh tool agregasi:
#include <spdlog/spdlog.h>
int main() {
spdlog::info("server mulai di port {}", 8080);
spdlog::warn("koneksi lambat: {} ms", 2500);
spdlog::error("koneksi gagal: {}", "timeout");
}spdlog::info("server mulai di port {}", 8080) menulis log berformat dengan placeholder. Gunakan level yang konsisten: info untuk kejadian normal, warning untuk kondisi yang mencurigakan, dan error untuk kegagalan. Kalian harus bisa memfilter log tanpa mengubah kode.
Prinsip keamanan dari episode 14 juga berlaku di log: jangan pernah mencatat password, token, atau data pribadi mentah. Batasi ukuran log dan terapkan rotasi agar disk tidak penuh. Log yang bagus menyimpan konteks, bukan sekadar pesan — sertakan id request, user id, dan korelasi dengan trace.
Monitoring mengumpulkan metric: CPU, memori, latensi, throughput, dan error rate. Tracing mengikuti satu permintaan melewati banyak komponen. Untuk aplikasi C++, OpenTelemetry C++ menyediakan keduanya:
#include <opentelemetry/trace/context.h>
// begin_span menciptakan span untuk satu operasi
auto span = tracer->StartSpan("proses-request");
// ... operasi ...
span->End();StartSpan("proses-request") menciptakan span yang dicatat ke backend tracing, dan span->End() menutupnya dengan durasi. Gabungan log, metric, dan trace membentuk observability lengkap — log menjawab "apa yang terjadi", trace menjawab "di mana", dan metric menjawab "berapa banyak".
Untuk aplikasi tanpa infrastruktur besar, metric bisa dipublikasikan lewat endpoint sendiri yang dibaca Prometheus. Pustaka seperti prometheus-cpp mengekspos counter dan histogram. Mulai dari tiga metric wajib: jumlah request, latensi, dan error rate — ketiganya sudah cukup untuk mendeteksi degradasi layanan.
Saat program crash, sistem operasi bisa menyimpan core dump — snapshot memori proses. Dump ini dianalisis dengan GDB untuk menemukan lokasi crash:
ulimit -c unlimited
./app
gdb ./app core -batch -ex btulimit -c unlimited mengaktifkan core dump, dan setelah crash, gdb ./app core -batch -ex bt menampilkan backtrace — rantai pemanggilan fungsi saat crash. Backtrace adalah petunjuk pertama menuju akar masalah.
Pola post-mortem yang efektif:
frame dan info locals.Analisis crash dump sebaiknya dipicu otomatis. Sistem seperti systemd atau Apport menangkap core dump, dan alamat crash bisa diterjemahkan lewat addr2line. Kombinasikan dengan sanitizer di CI (episode 11) agar banyak bug tidak pernah sampai ke produksi.
Release engineering mengelola siklus hidup perangkat lunak: versioning, packaging, dan rilis. Gunakan semantic versioning: MAJOR.MINOR.PATCH. MAJOR naik saat ada perubahan yang tidak kompatibel, MINOR untuk fitur baru yang kompatibel, PATCH untuk perbaikan bug. Version ini diinjek ke biner saat kompilasi:
project(app VERSION 2.3.1 LANGUAGES CXX)
configure_file(version.h.in version.h)
target_compile_definitions(app PRIVATE
APP_VERSION="${PROJECT_VERSION}")project(app VERSION 2.3.1 ...) menetapkan versi proyek, dan target_compile_definitions(... APP_VERSION="...") menanamkannya ke biner. Aplikasi yang tahu versinya sendiri membuat debugging di produksi jauh lebih mudah.
Packaging mengubah biner menjadi artefak yang bisa dipasang. Di Linux, format umumnya .deb dan .rpm; cpack dari CMake menghasilkan keduanya dari satu deskripsi. Pastikan artefak mencantumkan versi, dependency, dan checksum. CI dari episode 19 mengotomatiskan seluruhnya: build, tes, packaging, dan upload artefak.
Maintenance adalah bagian terbesar dari biaya perangkat lunak. Kode yang baik untuk dipelihara:
Dokumentasi API dengan Doxygen menghasilkan referensi dari komentar kode:
doxygen Doxyfiledoxygen Doxyfile menghasilkan dokumentasi HTML dari komentar /// dan /** ... */ di kode. Dokumentasi yang hidup bersama kode selalu lebih mutakhir daripada dokumen terpisah. Tambahkan contoh penggunaan di dokumentasi — contoh yang berjalan adalah dokumentasi terbaik.
Tip
Gabungkan semuanya dalam satu pipeline: build, tes, lint, packaging, dan dokumentasi dijalankan CI setiap perubahan. Otomatisasi adalah kunci produksi yang stabil.
Inti yang harus dibawa pulang:
cpack menghasilkan artefak .deb dan .rpm dari CMake.Di episode 23 terakhir kita akan membahas stable modern features dan future trends — fitur standar terbaru yang stabil, peran C++ di game development, finance, embedded, dan systems, evolusi ekosistem dan library modern, serta strategi menjaga keahlian C++ tetap relevan di industri.