Logging changes

- Adds `Logging` protocol
- Moves to Swift-style `OSLog` usage

os_log to Logger

os_log audit

Replacment of os.log with Logging
This commit is contained in:
Stuart Breckenridge
2022-08-03 15:37:12 +08:00
parent bff3c26490
commit 0dd4689bf0
52 changed files with 270 additions and 271 deletions

View File

@@ -11,8 +11,9 @@ import Account
import Secrets
import RSWeb
import SafariServices
import RSCore
class FeedbinAccountViewController: UITableViewController {
class FeedbinAccountViewController: UITableViewController, Logging {
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var cancelBarButtonItem: UIBarButtonItem!
@@ -116,7 +117,9 @@ class FeedbinAccountViewController: UITableViewController {
do {
try self.account?.removeCredentials(type: .basic)
} catch {}
} catch {
self.logger.error("Error removing credentials: \(error.localizedDescription, privacy: .public).")
}
try self.account?.storeCredentials(credentials)
self.account?.refreshAll() { result in
@@ -132,6 +135,7 @@ class FeedbinAccountViewController: UITableViewController {
self.delegate?.dismiss()
} catch {
self.showError(NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error"))
self.logger.error("Keychain error while storing credentials: \(error.localizedDescription, privacy: .public).")
}
} else {
self.showError(NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error"))

View File

@@ -10,9 +10,10 @@ import UIKit
import Account
import Secrets
import RSWeb
import RSCore
import SafariServices
class NewsBlurAccountViewController: UITableViewController {
class NewsBlurAccountViewController: UITableViewController, Logging {
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var cancelBarButtonItem: UIBarButtonItem!
@@ -118,7 +119,9 @@ class NewsBlurAccountViewController: UITableViewController {
do {
try self.account?.removeCredentials(type: .newsBlurBasic)
try self.account?.removeCredentials(type: .newsBlurSessionId)
} catch {}
} catch {
self.logger.error("Error removing credentials: \(error.localizedDescription, privacy: .public).")
}
try self.account?.storeCredentials(basicCredentials)
try self.account?.storeCredentials(sessionCredentials)
@@ -135,6 +138,7 @@ class NewsBlurAccountViewController: UITableViewController {
self.delegate?.dismiss()
} catch {
self.showError(NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error"))
self.logger.error("Keychain error while storing credentials: \(error.localizedDescription, privacy: .public).")
}
} else {
self.showError(NSLocalizedString("Invalid username/password combination.", comment: "Credentials Error"))

View File

@@ -11,8 +11,9 @@ import Account
import Secrets
import RSWeb
import SafariServices
import RSCore
class ReaderAPIAccountViewController: UITableViewController {
class ReaderAPIAccountViewController: UITableViewController, Logging {
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var cancelBarButtonItem: UIBarButtonItem!
@@ -187,6 +188,7 @@ class ReaderAPIAccountViewController: UITableViewController {
self.delegate?.dismiss()
} catch {
self.showError(NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error"))
self.logger.error("Keychain error while storing credentials: \(error.localizedDescription, privacy: .public).")
}
} else {
self.showError(NSLocalizedString("Invalid username/password combination.", comment: "Credentials Error"))

View File

@@ -11,14 +11,13 @@ import RSCore
import RSWeb
import Account
import BackgroundTasks
import os.log
import Secrets
import WidgetKit
var appDelegate: AppDelegate!
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, UnreadCountProvider {
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, UnreadCountProvider, Logging {
private var bgTaskDispatchQueue = DispatchQueue.init(label: "BGTaskScheduler")
@@ -36,8 +35,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
}
var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
var userNotificationManager: UserNotificationManager!
var faviconDownloader: FaviconDownloader!
var imageDownloader: ImageDownloader!
@@ -83,7 +80,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
let isFirstRun = AppDefaults.shared.isFirstRun
if isFirstRun {
os_log("Is first run.", log: log, type: .info)
logger.info("Is first run.")
}
if isFirstRun && !AccountManager.shared.anyAccountHasAtLeastOneFeed() {
@@ -166,7 +163,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func resumeDatabaseProcessingIfNecessary() {
if AccountManager.shared.isSuspended {
AccountManager.shared.resumeAll()
os_log("Application processing resumed.", log: self.log, type: .info)
logger.info("Application processing resumed.")
}
}
@@ -276,7 +273,7 @@ private extension AppDelegate {
self.waitBackgroundUpdateTask = UIApplication.shared.beginBackgroundTask { [weak self] in
guard let self = self else { return }
self.completeProcessing(true)
os_log("Accounts wait for progress terminated for running too long.", log: self.log, type: .info)
self.logger.info("Accounts wait for progress terminated for running too long.")
}
DispatchQueue.main.async { [weak self] in
@@ -288,18 +285,18 @@ private extension AppDelegate {
func waitToComplete(completion: @escaping (Bool) -> Void) {
guard UIApplication.shared.applicationState == .background else {
os_log("App came back to foreground, no longer waiting.", log: self.log, type: .info)
logger.info("App came back to foreground, no longer waiting.")
completion(false)
return
}
if AccountManager.shared.refreshInProgress || isSyncArticleStatusRunning {
os_log("Waiting for sync to finish...", log: self.log, type: .info)
logger.info("Waiting for sync to finish...")
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
self?.waitToComplete(completion: completion)
}
} else {
os_log("Refresh progress complete.", log: self.log, type: .info)
logger.info("Refresh progress complete.")
completion(true)
}
}
@@ -324,9 +321,9 @@ private extension AppDelegate {
self.syncBackgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
}
self.syncBackgroundUpdateTask = UIApplication.shared.beginBackgroundTask {
self.syncBackgroundUpdateTask = UIApplication.shared.beginBackgroundTask { [weak self] in
completeProcessing()
os_log("Accounts sync processing terminated for running too long.", log: self.log, type: .info)
self?.logger.info("Accounts sync processing terminated for running too long.")
}
DispatchQueue.main.async {
@@ -350,7 +347,7 @@ private extension AppDelegate {
}
}
os_log("Application processing suspended.", log: self.log, type: .info)
logger.info("Application processing suspended.")
}
}
@@ -374,11 +371,11 @@ private extension AppDelegate {
// We send this to a dedicated serial queue because as of 11/05/19 on iOS 13.2 the call to the
// task scheduler can hang indefinitely.
bgTaskDispatchQueue.async {
bgTaskDispatchQueue.async { [weak self] in
do {
try BGTaskScheduler.shared.submit(request)
} catch {
os_log(.error, log: self.log, "Could not schedule app refresh: %@", error.localizedDescription)
self?.logger.error("Could not schedule app refresh: \(error.localizedDescription, privacy: .public)")
}
}
}
@@ -390,7 +387,7 @@ private extension AppDelegate {
scheduleBackgroundFeedRefresh() // schedule next refresh
os_log("Woken to perform account refresh.", log: self.log, type: .info)
logger.info("Woken to perform account refresh.")
DispatchQueue.main.async {
if AccountManager.shared.isSuspended {
@@ -400,7 +397,7 @@ private extension AppDelegate {
if !AccountManager.shared.isSuspended {
try? WidgetDataEncoder.shared.encodeWidgetData()
self.suspendApplication()
os_log("Account refresh operation completed.", log: self.log, type: .info)
self.logger.info("Account refresh operation completed.")
task.setTaskCompleted(success: true)
}
}
@@ -408,7 +405,7 @@ private extension AppDelegate {
// set expiration handler
task.expirationHandler = { [weak task] in
os_log("Accounts refresh processing terminated for running too long.", log: self.log, type: .info)
self.logger.info("Accounts refresh processing terminated for running too long.")
DispatchQueue.main.async {
self.suspendApplication()
task?.setTaskCompleted(success: false)
@@ -431,12 +428,12 @@ private extension AppDelegate {
resumeDatabaseProcessingIfNecessary()
let account = AccountManager.shared.existingAccount(with: accountID)
guard account != nil else {
os_log(.debug, log: self.log, "No account found from notification.")
logger.debug("No account found from notification.")
return
}
let article = try? account!.fetchArticles(.articleIDs([articleID]))
guard article != nil else {
os_log(.debug, log: self.log, "No article found from search using %@", articleID)
logger.debug("No account found from search using \(articleID, privacy: .public)")
return
}
account!.markArticles(article!, statusKey: .read, flag: true) { _ in }
@@ -459,12 +456,12 @@ private extension AppDelegate {
resumeDatabaseProcessingIfNecessary()
let account = AccountManager.shared.existingAccount(with: accountID)
guard account != nil else {
os_log(.debug, log: self.log, "No account found from notification.")
logger.debug("No account found from notification.")
return
}
let article = try? account!.fetchArticles(.articleIDs([articleID]))
guard article != nil else {
os_log(.debug, log: self.log, "No article found from search using %@", articleID)
logger.debug("No article found from search using \(articleID, privacy: .public)")
return
}
account!.markArticles(article!, statusKey: .starred, flag: true) { _ in }

View File

@@ -8,24 +8,21 @@
import UIKit
import RSCore
import os.log
struct ErrorHandler {
private static var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
struct ErrorHandler: Logging {
public static func present(_ viewController: UIViewController) -> (Error) -> () {
return { [weak viewController] error in
if UIApplication.shared.applicationState == .active {
viewController?.presentError(error)
} else {
ErrorHandler.log(error)
log(error)
}
}
}
public static func log(_ error: Error) {
os_log(.error, log: self.log, "%@", error.localizedDescription)
ErrorHandler.logger.error("\(error.localizedDescription, privacy: .public)")
}
}

View File

@@ -50,7 +50,7 @@ struct FeedNode: Hashable {
}
}
class SceneCoordinator: NSObject, UndoableCommandRunner {
class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
var undoableCommands = [UndoableCommand]()
var undoManager: UndoManager? {
@@ -1272,6 +1272,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
try ArticleThemeImporter.importTheme(controller: rootSplitViewController, filename: filename)
} catch {
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error" : error])
logger.error("Failed to import theme with error: \(error.localizedDescription, privacy: .public)")
}
}

View File

@@ -10,8 +10,9 @@ import UIKit
import UserNotifications
import Account
import Zip
import RSCore
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
class SceneDelegate: UIResponder, UIWindowSceneDelegate, Logging {
var window: UIWindow?
var coordinator: SceneCoordinator!
@@ -184,7 +185,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
DispatchQueue.main.async {
NotificationCenter.default.post(name: .didBeginDownloadingTheme, object: nil)
}
let task = URLSession.shared.downloadTask(with: request) { location, response, error in
let task = URLSession.shared.downloadTask(with: request) { [weak self] location, response, error in
guard
let location = location else { return }
@@ -192,6 +193,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
try ArticleThemeDownloader.shared.handleFile(at: location)
} catch {
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error])
self?.logger.error("Failed to import theme with error: \(error.localizedDescription, privacy: .public)")
}
}
task.resume()

View File

@@ -7,8 +7,9 @@
//
import UIKit
import RSCore
struct ArticleThemeImporter {
struct ArticleThemeImporter: Logging {
static func importTheme(controller: UIViewController, filename: String) throws {
let theme = try ArticleTheme(path: filename, isAppTheme: false)
@@ -39,6 +40,7 @@ struct ArticleThemeImporter {
confirmImportSuccess(controller: controller, themeName: theme.name)
} catch {
controller.presentError(error)
ArticleThemeImporter.logger.error("Error importing theme: \(error.localizedDescription, privacy: .public)")
}
}

View File

@@ -8,10 +8,10 @@
import Foundation
import UniformTypeIdentifiers
import RSCore
import UIKit
class ArticleThemesTableViewController: UITableViewController {
class ArticleThemesTableViewController: UITableViewController, Logging {
override func viewDidLoad() {
let importBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(importTheme(_:)));
@@ -118,6 +118,7 @@ extension ArticleThemesTableViewController: UIDocumentPickerDelegate {
try ArticleThemeImporter.importTheme(controller: self, filename: url.standardizedFileURL.path)
} catch {
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error])
logger.error("Did fail to import theme: \(error.localizedDescription, privacy: .public)")
}
}

View File

@@ -13,8 +13,9 @@ import SafariServices
import SwiftUI
import UniformTypeIdentifiers
import UserNotifications
import RSCore
class SettingsViewController: UITableViewController {
class SettingsViewController: UITableViewController, Logging {
private weak var opmlAccount: Account?
@@ -509,6 +510,7 @@ private extension SettingsViewController {
try opmlString.write(to: tempFile, atomically: true, encoding: String.Encoding.utf8)
} catch {
self.presentError(title: "OPML Export Error", message: error.localizedDescription)
logger.error("OPML Export Error: \(error.localizedDescription, privacy: .public)")
}
let docPicker = UIDocumentPickerViewController(forExporting: [tempFile], asCopy: true)