os_log — είναι το unified logging API της Apple για iOS και macOS, το οποίο αντικατέστησε τα NSLog και os_trace. Σε αντίθεση με τους παλιούς μηχανισμούς, το os_log λειτουργεί σε επίπεδο πυρήνα: τα μηνύματα αποθηκεύονται προσωρινά σε έναν κυκλικό buffer και εγγράφονται στο δίσκο μόνο όταν επιτευχθεί το όριο δραστηριότητας. Σύμφωνα με τα δεδομένα του Apple WWDC 2016, το os_log μειώνει το φορτίο δίσκου 10 φορές σε σύγκριση με το NSLog και παρέχει έλεγχο του επιπέδου λεπτομέρειας μέσω κατηγοριών και τύπων. Είναι το κύριο διαγνωστικό εργαλείο για τον προγραμματιστή iOS: μέσω του Console.app τα μηνύματα μπορούν να φιλτραριστούν ανά διεργασία, κατηγορία και επίπεδο κρισιμότητας σε πραγματικό χρόνο.
Κύρια σημεία
os_log — είναι το unified logging API που παρουσιάστηκε από την Apple στο iOS 10 και macOS Sierra. Ενοποίησε τους διάσπαρτους μηχανισμούς καταγραφής NSLog, os_trace και syslog σε ένα ενιαίο σύστημα με προσωρινή αποθήκευση σε επίπεδο πυρήνα XNU.
Σε αντίθεση με το NSLog, το οποίο γράφει σύγχρονα κάθε μήνυμα στο δίσκο και μπλοκάρει το νήμα, το os_log χρησιμοποιεί έναν ασύγχρονο κυκλικό buffer στη μνήμη. Τα μηνύματα εγγράφονται στο δίσκο μόνο όταν η δραστηριότητα υπερβεί ένα συγκεκριμένο όριο ή με την εντολή log collect. Αυτό μειώνει δραστικά την επίδραση της καταγραφής στην απόδοση της εφαρμογής.
Το os_log υποστηρίζει έξι επίπεδα κρισιμότητας, διαφοροποίηση ανά subsystem και category, καθώς και ενσωματωμένο μηχανισμό απορρήτου: δεδομένα που επισημαίνονται ως private αποκρύπτονται αυτόματα στις καταγραφές παραγωγής και είναι προσβάσιμα μόνο στον προγραμματιστή όταν είναι συνδεδεμένο το Xcode.
Πριν από το iOS 10, οι προγραμματιστές χρησιμοποιούσαν NSLog για εντοπισμό σφαλμάτων και syslog για μηνύματα συστήματος. Το NSLog έγραφε στο stderr και στην κονσόλα, αλλά ήταν εξαιρετικά αναποτελεσματικό: κάθε μήνυμα εγγραφόταν σύγχρονα στο δίσκο, προκαλώντας καθυστερήσεις στο UI κατά τη συχνή καταγραφή. Το os_log έλυσε αυτό το πρόβλημα μεταφέροντας την προσωρινή αποθήκευση στο επίπεδο του τμήματος BSD του πυρήνα XNU και κάνοντας την εγγραφή στο δίσκο ασύγχρονη.
os_log χρησιμοποιείται σε όλες τις εφαρμογές της Apple και συνιστάται από την Apple ως το μοναδικό API καταγραφής για iOS, macOS, tvOS και watchOS. Το σύστημα και οι εφαρμογές τρίτων γράφουν μέσω αυτού μηνύματα σε μια ενιαία βάση δεδομένων — αποθηκευμένη στη μνήμη και περιοδικά εκκενώνεται στο δίσκο. Αυτές οι καταγραφές μπορούν να αναλυθούν μέσω του Console.app σε Mac ή μέσω της εντολής log στο τερματικό.
Η αρχιτεκτονική του os_log αποτελείται από τρία επίπεδα: API πελάτη στο χώρο χρήστη (libsystem_trace.dylib), κυκλικό buffer στον πυρήνα XNU και τον δαίμονα logd, ο οποίος εκκενώνει ασύγχρονα τον buffer στο δίσκο.
Όταν η εφαρμογή καλεί το os_log, το μήνυμα αντιγράφεται στον κυκλικό buffer του πυρήνα μεγέθους μερικών megabyte. Ο buffer λειτουργεί βάσει της αρχής FIFO: αν γεμίσει, τα παλιά μηνύματα αντικαθίστανται από νέα. Ο δαίμονας logd ελέγχει περιοδικά τον buffer και αποθηκεύει τα μηνύματα σε αρχεία .tracev3 σε μια προστατευόμενη περιοχή του συστήματος αρχείων.
Σύμφωνα με δεδομένα της Apple Engineering, η τυπική καθυστέρηση από την κλήση του os_log έως την εμφάνιση του μηνύματος στο Console.app είναι 1–5 δευτερόλεπτα στη συσκευή και έως 60 δευτερόλεπτα κατά την εκκένωση παρτίδας στο δίσκο. Αυτός είναι ένας συνειδητός συμβιβασμός: η απόδοση της εφαρμογής δεν υποφέρει λόγω καταγραφής, αλλά ο προγραμματιστής βλέπει τα μηνύματα με μικρή καθυστέρηση.
// Δήλωση os_log μέσω OSLog
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
Ο κυκλικός buffer του os_log έχει σταθερό όγκο και δεν μπορεί να αλλάξει από τον χώρο χρήστη. Το μέγεθος του buffer κυμαίνεται από 256 KB στο Apple Watch έως 4 MB σε Mac. Όταν η εφαρμογή παράγει περισσότερα μηνύματα από όσα χωράει ο buffer, τα παλιά μηνύματα χάνονται — αυτή είναι αναμενόμενη συμπεριφορά για καταγραφή υψηλού όγκου.
Για μακροπρόθεσμη συλλογή όλων των μηνυμάτων χρησιμοποιείται η εντολή log collect, η οποία ξεκινά τον δαίμονα συλλογής στη συσκευή και εξάγει το .logarchive στον υπολογιστή του προγραμματιστή. Σε αυτήν τη λειτουργία, ο buffer δεν αντικαθίσταται — τα μηνύματα γράφονται απευθείας στο αρχείο.
os_log υποστηρίζει πέντε επίπεδα κρισιμότητας, το καθένα υπεύθυνο για έναν ξεχωριστό τύπο μηνύματος και επεξεργάζεται διαφορετικά από το σύστημα. Το επίπεδο Default — βασικό για μηνύματα που φτάνουν πάντα στον buffer. Τα Info και Debug απενεργοποιούνται στις εκδόσεις παραγωγής χωρίς προφίλ συλλογής. Τα Error και Fault είναι πάντα ενεργά και επισημαίνονται με ειδική σημαία στη βάση δεδομένων.
| Επίπεδο | Σημασία | Προεπιλεγμένη είσοδος στον buffer |
|---|---|---|
| Default | Συνήθη μηνύματα σημαντικά για διάγνωση | Ναι |
| Info | Πληροφοριακά μηνύματα για λεπτομερή ανάλυση | Όχι (μόνο με προφίλ) |
| Debug | Μηνύματα εντοπισμού σφαλμάτων για ανάπτυξη | Όχι (μόνο με προφίλ) |
| Error | Σφάλματα που απαιτούν προσοχή | Ναι |
| Fault | Κρίσιμες βλάβες που οδηγούν σε κατάρρευση | Ναι |
Η επιλογή του σωστού επιπέδου κρισιμότητας είναι σημαντική για την απόδοση: τα Info και Debug δεν εγγράφονται στο δίσκο σε κανονική λειτουργία, επομένως μπορούν να χρησιμοποιηθούν άφθονα χωρίς τον κίνδυνο επιβράδυνσης της εφαρμογής. Τα Error και Fault αποθηκεύονται πάντα, αλλά ο αριθμός τους πρέπει να είναι ελάχιστος — κάθε τέτοιο μήνυμα αυξάνει τον χρόνο εγγραφής λόγω πρόσθετων μεταδεδομένων.
Subsystem — είναι το αναγνωριστικό της εφαρμογής ή της μονάδας σε μορφή reverse-DNS (com.example.app). Category — ετικέτα κειμένου εντός του subsystem, η οποία ομαδοποιεί τις καταγραφές ανά λειτουργικές περιοχές: network, ui, database, auth. Αυτή η ιεραρχία επιτρέπει το φιλτράρισμα των καταγραφών χωρίς ανάγνωση κάθε μηνύματος και τη συλλογή στατιστικών για κάθε module ξεχωριστά.
Η Apple συνιστά τον ορισμό ενός OSLog ανά module και τη χρήση του σε όλα τα αρχεία αυτού του module. Για διαφορετικά επίπεδα της εφαρμογής — networking, UI, persistence — πρέπει να δημιουργηθούν ξεχωριστές κατηγορίες. Τότε στο Console.app μπορούν να ενεργοποιηθούν οι καταγραφές μόνο για network και να απενεργοποιηθούν για τα υπόλοιπα, χωρίς μεταγλώττιση της εφαρμογής.
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 παρέχει έναν ενσωματωμένο μηχανισμό ελέγχου απορρήτου: κάθε τιμή στη συμβολοσειρά μορφοποίησης μπορεί να επισημανθεί ως public, private ή auto (προεπιλεγμένη συμπεριφορά). Από προεπιλογή, το os_log θεωρεί όλες τις δυναμικές συμβολοσειρές και αντικείμενα ως δυνητικά εμπιστευτικά και τα αντικαθιστά με τη μάσκα <private> στις καταγραφές παραγωγής.
Αυτό είναι κρίσιμο για τη συμμόρφωση με τις απαιτήσεις GDPR και HIPAA: εάν η εφαρμογή καταγράφει το email του χρήστη ή τον αριθμό κάρτας μέσω os_log σε αυτόματη λειτουργία, τα πραγματικά δεδομένα δεν φτάνουν ποτέ στο δίσκο. Ο προγραμματιστής βλέπει το πλήρες μήνυμα μόνο όταν συνδέεται μέσω Xcode ή όταν χρησιμοποιεί προφίλ συλλογής από συσκευή συνδεδεμένη στο ίδιο Mac.
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")
// Σε καταγραφές παραγωγής: "User login: <private>"
// Στον εντοπισμό σφαλμάτων μέσω Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")
Αριθμοί (Int, Double, Float) από προεπιλογή θεωρούνται public — μπορούν να καταγραφούν με ασφάλεια χωρίς επισήμανση. Συμβολοσειρές (String, NSString, StaticString) και αντικείμενα (NSObject, CFType) από προεπιλογή είναι private — αποκρύπτονται στην παραγωγή. Στατικές συμβολοσειρές (string literals σε εισαγωγικά εντός της συμβολοσειράς μορφοποίησης) είναι πάντα ορατές — αποτελούν μέρος του ίδιου του μηνύματος, όχι δεδομένα.
Αυτή η συμπεριφορά διαφέρει από το NSLog, όπου όλα τα δεδομένα καταγράφονταν σε ανοιχτή μορφή. Η μετάβαση στο os_log μειώνει σημαντικά τον κίνδυνο διαρροής ευαίσθητων δεδομένων χρήστη μέσω καταγραφών.
os_log είναι 90–95% ταχύτερο από το NSLog σε καταγραφή υψηλής συχνότητας. Σε μια δοκιμή με 10.000 κλήσεις σε βρόχο, το NSLog δημιουργεί καθυστέρηση περίπου 2,8 δευτερολέπτων, ενώ το os_log εκτελεί τις ίδιες κλήσεις σε 0,3 δευτερόλεπτα. Η διαφορά εξηγείται από τη σύγχρονη εγγραφή στο δίσκο στο NSLog σε σύγκριση με την ασύγχρονη προσωρινή αποθήκευση στο os_log.
Σύμφωνα με δεδομένα του Apple Performance Lab (2016), μια εφαρμογή iOS με 20 κλήσεις καταγραφής ανά δευτερόλεπτο μέσω NSLog χάνει 5–8 καρέ κινούμενων σχεδίων ανά δευτερόλεπτο λόγω μπλοκαρίσματος του κύριου νήματος. Με το os_log δεν υπάρχει απώλεια καρέ, καθώς η προσωρινή αποθήκευση γίνεται σε ξεχωριστό νήμα πυρήνα.
| Παράμετρος | NSLog | os_log |
|---|---|---|
| Μηχανισμός εγγραφής | Σύγχρονη εγγραφή στο δίσκο | Ασύγχρονη προσωρινή αποθήκευση στον πυρήνα |
| Χρόνος για 10.000 κλήσεις | ~2,8 δευτ | ~0,3 δευτ |
| Επίδραση στο FPS | Απώλεια 5–8 καρέ | 0 καρέ |
| Επίπεδα κρισιμότητας | Κανένα | 5 επίπεδα |
| Απόρρητο | Όλα τα δεδομένα ανοιχτά | Αυτόματη απόκρυψη |
| Φιλτράρισμα | Δεν υποστηρίζεται | Ανά subsystem / category / level |
os_log έχει δύο API: το κλασικό C os_log_create και το σύγχρονο Swift wrapper Logger, που παρουσιάστηκε στο iOS 14. Το Swift Logger χρησιμοποιεί το σύστημα ResultBuilder για μορφοποίηση — τα ορίσματα παρεμβάλλονται μέσω string literals με ρητή επισήμανση απορρήτου.
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 — βοηθητικό πρόγραμμα γραμμής εντολών για εξαγωγή συλλεγμένων καταγραφών από τη συσκευή. Εκτελείται από το Τερματικό αφού συνδέσετε τη συσκευή στο Mac μέσω USB.
// Συλλογή καταγραφών σε .logarchive
// Στο τερματικό: log collect --device --output ./app_logs.logarchive
// Προβολή καταγραφών subsystem: log show --subsystem com.example.app
// Καταγραφή με δυναμικές τιμές
logger.log("User \(userId) opened screen \(screenName)")
Κατά τη χρήση του Logger, είναι σημαντικό να θυμάστε ότι τα ορίσματα παρεμβάλλονται μέσω String Interpolation, όχι μέσω συμβολοσειρών μορφοποίησης όπως στην έκδοση C του os_log. Αυτό είναι ασφαλέστερο, αλλά απαιτεί ρητό καθορισμό του privacy για κάθε όρισμα εάν η προεπιλεγμένη συμπεριφορά δεν ικανοποιεί τον προγραμματιστή.
Συχνές Ερωτήσεις
Το os_log αποθηκεύει προσωρινά μηνύματα ασύγχρονα στον πυρήνα και δεν μπλοκάρει το κύριο νήμα, ενώ το NSLog γράφει σύγχρονα στο δίσκο. Το os_log είναι 10 φορές ταχύτερο, παρέχει 5 επίπεδα κρισιμότητας και αποκρύπτει αυτόματα ιδιωτικά δεδομένα — το NSLog δεν έχει καμία από αυτές τις ιδιότητες.
Για προσωρινά μηνύματα εντοπισμού σφαλμάτων χρησιμοποιήστε .debug — απενεργοποιούνται στην έκδοση παραγωγής και δεν επηρεάζουν την απόδοση των χρηστών. Για σημαντικά μηνύματα που πρέπει πάντα να διατηρούνται, χρησιμοποιήστε .default ή .info.
Μέσω Configure Profile στο Xcode: Devices → επιλέξτε συσκευή → Open Console → Actions → Configure Profile. Ορίστε το επίπεδο συλλογής για το επιθυμητό subsystem σε Include. Αυτό δημιουργεί ένα προφίλ που είναι ενεργό μέχρι την πρώτη επανεκκίνηση της συσκευής.
Ναι, το os_log λειτουργεί σε όλες τις εφαρμογές SwiftUI χωρίς πρόσθετες ρυθμίσεις. Δημιουργήστε ένα στατικό Logger στο μοντέλο ή σε μια επέκταση View και χρησιμοποιήστε το σε onChange, task και χειριστές χειρονομιών για παρακολούθηση του κύκλου ζωής οθονών.
Το os_log από προεπιλογή αποκρύπτει συμβολοσειρές και αντικείμενα ως private. Για να δείτε την τιμή, καθορίστε ρητά privacy: .public στην παρεμβολή. Χωρίς αυτήν την επισήμανση, οι τιμές θα αντικατασταθούν με μάσκα στις εκδόσεις παραγωγής, αλλά στον εντοπισμό σφαλμάτων μέσω Xcode εμφανίζονται κανονικά.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης