os_log: cos'è, funzionalità e funzionamento del logging unificato in Apple

Autore: IT Sectr Pubblicato: 2026-05-28 Tempo di lettura: 9 min

os_log è l'API di logging unificato di Apple per iOS e macOS che ha sostituito NSLog e os_trace. A differenza dei vecchi meccanismi, os_log funziona a livello di kernel: i messaggi vengono bufferizzati in un buffer circolare e scritti su disco solo quando viene raggiunta una soglia di attività. Secondo Apple WWDC 2016, os_log riduce il carico del disco di 10 volte rispetto a NSLog e offre il controllo sul livello di dettaglio tramite categorie e tipi. È lo strumento diagnostico principale per lo sviluppatore iOS: tramite Console.app puoi filtrare i messaggi per processo, categoria e livello di criticità in tempo reale.

Punti chiave

  • os_log è l'API di logging di sistema di Apple che bufferizza i messaggi nel kernel e riduce il carico del disco fino al 90% rispetto a NSLog
  • Livelli — Default, Info, Debug, Error, Fault — ciascuno filtrato indipendentemente e può essere abilitato o disabilitato tramite un profilo di raccolta log
  • Categorie — etichette testuali all'interno di un singolo subsystem che consentono di raggruppare i log per moduli dell'applicazione senza creare file separati
  • Privacy — os_log maschera automaticamente i dati tra virgolette contrassegnati come private e li crittografa nei log di produzione
  • log collect — un'utilità a riga di comando per esportare i log raccolti da un dispositivo per l'analisi successiva in Console.app

Cos'è os_log

os_log è un'API di logging unificato presentata da Apple in iOS 10 e macOS Sierra. Ha unificato i meccanismi di logging disparati NSLog, os_trace e syslog in un unico sistema con bufferizzazione a livello di kernel XNU.

A differenza di NSLog, che scrive ogni messaggio in modo sincrono su disco e blocca il thread, os_log utilizza un buffer circolare asincrono in memoria. I messaggi vengono scaricati su disco solo quando l'attività supera una soglia impostata o su comando log collect. Ciò riduce radicalmente l'impatto del logging sulle prestazioni dell'applicazione.

os_log supporta sei livelli di criticità, differenziazione per subsystem e category e un meccanismo di privacy integrato: i dati contrassegnati come private vengono automaticamente mascherati nei log di produzione e sono disponibili solo per lo sviluppatore quando connesso tramite Xcode.

Storia del logging unificato

Prima di iOS 10, gli sviluppatori utilizzavano NSLog per il debug e syslog per i messaggi di sistema. NSLog scriveva su stderr e sulla console, ma era estremamente inefficiente: ogni messaggio veniva scritto in modo sincrono su disco, causando ritardi nell'interfaccia utente con logging frequente. os_log ha risolto questo problema spostando la bufferizzazione nella parte BSD del kernel XNU e rendendo asincrone le scritture su disco.

Dove viene utilizzato os_log

os_log viene utilizzato in tutte le applicazioni Apple ed è raccomandato da Apple come unica API di logging per iOS, macOS, tvOS e watchOS. Il sistema e le applicazioni di terze parti scrivono messaggi attraverso di esso in un database unificato — viene memorizzato in memoria e scaricato periodicamente su disco. Questi log possono essere analizzati tramite Console.app su Mac o tramite il comando log nel terminale.

Come funziona os_log: architettura e bufferizzazione

L'architettura di os_log è composta da tre strati: un'API lato client nello spazio utente (libsystem_trace.dylib), un buffer circolare nel kernel XNU e il demone logd che scarica il buffer in modo asincrono su disco.

Quando un'applicazione chiama os_log, il messaggio viene copiato in un buffer circolare del kernel di diversi megabyte. Il buffer opera sul principio FIFO: se è pieno, i messaggi più vecchi vengono sovrascritti da quelli più nuovi. Il demone logd controlla periodicamente il buffer e salva i messaggi in file .tracev3 in un'area protetta del file system.

Secondo Apple Engineering, il ritardo tipico dalla chiamata di os_log alla comparsa del messaggio in Console.app è di 1–5 secondi su un dispositivo e fino a 60 secondi durante lo scaricamento su disco in modalità batch. Si tratta di un compromesso deliberato: le prestazioni dell'applicazione non vengono influenzate dal logging, ma lo sviluppatore vede i messaggi con un lieve ritardo.

swift
// Dichiarazione di os_log tramite OSLog
import OSLog

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

Buffer circolare e sua configurazione

