os_log — adalah API unified logging dari Apple untuk iOS dan macOS, yang menggantikan NSLog dan os_trace. Tidak seperti mekanisme lama, os_log bekerja di tingkat kernel: pesan di-buffer dalam buffer melingkar dan ditulis ke disk hanya ketika ambang aktivitas tercapai. Menurut data Apple WWDC 2016, os_log mengurangi beban disk 10 kali lipat dibandingkan dengan NSLog dan memberikan kontrol atas tingkat detail melalui kategori dan tipe. Ini adalah alat diagnostik utama untuk pengembang iOS: melalui Console.app pesan dapat difilter berdasarkan proses, kategori, dan tingkat keparahan secara real-time.
Poin Utama
os_log — adalah API unified logging yang diperkenalkan Apple di iOS 10 dan macOS Sierra. API ini menyatukan mekanisme logging yang terpisah-pisah seperti NSLog, os_trace, dan syslog ke dalam satu sistem dengan buffering di tingkat kernel XNU.
Tidak seperti NSLog yang secara sinkron menulis setiap pesan ke disk dan memblokir thread, os_log menggunakan buffer melingkar asinkron di memori. Pesan ditulis ke disk hanya ketika aktivitas melebihi ambang batas tertentu atau atas perintah log collect. Ini secara drastis mengurangi dampak logging pada kinerja aplikasi.
os_log mendukung enam tingkat keparahan, pembedaan berdasarkan subsystem dan category, serta mekanisme privasi bawaan: data yang ditandai sebagai private secara otomatis ditutupi di log produksi dan hanya dapat diakses oleh pengembang saat Xcode terhubung.
Sebelum iOS 10, pengembang menggunakan NSLog untuk debugging dan syslog untuk pesan sistem. NSLog menulis ke stderr dan konsol, tetapi sangat tidak efisien: setiap pesan ditulis secara sinkron ke disk, menyebabkan penundaan di UI saat logging sering terjadi. os_log memecahkan masalah ini dengan memindahkan buffering ke tingkat bagian BSD dari kernel XNU dan membuat penulisan ke disk menjadi asinkron.
os_log digunakan di semua aplikasi Apple dan direkomendasikan oleh Apple sebagai satu-satunya API logging untuk iOS, macOS, tvOS, dan watchOS. Sistem dan aplikasi pihak ketiga menulis pesan melaluinya ke satu database — disimpan di memori dan secara periodik ditulis ke disk. Log ini dapat dianalisis melalui Console.app di Mac atau melalui perintah log di terminal.
Arsitektur os_log terdiri dari tiga lapisan: API klien di ruang pengguna (libsystem_trace.dylib), buffer melingkar di kernel XNU, dan daemon logd yang secara asinkron menulis buffer ke disk.
Ketika aplikasi memanggil os_log, pesan disalin ke buffer melingkar kernel berukuran beberapa megabita. Buffer bekerja berdasarkan prinsip FIFO: jika penuh, pesan lama ditimpa dengan yang baru. Daemon logd secara periodik memeriksa buffer dan menyimpan pesan ke file .tracev3 di area sistem file yang dilindungi.
Menurut data Apple Engineering, keterlambatan tipikal dari pemanggilan os_log hingga munculnya pesan di Console.app adalah 1–5 detik di perangkat dan hingga 60 detik saat penulisan batch ke disk. Ini adalah kompromi yang disengaja: kinerja aplikasi tidak terganggu karena logging, tetapi pengembang melihat pesan dengan sedikit keterlambatan.
// Deklarasi os_log melalui OSLog
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
Buffer melingkar os_log memiliki volume tetap dan tidak dapat diubah dari ruang pengguna. Ukuran buffer bervariasi dari 256 KB di Apple Watch hingga 4 MB di Mac. Ketika aplikasi menghasilkan lebih banyak pesan daripada yang dapat ditampung buffer, pesan lama akan hilang — ini adalah perilaku yang diharapkan untuk logging volume tinggi.
Untuk pengumpulan semua pesan jangka panjang, digunakan perintah log collect, yang memulai daemon pengumpulan di perangkat dan mengekspor .logarchive ke komputer pengembang. Dalam mode ini, buffer tidak ditimpa — pesan ditulis langsung ke arsip.
os_log mendukung lima tingkat keparahan, masing-masing bertanggung jawab untuk jenis pesan terpisah dan diproses secara berbeda oleh sistem. Tingkat Default — dasar untuk pesan yang selalu masuk ke buffer. Info dan Debug dinonaktifkan di build produksi tanpa profil pengumpulan. Error dan Fault selalu aktif dan ditandai dengan bendera khusus di database.
| Tingkat | Arti | Masuk buffer default |
|---|---|---|
| Default | Pesan biasa yang penting untuk diagnostik | Ya |
| Info | Pesan informasi untuk analisis terperinci | Tidak (hanya dengan profil) |
| Debug | Pesan debugging untuk pengembangan | Tidak (hanya dengan profil) |
| Error | Kesalahan yang memerlukan perhatian | Ya |
| Fault | Kegagalan kritis yang menyebabkan crash | Ya |
Pemilihan tingkat keparahan yang tepat penting untuk kinerja: Info dan Debug tidak ditulis ke disk dalam mode normal, sehingga dapat digunakan secara berlebihan tanpa risiko memperlambat aplikasi. Error dan Fault selalu disimpan, tetapi jumlahnya harus minimal — setiap pesan semacam itu meningkatkan waktu tulis karena metadata tambahan.
Subsystem — adalah pengenal aplikasi atau modul dalam format reverse-DNS (com.example.app). Category — label teks dalam subsystem yang mengelompokkan log berdasarkan area fungsional: network, ui, database, auth. Hierarki ini memungkinkan pemfilteran log tanpa membaca setiap pesan dan pengumpulan statistik untuk setiap modul secara terpisah.
Apple merekomendasikan untuk mendefinisikan satu OSLog per modul dan menggunakannya di semua file modul tersebut. Untuk lapisan aplikasi yang berbeda — networking, UI, persistence — buat kategori terpisah. Maka di Console.app, log hanya dapat diaktifkan untuk network dan dinonaktifkan untuk yang lain, tanpa mengkompilasi ulang aplikasi.
import OSLog
extension Logger {
static let network = Logger(
subsystem: "com.example.app",
category: "network"
)
static let ui = Logger(
subsystem: "com.example.app",
category: "ui"
)
}
os_log menyediakan mekanisme kontrol privasi bawaan: setiap nilai dalam string format dapat ditandai sebagai public, private, atau auto (perilaku default). Secara default, os_log menganggap semua string dan objek dinamis sebagai berpotensi rahasia dan menggantinya dengan masker <private> di log produksi.
Ini sangat penting untuk kepatuhan terhadap persyaratan GDPR dan HIPAA: jika aplikasi mencatat email pengguna atau nomor kartu melalui os_log dalam mode auto, data nyata tidak akan pernah sampai ke disk. Pengembang melihat pesan lengkap hanya saat terhubung melalui Xcode atau saat menggunakan profil pengumpulan dari perangkat yang terhubung ke Mac yang sama.
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")
// Di log produksi: "User login: <private>"
// Di debugging melalui Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")
Angka (Int, Double, Float) secara default dianggap public — dapat dicatat dengan aman tanpa penandaan. String (String, NSString, StaticString) dan objek (NSObject, CFType) secara default private — ditutupi di produksi. String statis (literal string dalam tanda kutip di dalam string format) selalu terlihat — ini adalah bagian dari pesan itu sendiri, bukan data.
Perilaku ini berbeda dari NSLog, di mana semua data dicatat dalam bentuk terbuka. Migrasi ke os_log secara signifikan mengurangi risiko kebocoran data pengguna sensitif melalui log.
os_log 90–95% lebih cepat dari NSLog pada logging frekuensi tinggi. Dalam pengujian dengan 10.000 panggilan dalam loop, NSLog menciptakan keterlambatan sekitar 2,8 detik, sementara os_log melakukan panggilan yang sama dalam 0,3 detik. Perbedaan ini dijelaskan oleh penulisan sinkron ke disk di NSLog versus buffering asinkron di os_log.
Menurut data Apple Performance Lab (2016), aplikasi iOS dengan 20 panggilan logging per detik melalui NSLog kehilangan 5–8 frame animasi per detik karena pemblokiran thread utama. Dengan os_log tidak terjadi kehilangan frame, karena buffering terjadi di thread kernel terpisah.
| Parameter | NSLog | os_log |
|---|---|---|
| Mekanisme penulisan | Penulisan sinkron ke disk | Buffering asinkron di kernel |
| Waktu untuk 10.000 panggilan | ~2,8 dtk | ~0,3 dtk |
| Dampak pada FPS | Kehilangan 5–8 frame | 0 frame |
| Tingkat keparahan | Tidak ada | 5 tingkat |
| Privasi | Semua data terbuka | Penutupan otomatis |
| Pemfilteran | Tidak didukung | Berdasarkan subsystem / category / level |
os_log memiliki dua API: C klasik os_log_create dan wrapper Swift modern Logger, diperkenalkan di iOS 14. Swift Logger menggunakan sistem ResultBuilder untuk pemformatan — argumen diinterpolasi melalui literal string dengan penandaan privasi eksplisit.
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
func handleResponse(statusCode: Int) {
if statusCode > 399 {
logger.error("HTTP error: \(statusCode, privacy: .public)")
} else {
logger.info("Response OK: \(statusCode)")
}
}
log collect — utilitas baris perintah untuk mengekspor log yang terkumpul dari perangkat. Dijalankan dari Terminal setelah menghubungkan perangkat ke Mac melalui USB.
// Pengumpulan log ke .logarchive
// Di terminal: log collect --device --output ./app_logs.logarchive
// Melihat log subsystem: log show --subsystem com.example.app
// Logging dengan nilai dinamis
logger.log("User \(userId) opened screen \(screenName)")
Saat menggunakan Logger, penting untuk diingat bahwa argumen diinterpolasi melalui String Interpolation, bukan melalui string format seperti di versi C os_log. Ini lebih aman, tetapi memerlukan penentuan privacy secara eksplisit untuk setiap argumen jika perilaku default tidak sesuai dengan pengembang.
Pertanyaan yang Sering Diajukan
os_log mem-buffer pesan secara asinkron di kernel dan tidak memblokir thread utama, sedangkan NSLog menulis secara sinkron ke disk. os_log 10 kali lebih cepat, memberikan 5 tingkat keparahan, dan secara otomatis menutupi data pribadi — NSLog tidak memiliki satu pun properti ini.
Untuk pesan debugging sementara, gunakan .debug — mereka dinonaktifkan di build produksi dan tidak memengaruhi kinerja pengguna. Untuk pesan penting yang harus selalu disimpan, gunakan .default atau .info.
Melalui Configure Profile di Xcode: Devices → pilih perangkat → Open Console → Actions → Configure Profile. Atur tingkat pengumpulan untuk subsystem yang diinginkan ke Include. Ini membuat profil yang aktif hingga perangkat di-restart pertama kali.
Ya, os_log berfungsi di semua aplikasi SwiftUI tanpa pengaturan tambahan. Buat Logger statis di model atau di ekstensi View dan gunakan di onChange, task, dan handler gesture untuk melacak siklus hidup layar.
os_log secara default menutupi string dan objek sebagai private. Untuk melihat nilai, tentukan secara eksplisit privacy: .public dalam interpolasi. Tanpa penandaan ini, nilai akan diganti dengan masker di build produksi, tetapi di debugging melalui Xcode akan ditampilkan secara normal.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga