os_log: wat is het, mogelijkheden en werking van unified logging in Apple

Auteur: IT Sectr Gepubliceerd: 2026-05-28 Leestijd: 9 min

os_log — is de unified logging API van Apple voor iOS en macOS, die NSLog en os_trace heeft vervangen. In tegenstelling tot oude mechanismen werkt os_log op kernelniveau: berichten worden gebufferd in een circulaire buffer en pas naar schijf geschreven wanneer een activiteitsdrempel wordt bereikt. Volgens Apple WWDC 2016 vermindert os_log de schijfbelasting met een factor 10 vergeleken met NSLog en geeft het controle over het detailniveau via categorieën en types. Het is het belangrijkste diagnostische hulpmiddel voor iOS-ontwikkelaars: via Console.app kunnen berichten in real-time worden gefilterd op proces, categorie en kritikaliteitsniveau.

Belangrijkste punten

  • os_log — systeem-API voor loggen van Apple, die berichten buffert in de kernel en de schijfbelasting tot 90% vermindert vergeleken met NSLog
  • Niveaus — Default, Info, Debug, Error, Fault — elk wordt onafhankelijk gefilterd en kan worden in- of uitgeschakeld via een logverzamelingsprofiel
  • Categorieën — tekstuele labels binnen één subsystem, waarmee logs per app-module kunnen worden gegroepeerd zonder aparte bestanden aan te maken
  • Privacy — os_log maskeert automatisch gegevens tussen aanhalingstekens die als private zijn gemarkeerd en versleutelt ze in productielogs
  • log collect — commandoregelhulpprogramma voor het exporteren van verzamelde logs van het apparaat voor latere analyse in Console.app

Wat is os_log

os_log — is de unified logging API geïntroduceerd door Apple in iOS 10 en macOS Sierra. Het verenigt de verspreide logmechanismen NSLog, os_trace en syslog in één systeem met buffering op XNU-kernelniveau.

In tegenstelling tot NSLog, dat elk bericht synchroon naar schijf schrijft en de thread blokkeert, gebruikt os_log een asynchrone circulaire buffer in het geheugen. Berichten worden alleen naar schijf weggeschreven wanneer de activiteit een bepaalde drempel overschrijdt of op commando log collect. Dit vermindert de impact van loggen op de app-prestaties drastisch.

os_log ondersteunt zes kritikaliteitsniveaus, differentiatie per subsystem en category, en een ingebouwd privacymechanisme: gegevens gemarkeerd als private worden automatisch gemaskeerd in productielogs en zijn alleen toegankelijk voor de ontwikkelaar wanneer Xcode is aangesloten.

Geschiedenis van unified logging

Vóór iOS 10 gebruikten ontwikkelaars NSLog voor debuggen en syslog voor systeemberichten. NSLog schreef naar stderr en de console, maar was uiterst inefficiënt: elk bericht werd synchroon naar schijf geschreven, wat bij frequent loggen vertragingen in de UI veroorzaakte. os_log loste dit probleem op door buffering naar het BSD-gedeelte van de XNU-kernel te verplaatsen en het schrijven naar schijf asynchroon te maken.

Waar wordt os_log toegepast

os_log wordt gebruikt in alle Apple-apps en wordt door Apple aanbevolen als de enige log-API voor iOS, macOS, tvOS en watchOS. Het systeem en apps van derden schrijven er berichten mee naar één database — opgeslagen in het geheugen en periodiek naar schijf weggeschreven. Deze logs kunnen worden geanalyseerd via Console.app op de Mac of via het commando log in de terminal.

Hoe werkt os_log: architectuur en buffering

De architectuur van os_log bestaat uit drie lagen: client-API in de gebruikersruimte (libsystem_trace.dylib), een circulaire buffer in de XNU-kernel en de logd-daemon, die de buffer asynchroon naar schijf wegschrijft.

Wanneer een app os_log aanroept, wordt het bericht gekopieerd naar een circulaire kernelbuffer van enkele megabytes. De buffer werkt volgens het FIFO-principe: als deze vol is, worden oude berichten overschreven door nieuwe. De logd-daemon controleert periodiek de buffer en slaat berichten op in .tracev3-bestanden in een beveiligd gebied van het bestandssysteem.

Volgens Apple Engineering bedraagt de typische vertraging van een os_log-aanroep tot het verschijnen van het bericht in Console.app 1–5 seconden op het apparaat en tot 60 seconden bij batchgewijs wegschrijven naar schijf. Dit is een bewuste afweging: de app-prestaties lijden niet onder het loggen, maar de ontwikkelaar ziet berichten met een kleine vertraging.

swift
// Declaratie van os_log via OSLog
import OSLog

let logger = Logger(
    subsystem: "com.example.app",
    category: "network"
)

