mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
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:
@@ -9,6 +9,7 @@
|
||||
import Foundation
|
||||
import Account
|
||||
import Secrets
|
||||
import RSCore
|
||||
|
||||
public enum ArticleExtractorState {
|
||||
case ready
|
||||
@@ -23,7 +24,7 @@ protocol ArticleExtractorDelegate {
|
||||
func articleExtractionDidComplete(extractedArticle: ExtractedArticle)
|
||||
}
|
||||
|
||||
class ArticleExtractor {
|
||||
class ArticleExtractor: Logging {
|
||||
|
||||
private var dataTask: URLSessionDataTask? = nil
|
||||
|
||||
@@ -91,6 +92,7 @@ class ArticleExtractor {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
self.logger.error("Failed to extract article: \(error.localizedDescription, privacy: .public)")
|
||||
self.state = .failedToParse
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.articleExtractionDidFail(with: error)
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
import Foundation
|
||||
import Zip
|
||||
import RSCore
|
||||
|
||||
public class ArticleThemeDownloader {
|
||||
public class ArticleThemeDownloader: Logging {
|
||||
|
||||
public enum ArticleThemeDownloaderError: LocalizedError {
|
||||
case noThemeFile
|
||||
@@ -63,6 +64,7 @@ public class ArticleThemeDownloader {
|
||||
}
|
||||
return URL(fileURLWithPath: unzipDirectory.appendingPathComponent(themeFilePath!).path)
|
||||
} catch {
|
||||
logger.error("Failed to unzip theme: \(error.localizedDescription, privacy: .public)")
|
||||
try? FileManager.default.removeItem(at: location)
|
||||
throw error
|
||||
}
|
||||
@@ -101,7 +103,7 @@ public class ArticleThemeDownloader {
|
||||
try FileManager.default.removeItem(atPath: downloadDirectory().appendingPathComponent(path).path)
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
logger.error("Failed to clean up theme download: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public extension Notification.Name {
|
||||
static let CurrentArticleThemeDidChangeNotification = Notification.Name("CurrentArticleThemeDidChangeNotification")
|
||||
}
|
||||
|
||||
final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
|
||||
static var shared: ArticleThemesManager!
|
||||
public let folderPath: String
|
||||
@@ -58,6 +58,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
do {
|
||||
try FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
|
||||
} catch {
|
||||
logger.error("Could not create folder for themes: \(error.localizedDescription, privacy: .public)")
|
||||
assertionFailure("Could not create folder for Themes.")
|
||||
abort()
|
||||
}
|
||||
@@ -113,6 +114,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
return try ArticleTheme(path: path, isAppTheme: isAppTheme)
|
||||
} catch {
|
||||
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error])
|
||||
logger.error("Failed to import theme: \(error.localizedDescription, privacy: .public)")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,10 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
struct CacheCleaner {
|
||||
|
||||
static let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CacheCleaner")
|
||||
struct CacheCleaner: Logging {
|
||||
|
||||
static func purgeIfNecessary() {
|
||||
|
||||
@@ -35,10 +33,10 @@ struct CacheCleaner {
|
||||
|
||||
for tempItem in [faviconsFolderURL, imagesFolderURL, feedURLToIconURL, homePageToIconURL, homePagesWithNoIconURL] {
|
||||
do {
|
||||
os_log(.info, log: self.log, "Removing cache file: %@", tempItem.absoluteString)
|
||||
CacheCleaner.logger.info("Removing cache file: \(tempItem.absoluteString, privacy: .public)")
|
||||
try FileManager.default.removeItem(at: tempItem)
|
||||
} catch {
|
||||
os_log(.error, log: self.log, "Could not delete cache file: %@", error.localizedDescription)
|
||||
CacheCleaner.logger.error("Could not delete cache file: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ extension Notification.Name {
|
||||
static let FaviconDidBecomeAvailable = Notification.Name("FaviconDidBecomeAvailableNotification") // userInfo key: FaviconDownloader.UserInfoKey.faviconURL
|
||||
}
|
||||
|
||||
final class FaviconDownloader {
|
||||
final class FaviconDownloader: Logging {
|
||||
|
||||
private static let saveQueue = CoalescingQueue(name: "Cache Save Queue", interval: 1.0)
|
||||
|
||||
@@ -297,6 +297,7 @@ private extension FaviconDownloader {
|
||||
let data = try encoder.encode(homePageToFaviconURLCache)
|
||||
try data.write(to: url)
|
||||
} catch {
|
||||
logger.error("Failed to Save Home Page To Favicon URL Cache: \(error.localizedDescription, privacy: .public)")
|
||||
assertionFailure(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
@@ -311,6 +312,7 @@ private extension FaviconDownloader {
|
||||
let data = try encoder.encode(Array(homePageURLsWithNoFaviconURLCache))
|
||||
try data.write(to: url)
|
||||
} catch {
|
||||
logger.error("Failed to Save URLs With No Favicon URL Cache: \(error.localizedDescription, privacy: .public)")
|
||||
assertionFailure(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
import RSWeb
|
||||
|
||||
@@ -19,7 +18,7 @@ extension Notification.Name {
|
||||
static let DidLoadFavicon = Notification.Name("DidLoadFaviconNotification")
|
||||
}
|
||||
|
||||
final class SingleFaviconDownloader {
|
||||
final class SingleFaviconDownloader: Logging {
|
||||
|
||||
enum DiskStatus {
|
||||
case unknown, notOnDisk, onDisk
|
||||
@@ -29,8 +28,6 @@ final class SingleFaviconDownloader {
|
||||
var iconImage: IconImage?
|
||||
let homePageURL: String?
|
||||
|
||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "SingleFaviconDownloader")
|
||||
|
||||
private var lastDownloadAttemptDate: Date
|
||||
private var diskStatus = DiskStatus.unknown
|
||||
private var diskCache: BinaryDiskCache
|
||||
@@ -128,7 +125,9 @@ private extension SingleFaviconDownloader {
|
||||
self.diskStatus = .onDisk
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
catch {
|
||||
self.logger.error("Unable to save to disk: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,16 +138,16 @@ private extension SingleFaviconDownloader {
|
||||
return
|
||||
}
|
||||
|
||||
downloadUsingCache(url) { (data, response, error) in
|
||||
downloadUsingCache(url) { [weak self] (data, response, error) in
|
||||
|
||||
if let data = data, !data.isEmpty, let response = response, response.statusIsOK, error == nil {
|
||||
self.saveToDisk(data)
|
||||
self?.saveToDisk(data)
|
||||
RSImage.image(with: data, imageResultBlock: completion)
|
||||
return
|
||||
}
|
||||
|
||||
if let error = error {
|
||||
os_log(.info, log: self.log, "Error downloading image at %@: %@.", url.absoluteString, error.localizedDescription)
|
||||
self?.logger.error("Error downloading image at: \(url.absoluteString, privacy: .sensitive): \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
|
||||
completion(nil)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
import RSWeb
|
||||
|
||||
@@ -16,9 +15,7 @@ extension Notification.Name {
|
||||
static let ImageDidBecomeAvailable = Notification.Name("ImageDidBecomeAvailableNotification") // UserInfoKey.url
|
||||
}
|
||||
|
||||
final class ImageDownloader {
|
||||
|
||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ImageDownloader")
|
||||
final class ImageDownloader: Logging {
|
||||
|
||||
private let folder: String
|
||||
private var diskCache: BinaryDiskCache
|
||||
@@ -103,19 +100,19 @@ private extension ImageDownloader {
|
||||
return
|
||||
}
|
||||
|
||||
downloadUsingCache(imageURL) { (data, response, error) in
|
||||
downloadUsingCache(imageURL) { [weak self] (data, response, error) in
|
||||
|
||||
if let data = data, !data.isEmpty, let response = response, response.statusIsOK, error == nil {
|
||||
self.saveToDisk(url, data)
|
||||
self?.saveToDisk(url, data)
|
||||
completion(data)
|
||||
return
|
||||
}
|
||||
|
||||
if let response = response as? HTTPURLResponse, response.statusCode >= HTTPResponseCode.badRequest && response.statusCode <= HTTPResponseCode.notAcceptable {
|
||||
self.badURLs.insert(url)
|
||||
self?.badURLs.insert(url)
|
||||
}
|
||||
if let error = error {
|
||||
os_log(.info, log: self.log, "Error downloading image at %@: %@.", url, error.localizedDescription)
|
||||
self?.logger.error("Error downloading image at: \(url, privacy: .sensitive): \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
|
||||
completion(nil)
|
||||
|
||||
@@ -7,15 +7,12 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
import RSParser
|
||||
import Account
|
||||
|
||||
final class ExtensionContainersFile {
|
||||
final class ExtensionContainersFile: Logging {
|
||||
|
||||
private static var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "extensionContainersFile")
|
||||
|
||||
private static var filePath: String = {
|
||||
let appGroup = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String
|
||||
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup)
|
||||
@@ -55,7 +52,7 @@ final class ExtensionContainersFile {
|
||||
})
|
||||
|
||||
if let error = errorPointer?.pointee {
|
||||
os_log(.error, log: log, "Read from disk coordination failed: %@.", error.localizedDescription)
|
||||
logger.error("Read from coordination failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
|
||||
return extensionContainers
|
||||
@@ -88,19 +85,19 @@ private extension ExtensionContainersFile {
|
||||
let fileCoordinator = NSFileCoordinator()
|
||||
let fileURL = URL(fileURLWithPath: ExtensionContainersFile.filePath)
|
||||
|
||||
fileCoordinator.coordinate(writingItemAt: fileURL, options: [], error: errorPointer, byAccessor: { writeURL in
|
||||
fileCoordinator.coordinate(writingItemAt: fileURL, options: [], error: errorPointer, byAccessor: { [weak self] writeURL in
|
||||
do {
|
||||
let extensionAccounts = AccountManager.shared.sortedActiveAccounts.map { ExtensionAccount(account: $0) }
|
||||
let extensionContainers = ExtensionContainers(accounts: extensionAccounts)
|
||||
let data = try encoder.encode(extensionContainers)
|
||||
try data.write(to: writeURL)
|
||||
} catch let error as NSError {
|
||||
os_log(.error, log: Self.log, "Save to disk failed: %@.", error.localizedDescription)
|
||||
self?.logger.error("Save to disk failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
})
|
||||
|
||||
if let error = errorPointer?.pointee {
|
||||
os_log(.error, log: Self.log, "Save to disk coordination failed: %@.", error.localizedDescription)
|
||||
logger.error("Save to disk coordination failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import Account
|
||||
import RSCore
|
||||
|
||||
final class ExtensionFeedAddRequestFile: NSObject, NSFilePresenter {
|
||||
final class ExtensionFeedAddRequestFile: NSObject, NSFilePresenter, Logging {
|
||||
|
||||
private static var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "extensionFeedAddRequestFile")
|
||||
|
||||
private static var filePath: String = {
|
||||
let appGroup = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String
|
||||
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup)
|
||||
@@ -82,12 +80,12 @@ final class ExtensionFeedAddRequestFile: NSObject, NSFilePresenter {
|
||||
try data.write(to: url)
|
||||
|
||||
} catch let error as NSError {
|
||||
os_log(.error, log: Self.log, "Save to disk failed: %@.", error.localizedDescription)
|
||||
logger.error("Save to disk failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
})
|
||||
|
||||
if let error = errorPointer?.pointee {
|
||||
os_log(.error, log: Self.log, "Save to disk coordination failed: %@.", error.localizedDescription)
|
||||
logger.error("Save to disk coordination failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +105,7 @@ private extension ExtensionFeedAddRequestFile {
|
||||
|
||||
var requests: [ExtensionFeedAddRequest]? = nil
|
||||
|
||||
fileCoordinator.coordinate(writingItemAt: fileURL, options: [.forMerging], error: errorPointer, byAccessor: { url in
|
||||
fileCoordinator.coordinate(writingItemAt: fileURL, options: [.forMerging], error: errorPointer, byAccessor: { [weak self] url in
|
||||
do {
|
||||
|
||||
if let fileData = try? Data(contentsOf: url),
|
||||
@@ -119,12 +117,12 @@ private extension ExtensionFeedAddRequestFile {
|
||||
try data.write(to: url)
|
||||
|
||||
} catch let error as NSError {
|
||||
os_log(.error, log: Self.log, "Save to disk failed: %@.", error.localizedDescription)
|
||||
self?.logger.error("Save to disk failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
})
|
||||
|
||||
if let error = errorPointer?.pointee {
|
||||
os_log(.error, log: Self.log, "Save to disk coordination failed: %@.", error.localizedDescription)
|
||||
logger.error("Save to disk coordination failed: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
|
||||
requests?.forEach { processRequest($0) }
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
|
||||
struct WidgetDataDecoder {
|
||||
struct WidgetDataDecoder: Logging {
|
||||
|
||||
static func decodeWidgetData() throws -> WidgetData {
|
||||
func decodeWidgetData() throws -> WidgetData {
|
||||
let appGroup = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String
|
||||
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup)
|
||||
let dataURL = containerURL?.appendingPathComponent("widget-data.json")
|
||||
@@ -22,13 +23,14 @@ struct WidgetDataDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
static func sampleData() -> WidgetData {
|
||||
func sampleData() -> WidgetData {
|
||||
let pathToSample = Bundle.main.url(forResource: "widget-sample", withExtension: "json")
|
||||
do {
|
||||
let data = try Data(contentsOf: pathToSample!)
|
||||
let decoded = try JSONDecoder().decode(WidgetData.self, from: data)
|
||||
return decoded
|
||||
} catch {
|
||||
logger.error("Error accessing sample widget data: \(error.localizedDescription, privacy: .public)")
|
||||
return WidgetData(currentUnreadCount: 0, currentTodayCount: 0, currentStarredCount: 0, unreadArticles: [], starredArticles: [], todayArticles: [], lastUpdateTime: Date())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,15 @@
|
||||
|
||||
import Foundation
|
||||
import WidgetKit
|
||||
import os.log
|
||||
import UIKit
|
||||
import RSCore
|
||||
import Articles
|
||||
import Account
|
||||
|
||||
|
||||
public final class WidgetDataEncoder {
|
||||
public final class WidgetDataEncoder: Logging {
|
||||
|
||||
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
|
||||
private let fetchLimit = 7
|
||||
|
||||
private var backgroundTaskID: UIBackgroundTaskIdentifier!
|
||||
@@ -36,7 +35,7 @@ public final class WidgetDataEncoder {
|
||||
@available(iOS 14, *)
|
||||
func encodeWidgetData() throws {
|
||||
flushSharedContainer()
|
||||
os_log(.debug, log: log, "Starting encoding widget data.")
|
||||
logger.debug("Started encoding widget data.")
|
||||
|
||||
do {
|
||||
let unreadArticles = Array(try AccountManager.shared.fetchArticles(.unread(fetchLimit))).sortedByDate(.orderedDescending)
|
||||
@@ -95,14 +94,14 @@ public final class WidgetDataEncoder {
|
||||
}
|
||||
let encodedData = try? JSONEncoder().encode(latestData)
|
||||
|
||||
os_log(.debug, log: self.log, "Finished encoding widget data.")
|
||||
self.logger.debug("Finished encoding widget data.")
|
||||
|
||||
if self.fileExists() {
|
||||
try? FileManager.default.removeItem(at: self.dataURL!)
|
||||
os_log(.debug, log: self.log, "Removed widget data from container.")
|
||||
self.logger.debug("Removed widget data from container.")
|
||||
}
|
||||
if FileManager.default.createFile(atPath: self.dataURL!.path, contents: encodedData, attributes: nil) {
|
||||
os_log(.debug, log: self.log, "Wrote widget data to container.")
|
||||
self.logger.debug("Wrote widget data to container.")
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
|
||||
self.backgroundTaskID = .invalid
|
||||
|
||||
Reference in New Issue
Block a user