iosswiftloggingoslog

OSLogStore location


I'm trying to use the new OSLogStore object to retrieve created logs. It's very common to see the scope initialiser used like OSLogStore(scope: .currentProcessIdentifier). This works fine as long as I don't kill the app, but when I do, I cannot retrieve logs from a previous run. At least not on my simulator.

I would like to be able to persist the logs to a file and manually manage the file (if needed). So I attempted to use the OSLogStore(url:) initialiser, but that doesn't seem to work.

let url = FileManager.default.temporaryDirectory.appendingPathComponent("logs")
try OSLogStore(url: url)

// Error Domain=OSLogErrorDomain Code=1 
// "The specified URL did not refer to a valid log archive" 
// UserInfo={
//     _OSLogErrorPOSIXErrno=2, 
//     NSLocalizedDescription=The specified URL did not refer to a valid log archive,
//     _OSLogErrorInternalCode=3
// }

That made me think that maybe this throws an error, as the file doesn't exist, so I also tried to write an empty file to the location and change path extensions (to .logs, .log and .logarchive), but so far without luck.

Is there anyone who knows how I can manually tell the OSLog framework at which location to store the logs?


Solution

  • Unfortunately it is NOT possible to access system logs programmatically on iOS at all:

    1. Logs (.tracev3) are stored in /var/db/diagnostics and your sandboxed ios app can't access them.
    2. .tracev3 is proprietary file format and OSLog framework doesn't have methods to work with.

    OSLogStore(url:) allows to read .logarchive files only. For instance you can grab logs from your device and make this archive by running next command:

    sudo log collect --device-name "My iPhone Name" --last 1h --output log.logarchive
    

    And then OSLogStore can open this file and enumerate all log entries:

    let url = Bundle.main.url(forResource: "log", withExtension: "logarchive")!
    let store = try OSLogStore(url: url)
    
    try store.getEntries()
        .compactMap { $0 as? OSLogEntryLog }
        .forEach {
            print($0.date, $0.subsystem, $0.composedMessage)
        }
    

    Collecting os logs with log command line util can be made programmatically on MacOS app but it's not possible on iOS side so that OSLogStore(url:) not useful on iOS either.