De circulaire buffer en het instellen ervan

De circulaire buffer van os_log heeft een vaste capaciteit en kan niet worden gewijzigd vanuit de gebruikersruimte. De buffergrootte varieert van 256 KB op Apple Watch tot 4 MB op de Mac. Wanneer een app meer berichten genereert dan de buffer kan bevatten, gaan oude berichten verloren — dit is verwacht gedrag voor loggen met hoog volume.

Voor het langdurig verzamelen van alle berichten wordt het commando log collect gebruikt, dat de verzameldaemon op het apparaat start en .logarchive exporteert naar de computer van de ontwikkelaar. In deze modus wordt de buffer niet overschreven — berichten worden rechtstreeks naar het archief geschreven.

os_log-niveaus: Default, Info, Debug, Error, Fault

os_log ondersteunt vijf kritikaliteitsniveaus, elk verantwoordelijk voor een apart type bericht en verschillend verwerkt door het systeem. Niveau Default — basis voor berichten die altijd in de buffer terechtkomen. Info en Debug worden uitgeschakeld in productiebuilds zonder verzamelprofiel. Error en Fault zijn altijd actief en gemarkeerd met een speciale vlag in de database.

NiveauBetekenisStandaard in buffer
DefaultGewone berichten belangrijk voor diagnostiekJa
InfoInformatieberichten voor gedetailleerde analyseNee (alleen met profiel)
DebugDebugberichten voor ontwikkelingNee (alleen met profiel)
ErrorFouten die aandacht vereisenJa
FaultKritieke storingen die tot crashes leidenJa

Het kiezen van het juiste kritikaliteitsniveau is belangrijk voor de prestaties: Info en Debug worden in de normale modus niet naar schijf geschreven, dus ze kunnen overvloedig worden gebruikt zonder het risico de app te vertragen. Error en Fault worden altijd opgeslagen, maar hun aantal moet minimaal zijn — elk dergelijk bericht verlengt de schrijftijd vanwege extra metadata.

Categorieën en subsystem in os_log

Subsystem — is de identificatie van een app of module in reverse-DNS-formaat (com.example.app). Category — een tekstueel label binnen het subsystem dat logs groepeert op functionele gebieden: network, ui, database, auth. Deze hiërarchie maakt het mogelijk logs te filteren zonder elk bericht te lezen en per module apart statistieken te verzamelen.

Apple raadt aan om één OSLog per module te definiëren en deze in alle bestanden van die module te gebruiken. Voor verschillende lagen van de app — networking, UI, persistence — moeten aparte categorieën worden aangemaakt. Dan kunnen in Console.app de logs alleen voor network worden ingeschakeld en voor de rest worden uitgeschakeld, zonder de app opnieuw te compileren.

swift
import OSLog

extension Logger {
    static let network = Logger(
        subsystem: "com.example.app",
        category: "network"
    )
    static let ui = Logger(
        subsystem: "com.example.app",
        category: "ui"
    )
}

Gegevensprivacy in os_log

os_log biedt een ingebouwd mechanisme voor privacycontrole: elke waarde in de opmaakstring kan worden gemarkeerd als public, private of auto (standaardgedrag). Standaard beschouwt os_log alle dynamische strings en objecten als potentieel vertrouwelijk en vervangt ze door de masker <private> in productielogs.

Dit is van cruciaal belang voor naleving van GDPR- en HIPAA-vereisten: als een app de e-mail van een gebruiker of een kaartnummer via os_log in de automatische modus logt, komen de echte gegevens nooit op de schijf. De ontwikkelaar ziet het volledige bericht alleen bij verbinding via Xcode of bij gebruik van een verzamelprofiel van een apparaat dat op dezelfde Mac is aangesloten.

swift
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")

// In productielogs: "User login: <private>"
// Bij debuggen via Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")

Standaard privacyregels

Getallen (Int, Double, Float) worden standaard als public beschouwd — ze kunnen veilig worden gelogd zonder markering. Strings (String, NSString, StaticString) en objecten (NSObject, CFType) zijn standaard private — ze worden in productie gemaskeerd. Statische strings (stringliteralen tussen aanhalingstekens binnen de opmaakstring) zijn altijd zichtbaar — ze maken deel uit van het bericht zelf, niet van de gegevens.

Dit gedrag verschilt van NSLog, waar alle gegevens in open vorm werden gelogd. De overstap naar os_log vermindert het risico op lekkage van gevoelige gebruikersgegevens via logs aanzienlijk.

os_log vs NSLog: prestatievergelijking

os_log is 90–95% sneller dan NSLog bij hoogfrequent loggen. In een test met 10.000 aanroepen in een lus veroorzaakt NSLog een vertraging van ongeveer 2,8 seconden, terwijl os_log dezelfde aanroepen in 0,3 seconden uitvoert. Het verschil wordt verklaard door synchroon schrijven naar schijf in NSLog versus asynchrone buffering in os_log.