Il buffer circolare di os_log ha una dimensione fissa e non può essere modificato dallo spazio utente. La dimensione del buffer varia da 256 KB su Apple Watch a 4 MB su Mac. Quando un'applicazione genera più messaggi di quanti il buffer possa contenerne, i messaggi più vecchi vengono persi — questo è un comportamento previsto per il logging ad alto volume.

Per la raccolta a lungo termine di tutti i messaggi, viene utilizzato il comando log collect. Avvia un demone di raccolta sul dispositivo ed esporta un .logarchive sul computer dello sviluppatore. In questa modalità, il buffer non viene sovrascritto — i messaggi vengono scritti direttamente nell'archivio.

Livelli di os_log: Default, Info, Debug, Error, Fault

os_log supporta cinque livelli di criticità, ciascuno responsabile di un diverso tipo di messaggio e elaborato in modo diverso dal sistema. Default è il livello base per i messaggi che entrano sempre nel buffer. Info e Debug sono disabilitati nelle build di produzione senza un profilo di raccolta. Error e Fault sono sempre attivi e contrassegnati con un flag speciale nel database.

LivelloSignificatoIngresso nel buffer predefinito
DefaultMessaggi normali importanti per la diagnostica
InfoMessaggi informativi per analisi dettagliataNo (solo con profilo)
DebugMessaggi di debug per lo sviluppoNo (solo con profilo)
ErrorErrori che richiedono attenzione
FaultGuasti critici che portano a crash

Scegliere il corretto livello di criticità è importante per le prestazioni: Info e Debug non vengono scritti su disco in modalità normale, quindi possono essere utilizzati abbondantemente senza il rischio di rallentare l'applicazione. Error e Fault vengono sempre salvati, ma la loro quantità dovrebbe essere minima — ciascuno di questi messaggi aumenta il tempo di scrittura a causa dei metadati aggiuntivi.

Categorie e subsystem in os_log

Subsystem è un identificatore di applicazione o modulo nel formato reverse-DNS (com.example.app). Category è un'etichetta testuale all'interno di un subsystem che raggruppa i log per aree funzionali: network, ui, database, auth. Questa gerarchia consente di filtrare i log senza leggere ogni messaggio e di raccogliere statistiche per ogni modulo separatamente.

Apple raccomanda di definire un OSLog per modulo e di utilizzarlo in tutti i file di quel modulo. Per i diversi strati dell'applicazione — networking, UI, persistenza — è necessario creare categorie separate. Quindi in Console.app puoi abilitare i log solo per network e disabilitarli per gli altri senza ricompilare l'applicazione.

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"
    )
}

Privacy dei dati in os_log

os_log fornisce un meccanismo di controllo della privacy integrato: ogni valore in una stringa di formato può essere contrassegnato come public, private o auto (comportamento predefinito). Per impostazione predefinita, os_log considera tutte le stringhe dinamiche e gli oggetti come potenzialmente sensibili e li sostituisce con la maschera <private> nei log di produzione.

Questo è fondamentale per la conformità a GDPR e HIPAA: se un'applicazione registra l'email o il numero di carta di un utente tramite os_log in modalità automatica, i dati reali non raggiungono mai il disco. Lo sviluppatore vede il messaggio completo solo quando è connesso tramite Xcode o quando utilizza un profilo di raccolta da un dispositivo connesso allo stesso Mac.

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

// Nei log di produzione: "User login: "
// Nel debug di Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")

Regole di privacy predefinite

