diff --git a/Model/Brand.swift b/Model/Brand.swift index c2beba89..8387780d 100644 --- a/Model/Brand.swift +++ b/Model/Brand.swift @@ -106,7 +106,7 @@ enum Config: String { static func value(for key: Config) -> T? where T: LosslessStringConvertible { guard let object = Bundle.main.object(forInfoDictionaryKey: key.rawValue) else { - os_log("Missing key from bundle: %@", log: Log.Branding, type: .error, key.rawValue) + Log.Branding.info("Missing key from bundle: \(key.rawValue, privacy: .public)") return nil } switch object { @@ -116,7 +116,7 @@ enum Config: String { guard let value = T(string) else { fallthrough } return value default: - os_log("Invalid value type found for key: %@", log: Log.Branding, type: .error, key.rawValue) + Log.Branding.error("Invalid value type found for key: \(key.rawValue, privacy: .public)") return nil } } diff --git a/Model/Downloads/DownloadService.swift b/Model/Downloads/DownloadService.swift index 8c647265..70e4d13d 100644 --- a/Model/Downloads/DownloadService.swift +++ b/Model/Downloads/DownloadService.swift @@ -146,12 +146,8 @@ final class DownloadService: NSObject, URLSessionDelegate, URLSessionTaskDelegat context.delete(downloadTask) try context.save() } catch { - os_log( - "Error deleting download task. Error: %s", - log: Log.DownloadService, - type: .error, - error.localizedDescription - ) + Log.DownloadService.error( + "Error deleting download task for zimFile: \(zimFileID.uuidString, privacy: .public). Error: \(error.localizedDescription, privacy: .public)") } } } @@ -192,20 +188,12 @@ final class DownloadService: NSObject, URLSessionDelegate, URLSessionTaskDelegat // and the status code is in the 200 < 300 range guard let error = error as NSError? else { if (200..<300).contains(httpResponse.statusCode) { - os_log( - "Download finished successfully. File ID: %s.", - log: Log.DownloadService, - type: .info, - zimFileID.uuidString + Log.DownloadService.info( + "Download finished successfully. File ID: \(zimFileID.uuidString, privacy: .public)", ) } else { - os_log( - "Download was unsuccessful. File ID: %s. status code: %i", - log: Log.DownloadService, - type: .info, - zimFileID.uuidString, - httpResponse.statusCode - ) + Log.DownloadService.info( + "Download was unsuccessful. File ID: \(zimFileID.uuidString, privacy: .public). status code: \(httpResponse.statusCode, privacy: .public)") self.deleteDownloadTask(zimFileID: zimFileID) } return @@ -230,13 +218,7 @@ final class DownloadService: NSObject, URLSessionDelegate, URLSessionTaskDelegat try? context.save() } } - os_log( - "Download finished for File ID: %s. with: %s", - log: Log.DownloadService, - type: .error, - zimFileID.uuidString, - error.localizedDescription - ) + Log.DownloadService.error("Download finished for File ID: \(zimFileID.uuidString, privacy: .public). with: \(error.localizedDescription, privacy: .public)") } // MARK: - URLSessionDownloadDelegate @@ -261,6 +243,7 @@ final class DownloadService: NSObject, URLSessionDelegate, URLSessionTaskDelegat guard let httpResponse = downloadTask.response as? HTTPURLResponse else { return } guard (200..<300).contains(httpResponse.statusCode) else { + Log.DownloadService.error("Download didFinish failed with http status for: \(downloadTask.taskIdentifier.description, privacy: .public), httpStatusCode: \(httpResponse.statusCode, privacy: .public)") Task { @MainActor in NotificationCenter.default.post( name: .alert, @@ -279,17 +262,27 @@ final class DownloadService: NSObject, URLSessionDelegate, URLSessionTaskDelegat #endif // move file - guard let directory = FileManager.default.urls(for: searchPath, in: .userDomainMask).first, - let zimFileID = UUID(uuidString: downloadTask.taskDescription ?? "") else { return } + guard let directory = FileManager.default.urls(for: searchPath, in: .userDomainMask).first else { + Log.DownloadService.fault("Cannot find download directory!! downloadTask: \(downloadTask.taskDescription ?? "", privacy: .public)") + return + } + guard let zimFileID = UUID(uuidString: downloadTask.taskDescription ?? "") else { + Log.DownloadService.fault("Cannot convert downloadTask to zimFileID: \(downloadTask.taskDescription ?? "", privacy: .public)") + return + } let fileName = downloadTask.response?.suggestedFilename ?? downloadTask.originalRequest?.url?.lastPathComponent ?? zimFileID.uuidString + ".zim" let destination = directory.appendingPathComponent(fileName) + Log.DownloadService.info("Start moving downloaded zimFile: \(fileName, privacy: .public), zimFileID: \(zimFileID.uuidString, privacy: .public)") try? FileManager.default.moveItem(at: location, to: destination) - + Log.DownloadService.info("Completed moving downloaded zimFile: \(zimFileID.uuidString, privacy: .public)") + // open the file Task { @ZimActor in + Log.DownloadService.info("start opening downloaded zimFile: \(zimFileID.uuidString, privacy: .public)") await LibraryOperations.open(url: destination) + Log.DownloadService.info("opened downloaded zimFile: \(zimFileID.uuidString, privacy: .public)") // schedule notification scheduleDownloadCompleteNotification(zimFileID: zimFileID) deleteDownloadTask(zimFileID: zimFileID) diff --git a/Model/Payment.swift b/Model/Payment.swift index 8d106373..207c56e2 100644 --- a/Model/Payment.swift +++ b/Model/Payment.swift @@ -183,9 +183,9 @@ struct Payment { phase: PayWithApplePayButtonPaymentAuthorizationPhase) { switch phase { case .willAuthorize: - os_log("onPaymentAuthPhase: .willAuthorize") + Log.Payment.info("onPaymentAuthPhase: .willAuthorize") case .didAuthorize(let payment, let resultHandler): - os_log("onPaymentAuthPhase: .didAuthorize") + Log.Payment.info("onPaymentAuthPhase: .didAuthorize") // call our server to get payment / setup intent and return the client.secret Task { @MainActor [resultHandler] in let paymentServer = StripeKiwix(endPoint: Self.kiwixPaymentServer, @@ -218,13 +218,13 @@ struct Payment { Self.finalResult = nil } resultHandler(result) - os_log("onPaymentAuthPhase: .didAuthorize: \(result.status == .success)") + Log.Payment.info("onPaymentAuthPhase: .didAuthorize: \(result.status == .success, privacy: .public)") } case .didFinish: - os_log("onPaymentAuthPhase: .didFinish") + Log.Payment.info("onPaymentAuthPhase: .didFinish") completeSubject.send(()) @unknown default: - os_log("onPaymentAuthPhase: @unknown default") + Log.Payment.error("onPaymentAuthPhase: @unknown default") } } diff --git a/Model/StripeKiwix.swift b/Model/StripeKiwix.swift index 565246fc..3c370ea4 100644 --- a/Model/StripeKiwix.swift +++ b/Model/StripeKiwix.swift @@ -76,12 +76,12 @@ struct StripeKiwix { throw StripeError.serverError } guard let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { - os_log("Merchant session not established: unable to decode server response", type: .debug) + Log.Payment.error("Merchant session not established: unable to decode server response") return nil } return PKPaymentMerchantSession(dictionary: dictionary) } catch let serverError { - os_log("Merchant session not established: %@", type: .debug, serverError.localizedDescription) + Log.Payment.error("Merchant session not established: \(serverError.localizedDescription, privacy: .public)") return nil } } diff --git a/Model/Utilities/Log.swift b/Model/Utilities/Log.swift index 42130830..fa342d57 100644 --- a/Model/Utilities/Log.swift +++ b/Model/Utilities/Log.swift @@ -18,11 +18,12 @@ import os private let subsystem = "org.kiwix.kiwix" struct Log { - static let DownloadService = OSLog(subsystem: subsystem, category: "DownloadService") - static let FaviconDownloadService = OSLog(subsystem: subsystem, category: "FaviconDownloadService") - static let LibraryService = OSLog(subsystem: subsystem, category: "LibraryService") - static let LibraryOperations = OSLog(subsystem: subsystem, category: "LibraryOperations") - static let OPDS = OSLog(subsystem: subsystem, category: "OPDS") - static let URLSchemeHandler = OSLog(subsystem: subsystem, category: "URLSchemeHandler") - static let Branding = OSLog(subsystem: subsystem, category: "Branding") + static let DownloadService = Logger(subsystem: subsystem, category: "DownloadService") + static let FaviconDownloadService = Logger(subsystem: subsystem, category: "FaviconDownloadService") + static let LibraryOperations = Logger(subsystem: subsystem, category: "LibraryOperations") + static let QRCode = Logger(subsystem: subsystem, category: "QRCode") + static let OPDS = Logger(subsystem: subsystem, category: "OPDS") + static let URLSchemeHandler = Logger(subsystem: subsystem, category: "URLSchemeHandler") + static let Branding = Logger(subsystem: subsystem, category: "Branding") + static let Payment = Logger(subsystem: subsystem, category: "Payment") } diff --git a/Model/Utilities/QRCode.swift b/Model/Utilities/QRCode.swift index ee231858..d1f2142e 100644 --- a/Model/Utilities/QRCode.swift +++ b/Model/Utilities/QRCode.swift @@ -22,7 +22,7 @@ struct QRCode { static func image(from text: String) async -> CGImage? { let data = Data(text.utf8) guard let filter = CIFilter(name: "CIQRCodeGenerator") else { - os_log("QRCode cannot create CIFilter", log: Log.LibraryService, type: .error) + Log.QRCode.error("QRCode cannot create CIFilter") return nil } filter.setValue(data, forKey: "inputMessage") @@ -31,7 +31,7 @@ struct QRCode { let transform = CGAffineTransform(scaleX: 20, y: 20) guard let outputImage = filter.outputImage?.transformed(by: transform), let image = context.createCGImage(outputImage, from: outputImage.extent.insetBy(dx: 20, dy: 20)) else { - os_log("QRCode cannot create image", log: Log.LibraryService, type: .error) + Log.QRCode.error("QRCode cannot create image") return nil } return image diff --git a/SwiftUI/Model/LibraryOperations.swift b/SwiftUI/Model/LibraryOperations.swift index 19aa9c45..a0d55d64 100644 --- a/SwiftUI/Model/LibraryOperations.swift +++ b/SwiftUI/Model/LibraryOperations.swift @@ -91,7 +91,7 @@ struct LibraryOperations { try? context.save() } } - os_log("Reopened %d out of %d zim files", log: Log.LibraryOperations, type: .info, successCount, zimFiles.count) + Log.LibraryOperations.info("Reopened \(successCount, privacy: .public) out of \(zimFiles.count, privacy: .public) zim files") } /// Scan a directory and open available zim files inside it @@ -102,7 +102,7 @@ struct LibraryOperations { includingPropertiesForKeys: nil, options: [.skipsHiddenFiles, .skipsPackageDescendants, .skipsSubdirectoryDescendants] ).filter({ $0.pathExtension == "zim"}) else { return } - os_log("Discovered %d probable zim files.", log: Log.LibraryOperations, type: .info, fileURLs.count) + Log.LibraryOperations.info("Discovered \(fileURLs.count, privacy: .public) probable zim files.") Task { for fileURL in fileURLs { await LibraryOperations.open(url: fileURL) @@ -207,13 +207,10 @@ struct LibraryOperations { var url = url try url.setResourceValues(resourceValues) } - os_log( - "Applying zim file backup setting (%s) on %u zim file(s).", - log: Log.LibraryOperations, - type: .info, - backupDocumentDirectory ? "backing up" : "not backing up", - urls.count - ) - } catch {} + let status = backupDocumentDirectory ? "backing up" : "not backing up" + Log.LibraryOperations.info("Applying zim file backup setting (\(status, privacy: .public)) on \(urls.count, privacy: .public) zim file(s).") + } catch { + Log.LibraryOperations.error("Unable to change iCloud backup settings, due to \(error.localizedDescription, privacy: .public)") + } } } diff --git a/ViewModel/BrowserViewModel.swift b/ViewModel/BrowserViewModel.swift index 6f6cc076..e8bf7e2b 100644 --- a/ViewModel/BrowserViewModel.swift +++ b/ViewModel/BrowserViewModel.swift @@ -445,13 +445,7 @@ final class BrowserViewModel: NSObject, ObservableObject, return .cancel } else if url.isZIMURL { guard await ZimFileService.shared.getContentSize(url: url) != nil else { - os_log( - "Missing content at url: %@ => %@", - log: Log.URLSchemeHandler, - type: .error, - url.absoluteString, - url.contentPath - ) + Log.URLSchemeHandler.error("Missing content at url: \(url.absoluteString, privacy: .public) => \(url.contentPath, privacy: .public)") if navigationAction.request.mainDocumentURL == url { // only show alerts for missing main document NotificationCenter.default.post( diff --git a/ViewModel/LibraryViewModel.swift b/ViewModel/LibraryViewModel.swift index 1ac020d4..9128ba02 100644 --- a/ViewModel/LibraryViewModel.swift +++ b/ViewModel/LibraryViewModel.swift @@ -204,8 +204,10 @@ final class LibraryViewModel: ObservableObject { process.state = .complete // logging - os_log("Refresh finished -- addition: %d, deletion: %d, total: %d", - log: Log.OPDS, type: .default, insertionCount, deletionCount, parser.zimFileIDs.count) + let insertedCount = insertionCount + let deletedCount = deletionCount + let totalCount = parser.zimFileIDs.count + Log.OPDS.notice("Refresh finished -- insertion: \(insertedCount, privacy: .public), deletion: \(deletedCount, privacy: .public), total: \(totalCount, privacy: .public)") } catch { self.error = error process.state = .error @@ -291,7 +293,7 @@ final class LibraryViewModel: ObservableObject { defaults[.libraryETag] = eTag } // OK to process further - os_log("Retrieved OPDS Data, size: %llu bytes", log: Log.OPDS, type: .info, data.count) + Log.OPDS.debug("Retrieved OPDS Data, size: \(data.count, format: .byteCount, privacy: .public) bytes") return (data, responseURL) case 304: return nil // already downloaded @@ -299,7 +301,7 @@ final class LibraryViewModel: ObservableObject { throw LibraryRefreshError.retrieve(description: "HTTP Status \(response.statusCode).") } } catch { - os_log("Error retrieving OPDS Data: %s", log: Log.OPDS, type: .error, error.localizedDescription) + Log.OPDS.error("Error retrieving OPDS Data: \(error.localizedDescription, privacy: .public)") if let error = error as? LibraryRefreshError { throw error } else { @@ -349,7 +351,7 @@ final class LibraryViewModel: ObservableObject { continuation.resume() } catch { - os_log("Error saving OPDS Data: %s", log: Log.OPDS, type: .error, error.localizedDescription) + Log.OPDS.error("Error saving OPDS Data: \(error.localizedDescription, privacy: .public)") continuation.resume(throwing: LibraryRefreshError.process) } }