Swift - How to Get Logs
Here is the following code if you need to get your app’s logs as well as system logs through Applications code. The docs will tell you that the .system
scope requires administration, but the reality is that by using the local
log store, you can still get the system logs. OSLogStore on Monterey by Michael Tsai.
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
Gaining access to the local unified logging system requires permission from the system. The caller must be run by an admin account and have the com.apple.logging.local-store entitlement.
The docs here are actually outdated since you do not need that entitlement. Note that using the .system
scope won’t work with sandboxed apps.
import AppKit
import Foundation
import OSLog
import ZipArchive
let utcDateFormat: DateFormatter = {
var f = DateFormatter()
f.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
f.timeZone = TimeZone.gmt
return f
}()
let logStore: OSLogStore
do {
logStore = try OSLogStore.local()
fileName = "system.log"
} catch {
self.writeError(name: "system-logs", error: error)
logStore = try OSLogStore(scope: .currentProcessIdentifier)
fileName = "client.log"
}
let logEntries = try logStore.getEntries(
at: logStore.position(date: self.logStartTimestamp),
matching: NSPredicate(format: """
process CONTAINS[c] "APP_NAME" || subsystem CONTAINS[c] "APP_NAME"
|| process CONTAINS[c] "neagent"
|| process CONTAINS[c] "nesessionmanager"
|| subsystem CONTAINS[c] "com.apple.networkextension"
""")
)
let file = try self.openFile(name: fileName)
for entry in logEntries {
if entry.date > self.bundleTimestamp {
break
}
// TODO: Buffering?
let date = utcDateFormat.string(from: entry.date)
// TODO: Structured data.
let formatted = "\(date): \(entry.composedMessage)\n"
// This is safe because String is unicode.
let data = formatted.data(using: String.Encoding.utf8)!
try file.write(contentsOf: data)
}
try file.close()
References
Peter Steinberger; Logging in Swift; August 27, 2021