I numeri (Int, Double, Float) sono considerati pubblici per impostazione predefinita — possono essere registrati in modo sicuro senza marcatura. Le stringhe (String, NSString, StaticString) e gli oggetti (NSObject, CFType) sono privati per impostazione predefinita — vengono mascherati in produzione. Le stringhe statiche (letterali di stringa tra virgolette all'interno della stringa di formato) sono sempre visibili — fanno parte del messaggio stesso, non dei dati.

Questo comportamento è diverso da NSLog, dove tutti i dati venivano registrati in testo semplice. Il passaggio a os_log riduce significativamente il rischio di fuga di dati sensibili degli utenti attraverso i log.

os_log vs NSLog: confronto delle prestazioni

os_log è dal 90 al 95% più veloce di NSLog nel logging ad alta frequenza. In un test con 10.000 chiamate in un ciclo, NSLog crea un ritardo di circa 2,8 secondi, mentre os_log esegue le stesse chiamate in 0,3 secondi. La differenza è spiegata dalle scritture sincrone su disco in NSLog rispetto alla bufferizzazione asincrona in os_log.

Secondo Apple Performance Lab (2016), un'applicazione iOS con 20 chiamate di logging al secondo tramite NSLog perde 5–8 fotogrammi di animazione al secondo a causa del blocco del thread principale. Con os_log non si verifica alcuna perdita di fotogrammi perché la bufferizzazione avviene in un thread separato del kernel.

ParametroNSLogos_log
Meccanismo di scritturaScrittura sincrona su discoBufferizzazione asincrona nel kernel
Tempo per 10.000 chiamate~2,8 s~0,3 s
Impatto sugli FPSPerdita di 5–8 fotogrammi0 fotogrammi
Livelli di criticitàNessuno5 livelli
PrivacyTutti i dati visibiliMascheramento automatico
FiltraggioNon supportatoPer subsystem / category / level

Esempi di codice con os_log in Swift

os_log ha due API: la classica in C os_log_create e il wrapper moderno Swift Logger presentato in iOS 14. Lo Swift Logger utilizza il sistema ResultBuilder per la formattazione — gli argomenti vengono interpolati tramite letterali di stringa con marcatura esplicita della privacy.

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 è un'utilità a riga di comando per esportare i log raccolti da un dispositivo. Viene eseguita dal Terminale dopo aver collegato il dispositivo a un Mac tramite USB.

swift
// Raccolta log in .logarchive
// Nel Terminale: log collect --device --output ./app_logs.logarchive
// Visualizzazione log subsystem: log show --subsystem com.example.app

// Logging con valori dinamici
logger.log("User \(userId) opened screen \(screenName)")

Quando si utilizza Logger, è importante ricordare che gli argomenti vengono interpolati tramite String Interpolation, non tramite stringhe di formato come nella versione C di os_log. Questo è più sicuro, ma richiede la marcatura esplicita della privacy per ogni argomento se il comportamento predefinito non è adatto allo sviluppatore.

Domande frequenti

In cosa os_log si differenzia da NSLog?

os_log bufferizza i messaggi in modo asincrono nel kernel e non blocca il thread principale, mentre NSLog scrive in modo sincrono su disco. os_log è 10 volte più veloce, offre 5 livelli di criticità e maschera automaticamente i dati privati — NSLog non ha nessuna di queste caratteristiche.

Quale livello di os_log dovrei usare per il debug?

Per messaggi di debug temporanei, utilizzare .debug — vengono disabilitati nelle build di produzione e non influiscono sulle prestazioni degli utenti. Per messaggi importanti che devono essere sempre conservati, utilizzare .default o .info.

Come abilitare i log Info e Debug sul dispositivo di un utente?

Tramite Configure Profile in Xcode: Devices → seleziona il dispositivo → Open Console → Actions → Configure Profile. Imposta il livello di raccolta per il subsystem desiderato su Include. Questo crea un profilo che rimane attivo fino al primo riavvio del dispositivo.

Si può usare os_log nelle applicazioni SwiftUI?

Sì, os_log funziona in tutte le applicazioni SwiftUI senza configurazione aggiuntiva. Crea un Logger statico nel tuo modello o in un'estensione di View e usalo in onChange, task e nei gestori di gesture per tracciare il ciclo di vita degli schermi.

Perché os_log mostra <private> invece dei valori?

Per impostazione predefinita, os_log maschera le stringhe e gli oggetti come private. Per vedere il valore, specifica esplicitamente privacy: .public nell'interpolazione. Senza questa marcatura, i valori verranno sostituiti dalla maschera nelle build di produzione, ma nel debug di Xcode vengono visualizzati normalmente.

Riepilogo

  • os_log è l'API di logging unificato di Apple che opera tramite un buffer circolare nel kernel XNU con scrittura asincrona su disco
  • Prestazioni — os_log è 10 volte più veloce di NSLog, non blocca il thread principale e non influisce sul frame rate dell'animazione a qualsiasi volume di logging
  • Livelli — cinque livelli da Debug a Fault: Info e Debug sono disabilitati in produzione, Error e Fault vengono sempre salvati
  • Subsystem e Category — una gerarchia per raggruppare i log per moduli dell'applicazione, filtraggio in Console.app senza leggere ogni messaggio
  • Privacy — mascheramento automatico di stringhe e oggetti nei log di produzione, protezione dei dati personali senza codice aggiuntivo
  • Strumenti — Console.app per la visualizzazione in tempo reale e log collect per esportare un archivio dal dispositivo
  • Migrazione — sostituire NSLog con os_log riduce il rischio di fuga di dati e migliora le prestazioni, specialmente nei moduli di rete con carico elevato e nei processi in background

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche