os_log — är unified logging API från Apple för iOS och macOS, som har ersatt NSLog och os_trace. Till skillnad från gamla mekanismer fungerar os_log på kärnnivå: meddelanden buffras i en cirkulär buffert och skrivs till disk endast när aktivitetströskeln nås. Enligt uppgifter från Apple WWDC 2016 minskar os_log diskbelastningen 10 gånger jämfört med NSLog och ger kontroll över detaljnivån via kategorier och typer. Det är det främsta diagnostikverktyget för iOS-utvecklare: via Console.app kan meddelanden filtreras efter process, kategori och kritiskhetsnivå i realtid.
Huvudpunkter
os_log — är unified logging API som introducerades av Apple i iOS 10 och macOS Sierra. Det förenade de spridda loggningsmekanismerna NSLog, os_trace och syslog till ett enda system med buffring på XNU-kärnnivå.
Till skillnad från NSLog, som synkront skriver varje meddelande till disk och blockerar tråden, använder os_log en asynkron cirkulär buffert i minnet. Meddelanden skrivs till disk endast när aktiviteten överstiger en viss tröskel eller på kommando log collect. Detta minskar dramatiskt loggningens påverkan på appens prestanda.
os_log stöder sex kritiskhetsnivåer, differentiering efter subsystem och category, samt en inbyggd sekretessmekanism: data markerade som private maskeras automatiskt i produktionsloggar och är endast tillgängliga för utvecklaren när Xcode är anslutet.
Före iOS 10 använde utvecklare NSLog för felsökning och syslog för systemmeddelanden. NSLog skrev till stderr och konsolen, men var extremt ineffektivt: varje meddelande skrevs synkront till disk, vilket orsakade fördröjningar i gränssnittet vid frekvent loggning. os_log löste detta problem genom att flytta buffringen till BSD-delen av XNU-kärnan och göra skrivning till disk asynkron.
os_log används i alla Apple-appar och rekommenderas av Apple som det enda loggnings-API:et för iOS, macOS, tvOS och watchOS. Systemet och tredjepartsappar skriver meddelanden via det till en enda databas — lagrad i minnet och periodvis tömd till disk. Dessa loggar kan analyseras via Console.app på Mac eller via kommandot log i terminalen.
Arkitekturen för os_log består av tre lager: klient-API i användarutrymmet (libsystem_trace.dylib), cirkulär buffert i XNU-kärnan och logd-demonen som asynkront tömmer bufferten till disk.
När en app anropar os_log kopieras meddelandet till en cirkulär kärnbuffert på flera megabyte. Bufferten fungerar enligt FIFO-principen: om den är full skrivs gamla meddelanden över av nya. logd-demonen kontrollerar periodiskt bufferten och sparar meddelanden i .tracev3-filer i ett skyddat område av filsystemet.
Enligt Apple Engineering är den typiska fördröjningen från ett os_log-anrop tills meddelandet visas i Console.app 1–5 sekunder på enheten och upp till 60 sekunder vid batchutskrift till disk. Detta är en medveten avvägning: appens prestanda påverkas inte av loggningen, men utvecklaren ser meddelanden med en liten fördröjning.
// Deklaration av os_log via OSLog
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
Den cirkulära bufferten för os_log har en fast volym och kan inte ändras från användarutrymmet. Buffertstorleken varierar från 256 KB på Apple Watch till 4 MB på Mac. När en app genererar fler meddelanden än bufferten rymmer går gamla meddelanden förlorade — detta är förväntat beteende för högvolymloggning.
För långsiktig insamling av alla meddelanden används kommandot log collect, som startar insamlingsdemonen på enheten och exporterar .logarchive till utvecklarens dator. I detta läge skrivs bufferten inte över — meddelanden skrivs direkt till arkivet.
os_log stöder fem kritiskhetsnivåer, var och en ansvarig för en separat typ av meddelanden och bearbetas olika av systemet. Nivå Default — grundläggande för meddelanden som alltid hamnar i bufferten. Info och Debug inaktiveras i produktionsbyggen utan insamlingsprofil. Error och Fault är alltid aktiva och markerade med en speciell flagga i databasen.
| Nivå | Betydelse | Standardinträde i buffert |
|---|---|---|
| Default | Vanliga meddelanden viktiga för diagnostik | Ja |
| Info | Informationsmeddelanden för detaljerad analys | Nej (endast med profil) |
| Debug | Felsökningsmeddelanden för utveckling | Nej (endast med profil) |
| Error | Fel som kräver uppmärksamhet | Ja |
| Fault | Kritiska fel som leder till krasch | Ja |
Att välja rätt kritiskhetsnivå är viktigt för prestandan: Info och Debug skrivs inte till disk i normalt läge, så de kan användas rikligt utan risk att sakta ner appen. Error och Fault sparas alltid, men deras antal bör vara minimalt — varje sådant meddelande ökar skrivtiden på grund av ytterligare metadata.
Subsystem — är identifieraren för en app eller modul i reverse-DNS-format (com.example.app). Category — en textetikett inom subsystem som grupperar loggar efter funktionella områden: network, ui, database, auth. Denna hierarki gör det möjligt att filtrera loggar utan att läsa varje meddelande och samla statistik för varje modul separat.
Apple rekommenderar att definiera en OSLog per modul och använda den i alla filer för den modulen. För olika lager i appen — networking, UI, persistence — ska separata kategorier skapas. Då kan i Console.app loggar endast aktiveras för network och inaktiveras för de andra, utan att kompilera om appen.
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 tillhandahåller en inbyggd mekanism för sekretesskontroll: varje värde i formateringssträngen kan markeras som public, private eller auto (standardbeteende). Som standard betraktar os_log alla dynamiska strängar och objekt som potentiellt konfidentiella och ersätter dem med masken <private> i produktionsloggar.
Detta är kritiskt för efterlevnad av GDPR- och HIPAA-krav: om appen loggar användarens e-post eller kortnummer via os_log i automatiskt läge, når de verkliga uppgifterna aldrig disken. Utvecklaren ser det fullständiga meddelandet endast vid anslutning via Xcode eller vid användning av en insamlingsprofil från en enhet ansluten till samma Mac.
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")
// I produktionsloggar: "User login: <private>"
// Vid felsökning via Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")
Siffror (Int, Double, Float) betraktas som standard som public — de kan loggas säkert utan markering. Strängar (String, NSString, StaticString) och objekt (NSObject, CFType) är som standard private — de maskeras i produktion. Statiska strängar (strängliteral inom citationstecken i formateringssträngen) är alltid synliga — de är en del av själva meddelandet, inte data.
Detta beteende skiljer sig från NSLog, där alla data loggades i öppen form. Övergången till os_log minskar avsevärt risken för läckage av känsliga användardata via loggar.
os_log är 90–95% snabbare än NSLog vid högfrekvent loggning. I ett test med 10 000 anrop i en loop skapar NSLog en fördröjning på cirka 2,8 sekunder, medan os_log utför samma anrop på 0,3 sekunder. Skillnaden förklaras av synkron skrivning till disk i NSLog jämfört med asynkron buffring i os_log.
Enligt Apple Performance Lab (2016) förlorar en iOS-app med 20 loggningsanrop per sekund via NSLog 5–8 bildrutor per sekund på grund av blockering av huvudtråden. Med os_log sker ingen bildruteförlust eftersom buffringen sker i en separat kärntråd.
| Parameter | NSLog | os_log |
|---|---|---|
| Skrivmekanism | Synkron skrivning till disk | Asynkron buffring i kärnan |
| Tid för 10 000 anrop | ~2,8 s | ~0,3 s |
| Påverkan på FPS | Förlust 5–8 bildrutor | 0 bildrutor |
| Kritiskhetsnivåer | Inga | 5 nivåer |
| Sekretess | Alla data öppna | Automatisk maskering |
| Filtrering | Stöds inte | Efter subsystem / category / level |
os_log har två API:er: klassisk C os_log_create och modern Swift-omslag Logger, introducerad i iOS 14. Swift Logger använder ResultBuilder-systemet för formatering — argument interpoleras via strängliteral med explicit sekretessmarkering.
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 — kommandoradsverktyg för att exportera insamlade loggar från enheten. Startas från Terminal efter att ha anslutit enheten till Mac via USB.
// Insamling av loggar i .logarchive
// I terminalen: log collect --device --output ./app_logs.logarchive
// Visa subsystem-loggar: log show --subsystem com.example.app
// Loggning med dynamiska värden
logger.log("User \(userId) opened screen \(screenName)")
Vid användning av Logger är det viktigt att komma ihåg att argument interpoleras via String Interpolation, inte via formatsträngar som i C-versionen av os_log. Detta är säkrare, men kräver explicit angivelse av privacy för varje argument om standardbeteendet inte passar utvecklaren.
Vanliga frågor
os_log buffrar meddelanden asynkront i kärnan och blockerar inte huvudtråden, medan NSLog skriver synkront till disk. os_log är 10 gånger snabbare, ger 5 kritiskhetsnivåer och maskerar automatiskt privat data — NSLog har inga av dessa egenskaper.
Använd .debug för tillfälliga felsökningsmeddelanden — de inaktiveras i produktionsbyggen och påverkar inte användarnas prestanda. För viktiga meddelanden som alltid ska bevaras, använd .default eller .info.
Via Configure Profile i Xcode: Devices → välj enhet → Open Console → Actions → Configure Profile. Ställ in insamlingsnivån för önskat subsystem på Include. Detta skapar en profil som är aktiv till enhetens första omstart.
Ja, os_log fungerar i alla SwiftUI-appar utan extra inställningar. Skapa en statisk Logger i modellen eller i en View-förlängning och använd den i onChange, task och gesthanterare för att spåra skärmars livscykel.
os_log maskerar som standard strängar och objekt som private. För att se värdet, ange explicit privacy: .public i interpoleringen. Utan denna markering ersätts värden med en mask i produktionsbyggen, men vid felsökning via Xcode visas de normalt.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också