Volgens Apple Performance Lab (2016) verliest een iOS-app met 20 logaanroepen per seconde via NSLog 5–8 animatieframes per seconde door het blokkeren van de hoofdthread. Met os_log treedt geen frameverlies op, omdat buffering plaatsvindt in een aparte kernelthread.

ParameterNSLogos_log
SchrijfmechanismeSynchroon naar schijfAsynchrone buffering in kernel
Tijd voor 10.000 aanroepen~2,8 s~0,3 s
Impact op FPSVerlies 5–8 frames0 frames
KritikaliteitsniveausNee5 niveaus
PrivacyAlle gegevens openAutomatisch maskeren
FilterenNiet ondersteundOp subsystem / category / level

Codevoorbeelden met os_log in Swift

os_log heeft twee API's: klassiek C os_log_create en de moderne Swift-wrapper Logger, geïntroduceerd in iOS 14. Swift Logger gebruikt het ResultBuilder-systeem voor opmaak — argumenten worden geïnterpoleerd via stringliteralen met expliciete privacymarkering.

swift
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 — commandoregelhulpprogramma voor het exporteren van verzamelde logs van het apparaat. Wordt gestart vanuit Terminal na het aansluiten van het apparaat op de Mac via USB.

swift
// Logs verzamelen in .logarchive
// In terminal: log collect --device --output ./app_logs.logarchive
// Subsystem-logs bekijken: log show --subsystem com.example.app

// Loggen met dynamische waarden
logger.log("User \(userId) opened screen \(screenName)")

Bij gebruik van Logger is het belangrijk te onthouden dat argumenten worden geïnterpoleerd via String Interpolation, niet via opmaakstrings zoals in de C-versie van os_log. Dit is veiliger, maar vereist expliciete vermelding van privacy voor elk argument als het standaardgedrag de ontwikkelaar niet bevalt.

Veelgestelde vragen

Wat is het verschil tussen os_log en NSLog?

os_log buffert berichten asynchroon in de kernel en blokkeert de hoofdthread niet, terwijl NSLog synchroon naar schijf schrijft. os_log is 10 keer sneller, biedt 5 kritikaliteitsniveaus en maskeert automatisch privégegevens — NSLog heeft geen van deze eigenschappen.

Welk os_log-niveau moet ik gebruiken voor debuggen?

Gebruik .debug voor tijdelijke debugberichten — ze worden uitgeschakeld in de productiebuild en hebben geen invloed op de prestaties van gebruikers. Gebruik .default of .info voor belangrijke berichten die altijd bewaard moeten blijven.

Hoe schakel ik Info- en Debug-logs in op het apparaat van een gebruiker?

Via Configure Profile in Xcode: Devices → selecteer het apparaat → Open Console → Actions → Configure Profile. Stel het verzamelingsniveau voor het gewenste subsystem in op Include. Dit maakt een profiel aan dat actief is tot de eerste herstart van het apparaat.

Kan os_log worden gebruikt in SwiftUI-apps?

Ja, os_log werkt in alle SwiftUI-apps zonder extra configuratie. Maak een statische Logger aan in het model of in een View-extensie en gebruik deze in onChange, task en gesture-handlers voor het volgen van de levenscyclus van schermen.

Waarom toont os_log <private> in plaats van waarden?

os_log maskeert standaard strings en objecten als private. Om de waarde te zien, geeft u expliciet privacy: .public op in de interpolatie. Zonder deze markering worden waarden vervangen door een masker in productiebuilds, maar in debug via Xcode worden ze normaal weergegeven.

Samenvatting

  • os_log — unified logging API van Apple die werkt via een circulaire buffer in de XNU-kernel met asynchroon schrijven naar schijf
  • Prestaties — os_log is 10 keer sneller dan NSLog, blokkeert de hoofdthread niet en beïnvloedt de animatieframesnelheid niet bij elk logvolume
  • Niveaus — vijf niveaus van Debug tot Fault: Info en Debug worden uitgeschakeld in productie, Error en Fault worden altijd opgeslagen
  • Subsystem en Category — hiërarchie voor het groeperen van logs per app-module, filteren in Console.app zonder elk bericht te lezen
  • Privacy — automatisch maskeren van strings en objecten in productielogs, bescherming van persoonsgegevens zonder extra code
  • Hulpmiddelen — Console.app voor real-time weergave en log collect voor het exporteren van een archief van het apparaat
  • Migratie — vervanging van NSLog door os_log vermindert het risico op gegevenslekkage en verbetert de prestaties, vooral in zwaarbelaste netwerkmodules en achtergrondprocessen

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook