os_log là API ghi nhật ký hợp nhất của Apple dành cho iOS và macOS, thay thế NSLog và os_trace. Không giống như các cơ chế cũ, os_log hoạt động ở cấp nhân: các thông báo được lưu vào bộ đệm vòng và chỉ ghi vào đĩa khi đạt đến ngưỡng hoạt động. Theo Apple WWDC 2016, os_log giảm tải đĩa gấp 10 lần so với NSLog và cung cấp khả năng kiểm soát mức độ chi tiết thông qua danh mục và loại. Đây là công cụ chẩn đoán chính cho nhà phát triển iOS: thông qua Console.app, bạn có thể lọc thông báo theo tiến trình, danh mục và mức độ nghiêm trọng trong thời gian thực.
Các điểm chính
os_log là API ghi nhật ký hợp nhất được Apple giới thiệu trong iOS 10 và macOS Sierra. Nó hợp nhất các cơ chế ghi nhật ký riêng rẽ NSLog, os_trace và syslog thành một hệ thống duy nhất với bộ đệm ở cấp nhân XNU.
Không giống như NSLog, ghi từng thông báo đồng bộ lên đĩa và chặn luồng, os_log sử dụng bộ đệm vòng không đồng bộ trong bộ nhớ. Các thông báo chỉ được đẩy xuống đĩa khi hoạt động vượt quá ngưỡng đã đặt hoặc theo lệnh log collect. Điều này làm giảm triệt để tác động của việc ghi nhật ký lên hiệu suất ứng dụng.
os_log hỗ trợ sáu mức nghiêm trọng, phân biệt theo subsystem và category, cùng cơ chế quyền riêng tư tích hợp: dữ liệu được đánh dấu là private sẽ tự động bị che trong nhật ký sản xuất và chỉ khả dụng cho nhà phát triển khi kết nối qua Xcode.
Trước iOS 10, các nhà phát triển sử dụng NSLog để gỡ lỗi và syslog cho thông báo hệ thống. NSLog ghi vào stderr và bảng điều khiển, nhưng cực kỳ kém hiệu quả: mỗi thông báo được ghi đồng bộ lên đĩa, gây ra độ trễ trong giao diện người dùng khi ghi nhật ký thường xuyên. os_log đã giải quyết vấn đề này bằng cách chuyển bộ đệm sang phần BSD của nhân XNU và làm cho việc ghi đĩa không đồng bộ.
os_log được sử dụng trong tất cả các ứng dụng Apple và được Apple khuyến nghị là API ghi nhật ký duy nhất cho iOS, macOS, tvOS và watchOS. Hệ thống và các ứng dụng bên thứ ba ghi thông báo qua nó vào cơ sở dữ liệu hợp nhất — được lưu trữ trong bộ nhớ và định kỳ được đẩy xuống đĩa. Các nhật ký này có thể được phân tích qua Console.app trên Mac hoặc qua lệnh log trong terminal.
Kiến trúc của os_log bao gồm ba lớp: API phía máy khách trong không gian người dùng (libsystem_trace.dylib), bộ đệm vòng trong nhân XNU và trình nền logd đẩy bộ đệm không đồng bộ xuống đĩa.
Khi ứng dụng gọi os_log, thông báo được sao chép vào bộ đệm vòng nhân có kích thước vài megabyte. Bộ đệm hoạt động theo nguyên tắc FIFO: nếu đầy, các thông báo cũ bị ghi đè bởi thông báo mới. Trình nền logd định kỳ kiểm tra bộ đệm và lưu thông báo vào tệp .tracev3 trong vùng được bảo vệ của hệ thống tệp.
Theo Apple Engineering, độ trễ điển hình từ khi gọi os_log đến khi thông báo xuất hiện trong Console.app là 1–5 giây trên thiết bị và lên đến 60 giây khi đẩy xuống đĩa ở chế độ hàng loạt. Đây là sự đánh đổi có chủ ý: hiệu suất ứng dụng không bị ảnh hưởng bởi việc ghi nhật ký, nhưng nhà phát triển thấy thông báo với độ trễ nhỏ.
// Khai báo os_log qua OSLog
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
Bộ đệm vòng của os_log có kích thước cố định và không thể thay đổi từ không gian người dùng. Kích thước bộ đệm dao động từ 256 KB trên Apple Watch đến 4 MB trên Mac. Khi ứng dụng tạo ra nhiều thông báo hơn dung lượng bộ đệm, các thông báo cũ sẽ bị mất — đây là hành vi mong đợi đối với ghi nhật ký khối lượng lớn.
Để thu thập tất cả thông báo dài hạn, lệnh log collect được sử dụng. Nó khởi chạy trình nền thu thập trên thiết bị và xuất .logarchive sang máy tính của nhà phát triển. Ở chế độ này, bộ đệm không bị ghi đè — các thông báo được ghi trực tiếp vào kho lưu trữ.
os_log hỗ trợ năm mức nghiêm trọng, mỗi mức chịu trách nhiệm cho một loại thông báo khác nhau và được hệ thống xử lý khác nhau. Default là mức cơ sở cho các thông báo luôn vào bộ đệm. Info và Debug bị vô hiệu hóa trong bản dựng sản xuất mà không có hồ sơ thu thập. Error và Fault luôn hoạt động và được đánh dấu bằng cờ đặc biệt trong cơ sở dữ liệu.
| Cấp độ | Ý nghĩa | Vào bộ đệm mặc định |
|---|---|---|
| Default | Thông báo thông thường quan trọng cho chẩn đoán | Có |
| Info | Thông báo thông tin để phân tích chi tiết | Không (chỉ với hồ sơ) |
| Debug | Thông báo gỡ lỗi cho phát triển | Không (chỉ với hồ sơ) |
| Error | Lỗi cần chú ý | Có |
| Fault | Sự cố nghiêm trọng dẫn đến treo máy | Có |
Chọn đúng mức nghiêm trọng rất quan trọng cho hiệu suất: Info và Debug không được ghi vào đĩa ở chế độ thông thường, do đó có thể sử dụng nhiều mà không làm chậm ứng dụng. Error và Fault luôn được lưu, nhưng số lượng của chúng phải ở mức tối thiểu — mỗi thông báo như vậy làm tăng thời gian ghi do siêu dữ liệu bổ sung.
Subsystem là định danh ứng dụng hoặc mô-đun ở định dạng reverse-DNS (com.example.app). Category là nhãn chuỗi trong subsystem nhóm nhật ký theo lĩnh vực chức năng: network, ui, database, auth. Hệ thống phân cấp này cho phép lọc nhật ký mà không cần đọc từng thông báo và thu thập thống kê cho từng mô-đun riêng biệt.
Apple khuyến nghị định nghĩa một OSLog cho mỗi mô-đun và sử dụng nó trong tất cả các tệp của mô-đun đó. Đối với các lớp khác nhau của ứng dụng — networking, UI, persistence — cần tạo các danh mục riêng. Sau đó trong Console.app, bạn có thể bật nhật ký chỉ cho network và tắt cho các lớp khác mà không cần biên dịch lại ứng dụng.
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 cung cấp cơ chế kiểm soát quyền riêng tư tích hợp: mỗi giá trị trong chuỗi định dạng có thể được đánh dấu là public, private hoặc auto (hành vi mặc định). Theo mặc định, os_log coi tất cả chuỗi động và đối tượng là nhạy cảm tiềm ẩn và thay thế chúng bằng mặt nạ <private> trong nhật ký sản xuất.
Điều này rất quan trọng để tuân thủ GDPR và HIPAA: nếu ứng dụng ghi nhật ký email hoặc số thẻ của người dùng qua os_log ở chế độ tự động, dữ liệu thực tế không bao giờ đến được đĩa. Nhà phát triển chỉ thấy thông báo đầy đủ khi kết nối qua Xcode hoặc khi sử dụng hồ sơ thu thập từ thiết bị được kết nối với cùng một Mac.
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")
// Trong nhật ký sản xuất: "User login: "
// Trong gỡ lỗi Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")
Số (Int, Double, Float) được coi là công khai theo mặc định — có thể ghi nhật ký an toàn mà không cần đánh dấu. Chuỗi (String, NSString, StaticString) và đối tượng (NSObject, CFType) là private theo mặc định — chúng bị che trong sản xuất. Chuỗi tĩnh (chuỗi ký tự trong dấu ngoặc kép bên trong chuỗi định dạng) luôn hiển thị — chúng là một phần của thông báo, không phải dữ liệu.
Hành vi này khác với NSLog, nơi tất cả dữ liệu được ghi dưới dạng văn bản thuần túy. Chuyển sang os_log làm giảm đáng kể nguy cơ rò rỉ dữ liệu nhạy cảm của người dùng qua nhật ký.
os_log nhanh hơn 90–95% so với NSLog khi ghi nhật ký tần số cao. Trong thử nghiệm với 10.000 lần gọi trong vòng lặp, NSLog tạo ra độ trễ khoảng 2,8 giây, trong khi os_log thực hiện các lệnh gọi tương tự trong 0,3 giây. Sự khác biệt được giải thích bởi ghi đồng bộ lên đĩa trong NSLog so với bộ đệm không đồng bộ trong os_log.
Theo Apple Performance Lab (2016), ứng dụng iOS với 20 lần gọi ghi nhật ký mỗi giây qua NSLog mất 5–8 khung hình hoạt ảnh mỗi giây do chặn luồng chính. Với os_log không mất khung hình vì bộ đệm hoạt động trong một luồng nhân riêng biệt.
| Tham số | NSLog | os_log |
|---|---|---|
| Cơ chế ghi | Ghi đồng bộ lên đĩa | Bộ đệm không đồng bộ trong nhân |
| Thời gian cho 10.000 lần gọi | ~2,8 giây | ~0,3 giây |
| Tác động lên FPS | Mất 5–8 khung hình | 0 khung hình |
| Mức nghiêm trọng | Không có | 5 mức |
| Quyền riêng tư | Tất cả dữ liệu hiển thị | Tự động che |
| Lọc | Không hỗ trợ | Theo subsystem / category / level |
os_log có hai API: kiểu C cổ điển os_log_create và trình bao bọc Swift hiện đại Logger được giới thiệu trong iOS 14. Logger Swift sử dụng hệ thống ResultBuilder để định dạng — các đối số được nội suy qua chuỗi ký tự với đánh dấu quyền riêng tư rõ ràng.
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 là tiện ích dòng lệnh để xuất nhật ký đã thu thập từ thiết bị. Nó được chạy từ Terminal sau khi kết nối thiết bị với Mac qua USB.
// Thu thập nhật ký trong .logarchive
// Trong Terminal: log collect --device --output ./app_logs.logarchive
// Xem nhật ký subsystem: log show --subsystem com.example.app
// Ghi nhật ký với giá trị động
logger.log("User \(userId) opened screen \(screenName)")
Khi sử dụng Logger, điều quan trọng cần nhớ là các đối số được nội suy qua String Interpolation, không phải qua chuỗi định dạng như trong phiên bản C của os_log. Điều này an toàn hơn, nhưng yêu cầu đánh dấu quyền riêng tư rõ ràng cho từng đối số nếu hành vi mặc định không phù hợp với nhà phát triển.
Câu hỏi thường gặp
os_log lưu trữ thông báo không đồng bộ trong nhân và không chặn luồng chính, trong khi NSLog ghi đồng bộ lên đĩa. os_log nhanh gấp 10 lần, cung cấp 5 mức nghiêm trọng và tự động che dữ liệu riêng tư — NSLog không có bất kỳ tính năng nào trong số này.
Đối với thông báo gỡ lỗi tạm thời, hãy sử dụng .debug — chúng bị vô hiệu hóa trong bản dựng sản xuất và không ảnh hưởng đến hiệu suất của người dùng. Đối với thông báo quan trọng cần được lưu giữ mãi mãi, hãy sử dụng .default hoặc .info.
Thông qua Configure Profile trong Xcode: Devices → chọn thiết bị → Open Console → Actions → Configure Profile. Đặt mức thu thập cho subsystem mong muốn thành Include. Điều này tạo một hồ sơ hoạt động cho đến khi thiết bị khởi động lại lần đầu tiên.
Có, os_log hoạt động trong tất cả ứng dụng SwiftUI mà không cần cấu hình thêm. Tạo Logger tĩnh trong mô hình của bạn hoặc trong phần mở rộng của View và sử dụng nó trong onChange, task và trình xử lý cử chỉ để theo dõi vòng đời màn hình.
Theo mặc định, os_log che chuỗi và đối tượng là private. Để xem giá trị, hãy chỉ định rõ ràng privacy: .public trong nội suy. Nếu không có đánh dấu này, giá trị sẽ bị thay thế bằng mặt nạ trong bản dựng sản xuất, nhưng trong gỡ lỗi Xcode, chúng hiển thị bình thường.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm