Exporting Unified Logging System Messages with OSLog

Logs are useless, if you cannot access them. The introduction of the OSLog framework finally makes it possible to extract logs from the unified logging system. This is how.

Available since macOS 10.15 and iOS 15 is the OSLog framework. It provides programmatic access to the log database with the possibility of exporting messages. This is a valuable addition which finally makes the much longer available unified logging system in the Apple operating systems my first and favorite consideration in context of logging.

Writing logs without having the possibility to access them is pointless. This previously was the situation with the unified logging system. The only exceptions were development time when log messages could be streamed in Xcode and the Console app of macOS and sysdiagnoses on the other hand. The latter is a time consuming and rather complicated process for the simple task of obtaining app logs. It is unfit and does way too much unnecessary work which is not needed.

A team and product like ours depends on access to logs for detailed investigation. There are problems which appear first out in the wild due to the many factors influencing the app’s behaviour. In example different server versions and configurations. We used custom and third-party solutions until now. But this is supposed to change.

Today I tried out the log message access through OSLog the first time and I am convinced by the convenient access.

do {
    let store = try OSLogStore(scope: .currentProcessIdentifier)
    let start = store.position(date: Date().addingTimeInterval(-600)) // last 10 minutes
    let entries = try store.getEntries(with: [], at: start, matching: nil)

    entries.forEach {
        print("\($0.composedMessage)")
    }

    // TODO: (In example) write to file.
} catch {
    print("Something went wrong during log store export: \(error.localizedDescription)")
}

There remains one disappointment, though: on iOS we can only use OSLogStore.Scope.currentProcessIdentifier, not .system which is available on macOS 12 and newer. This way the app can only retrieve logs of itself but not its extensions which are running as separate processes. There is the idea of using XPC to make all app components query their logs on their own and some push it to the main app in a group container but that appears overly complicated for this feature.

About The Author

Peter Thomas Horn is a professional software developer at Open-Xchange specialized on the Apple platform. He previously worked a decade across the full stack of various web technologies. Originally started with Java on Windows at the age of 12 years. While staying humble in throwing around buzzwords like "VR" and "machine learning" he occasionally experiences problems and the fitting solutions considered worth sharing.