// // Logging.swift // Tusker // // Created by Shadowfacts on 10/10/22. // Copyright © 2022 Shadowfacts. All rights reserved. // import Foundation import OSLog struct Logging { private init() {} static let general = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "General") static let generalSignposter = OSSignposter(logger: general) static func getLogData() -> Data? { do { let store = try OSLogStore(scope: .currentProcessIdentifier) // do the filtering ourself, passing position/predicate into getEntries is far slower (priority inversion, I think) let entries = try store.getEntries() var data = Data() let subsystem = Bundle.main.bundleIdentifier! let format = Date.ISO8601FormatStyle(includingFractionalSeconds: true) for entry in entries { guard let entry = entry as? OSLogEntryLog, entry.subsystem == subsystem else { continue } data.append(contentsOf: entry.date.formatted(format).utf8) data.append(32) // ' ' data.append(91) // '[' data.append(contentsOf: entry.category.utf8) data.append(93) // ']' data.append(32) // ' ' data.append(contentsOf: entry.composedMessage.utf8) data.append(10) // '\n' } return data } catch { return nil } } static func writeDataForCrash() { guard let data = getLogData(), let cacheDir = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else { return } let timestamp = ISO8601DateFormatter().string(from: Date()) let url = cacheDir.appendingPathComponent("Tusker-\(timestamp).log", isDirectory: false) do { try data.write(to: url) UserDefaults.standard.set(url, forKey: "lastCrashLog") } catch { // if we can't write the data, oh well, we just won't have logs } } static func logURLForLastCrash() -> URL? { return UserDefaults.standard.url(forKey: "lastCrashLog") } }