os_log ist Apples einheitliche Logging-API für iOS und macOS, die NSLog und os_trace ersetzt hat. Im Gegensatz zu älteren Mechanismen arbeitet os_log auf Kernel-Ebene: Nachrichten werden in einem Ringpuffer zwischengespeichert und nur dann auf die Festplatte geschrieben, wenn eine Aktivitätsschwelle erreicht wird. Laut Apple WWDC 2016 reduziert os_log die Festplattenlast um das 10-fache im Vergleich zu NSLog und bietet Kontrolle über den Detailgrad durch Kategorien und Typen. Es ist das primäre Diagnosetool für iOS-Entwickler: Über Console.app können Nachrichten in Echtzeit nach Prozess, Kategorie und Kritikalitätsgrad gefiltert werden.
Wichtige Punkte
os_log ist eine einheitliche Logging-API, die von Apple in iOS 10 und macOS Sierra eingeführt wurde. Sie vereinte die unterschiedlichen Logging-Mechanismen NSLog, os_trace und syslog in einem einzigen System mit Pufferung auf XNU-Kernel-Ebene.
Im Gegensatz zu NSLog, das jede Nachricht synchron auf die Festplatte schreibt und den Thread blockiert, verwendet os_log einen asynchronen Ringpuffer im Speicher. Nachrichten werden nur dann auf die Festplatte geschrieben, wenn die Aktivität einen festgelegten Schwellenwert überschreitet oder auf Befehl von log collect. Dadurch werden die Auswirkungen des Loggings auf die Anwendungsleistung drastisch reduziert.
os_log unterstützt sechs Kritikalitätsstufen, eine Unterscheidung nach subsystem und category sowie einen integrierten Datenschutzmechanismus: Als private markierte Daten werden in Produktionslogs automatisch maskiert und sind nur für den Entwickler sichtbar, wenn er über Xcode verbunden ist.
Vor iOS 10 verwendeten Entwickler NSLog zum Debuggen und syslog für Systemmeldungen. NSLog schrieb in stderr und die Konsole, war aber äußerst ineffizient: Jede Nachricht wurde synchron auf die Festplatte geschrieben, was bei häufigen Logging zu Verzögerungen in der Benutzeroberfläche führte. os_log löste dieses Problem, indem es die Pufferung in den BSD-Teil des XNU-Kernels verlagerte und die Festplattenschreibvorgänge asynchron machte.
os_log wird in allen Apple-Anwendungen verwendet und von Apple als die einzige Logging-API für iOS, macOS, tvOS und watchOS empfohlen. Das System und Drittanbieter-Apps schreiben darüber Nachrichten in eine einheitliche Datenbank — sie wird im Speicher gehalten und regelmäßig auf die Festplatte ausgelagert. Diese Logs können über die Console.app auf dem Mac oder über den Befehl log im Terminal analysiert werden.
Die Architektur von os_log besteht aus drei Schichten: einer clientseitigen API im Benutzerbereich (libsystem_trace.dylib), einem Ringpuffer im XNU-Kernel und dem logd-Dämon, der den Puffer asynchron auf die Festplatte schreibt.
Wenn eine Anwendung os_log aufruft, wird die Nachricht in einen Kernel-Ringpuffer von mehreren Megabyte Größe kopiert. Der Puffer arbeitet nach dem FIFO-Prinzip: Wenn er voll ist, werden ältere Nachrichten durch neuere überschrieben. Der logd-Dämon überprüft regelmäßig den Puffer und speichert die Nachrichten in .tracev3-Dateien in einem geschützten Bereich des Dateisystems.
Laut Apple Engineering beträgt die typische Verzögerung vom Aufruf von os_log bis zum Erscheinen der Nachricht in der Console.app 1–5 Sekunden auf einem Gerät und bis zu 60 Sekunden beim Schreiben auf die Festplatte im Batch-Modus. Dies ist ein bewusster Kompromiss: Die Anwendungsleistung wird durch das Logging nicht beeinträchtigt, aber der Entwickler sieht die Nachrichten mit einer leichten Verzögerung.
// os_log-Deklaration über OSLog
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
Der Ringpuffer von os_log hat eine feste Größe und kann vom Benutzerbereich aus nicht geändert werden. Die Puffergröße reicht von 256 KB auf der Apple Watch bis zu 4 MB auf dem Mac. Wenn eine Anwendung mehr Nachrichten erzeugt, als der Puffer aufnehmen kann, gehen ältere Nachrichten verloren — dies ist bei umfangreichem Logging ein erwartetes Verhalten.
Für die langfristige Erfassung aller Nachrichten wird der Befehl log collect verwendet. Er startet einen Erfassungsdämon auf dem Gerät und exportiert ein .logarchive auf den Computer des Entwicklers. In diesem Modus wird der Puffer nicht überschrieben — die Nachrichten werden direkt in das Archiv geschrieben.
os_log unterstützt fünf Kritikalitätsstufen, die jeweils für verschiedene Nachrichtentypen zuständig sind und vom System unterschiedlich verarbeitet werden. Default ist die Basisstufe für Nachrichten, die immer in den Puffer gelangen. Info und Debug werden in Produktions-Builds ohne Erfassungsprofil deaktiviert. Error und Fault sind immer aktiv und werden in der Datenbank mit einem speziellen Flag markiert.
| Stufe | Bedeutung | Standardeintritt in Puffer |
|---|---|---|
| Default | Normale, für die Diagnose wichtige Nachrichten | Ja |
| Info | Informationsnachrichten für detaillierte Analysen | Nein (nur mit Profil) |
| Debug | Debug-Nachrichten für die Entwicklung | Nein (nur mit Profil) |
| Error | Fehler, die Aufmerksamkeit erfordern | Ja |
| Fault | Kritische Ausfälle, die zu Abstürzen führen | Ja |
Die Wahl der richtigen Kritikalitätsstufe ist wichtig für die Leistung: Info und Debug werden im normalen Modus nicht auf die Festplatte geschrieben, daher können sie reichlich verwendet werden, ohne die Anwendung zu verlangsamen. Error und Fault werden immer gespeichert, aber ihre Anzahl sollte minimal sein — jede solche Nachricht erhöht die Schreibzeit aufgrund zusätzlicher Metadaten.
Subsystem ist eine Anwendungs- oder Modulkennung im Reverse-DNS-Format (com.example.app). Category ist eine Textbezeichnung innerhalb eines subsystem, die Logs nach Funktionsbereichen gruppiert: network, ui, database, auth. Diese Hierarchie ermöglicht das Filtern von Logs ohne Lesen jeder einzelnen Nachricht und das separate Erfassen von Statistiken für jedes Modul.
Apple empfiehlt, ein OSLog pro Modul zu definieren und es in allen Dateien dieses Moduls zu verwenden. Für verschiedene Anwendungsschichten — Networking, UI, Persistenz — sollten separate Kategorien erstellt werden. Dann können Sie in der Console.app Logs nur für network aktivieren und für andere deaktivieren, ohne die Anwendung neu zu kompilieren.
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 bietet einen integrierten Datenschutz-Kontrollmechanismus: Jeder Wert in einer Formatzeichenfolge kann als public, private oder auto (Standardverhalten) markiert werden. Standardmäßig betrachtet os_log alle dynamischen Zeichenfolgen und Objekte als potenziell vertraulich und ersetzt sie in Produktionslogs durch die Maske <private>.
Dies ist für die Einhaltung von DSGVO und HIPAA von entscheidender Bedeutung: Wenn eine Anwendung die E-Mail oder Kartennummer eines Benutzers über os_log im Auto-Modus protokolliert, gelangen die tatsächlichen Daten niemals auf die Festplatte. Der Entwickler sieht die vollständige Nachricht nur, wenn er über Xcode verbunden ist oder ein Erfassungsprofil von einem mit demselben Mac verbundenen Gerät verwendet.
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")
// In Produktionslogs: „User login: “
// Im Xcode-Debugging: „User login: user@example.com“
logger.log("Payment token: \(token)")
Zahlen (Int, Double, Float) gelten standardmäßig als öffentlich — sie können ohne Markierung sicher protokolliert werden. Zeichenfolgen (String, NSString, StaticString) und Objekte (NSObject, CFType) sind standardmäßig privat — sie werden in der Produktion maskiert. Statische Zeichenfolgen (Zeichenfolgenliterale in Anführungszeichen innerhalb der Formatzeichenfolge) sind immer sichtbar — sie sind Teil der Nachricht selbst, keine Daten.
Dieses Verhalten unterscheidet sich von NSLog, bei dem alle Daten im Klartext protokolliert wurden. Der Wechsel zu os_log reduziert das Risiko der Offenlegung vertraulicher Benutzerdaten durch Protokolle erheblich.
os_log ist bei hochfrequentem Logging 90–95% schneller als NSLog. In einem Test mit 10.000 Aufrufen in einer Schleife verursacht NSLog eine Verzögerung von etwa 2,8 Sekunden, während os_log dieselben Aufrufe in 0,3 Sekunden ausführt. Der Unterschied erklärt sich durch die synchronen Festplattenschreibvorgänge bei NSLog im Vergleich zur asynchronen Pufferung bei os_log.
Laut Apple Performance Lab (2016) verliert eine iOS-Anwendung mit 20 Logging-Aufrufen pro Sekunde über NSLog aufgrund der Blockierung des Hauptthreads 5–8 Animationsbilder pro Sekunde. Bei os_log gibt es keinen Bildverlust, da die Pufferung in einem separaten Kernel-Thread erfolgt.
| Parameter | NSLog | os_log |
|---|---|---|
| Schreibmechanismus | Synchroner Festplattenschreibvorgang | Asynchrone Kernel-Pufferung |
| Zeit für 10.000 Aufrufe | ~2,8 s | ~0,3 s |
| Auswirkung auf FPS | Verlust von 5–8 Bildern | 0 Bilder |
| Kritikalitätsstufen | Keine | 5 Stufen |
| Datenschutz | Alle Daten sichtbar | Automatische Maskierung |
| Filterung | Nicht unterstützt | Nach subsystem / category / level |
os_log bietet zwei APIs: die klassische C-Art os_log_create und den modernen Swift-Wrapper Logger, der in iOS 14 eingeführt wurde. Der Swift-Logger verwendet das ResultBuilder-System für die Formatierung — Argumente werden über Zeichenfolgenliterale mit expliziter Datenschutzkennzeichnung interpoliert.
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 ist ein Befehlszeilenprogramm zum Exportieren gesammelter Logs von einem Gerät. Es wird im Terminal ausgeführt, nachdem das Gerät über USB mit einem Mac verbunden wurde.
// Logs in .logarchive sammeln
// Im Terminal: log collect --device --output ./app_logs.logarchive
// Subsystem-Logs anzeigen: log show --subsystem com.example.app
// Protokollierung mit dynamischen Werten
logger.log("User \(userId) opened screen \(screenName)")
Bei Verwendung von Logger ist es wichtig zu beachten, dass Argumente über String Interpolation interpoliert werden, nicht über Formatstrings wie in der C-Version von os_log. Dies ist sicherer, erfordert jedoch eine explizite Datenschutzkennzeichnung für jedes Argument, wenn das Standardverhalten für den Entwickler nicht geeignet ist.
Häufig gestellte Fragen
os_log puffert Nachrichten asynchron im Kernel und blockiert den Hauptthread nicht, während NSLog synchron auf die Festplatte schreibt. os_log ist 10-mal schneller, bietet 5 Kritikalitätsstufen und maskiert automatisch private Daten — NSLog hat keine dieser Eigenschaften.
Für temporäre Debug-Meldungen verwenden Sie .debug — sie werden in Produktions-Builds deaktiviert und beeinträchtigen die Benutzerleistung nicht. Für wichtige Meldungen, die immer erhalten bleiben sollen, verwenden Sie .default oder .info.
Über Configure Profile in Xcode: Devices → Gerät auswählen → Open Console → Actions → Configure Profile. Setzen Sie die Erfassungsstufe für das gewünschte subsystem auf Include. Dadurch wird ein Profil erstellt, das bis zum ersten Neustart des Geräts aktiv bleibt.
Ja, os_log funktioniert in allen SwiftUI-Anwendungen ohne zusätzliche Einrichtung. Erstellen Sie einen statischen Logger in Ihrem Modell oder in einer View-Erweiterung und verwenden Sie ihn in onChange, task und Gesten-Handlern, um den Lebenszyklus von Bildschirmen zu verfolgen.
Standardmäßig maskiert os_log Zeichenfolgen und Objekte als private. Um den Wert zu sehen, geben Sie in der Interpolation explizit privacy: .public an. Ohne diese Kennzeichnung werden die Werte in Produktions-Builds durch die Maske ersetzt, in der Xcode-Debugging werden sie jedoch normal angezeigt.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch