Skip to content
This repository was archived by the owner on Jan 10, 2023. It is now read-only.

Macos support issue2 #3

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Sources/SwiftLogFireCloud/CloudLogFileManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import Foundation
#if canImport(UIKit)
import UIKit
#endif
Expand Down Expand Up @@ -56,7 +57,7 @@ class CloudLogFileManager: CloudLogFileManagerProtocol {
pendingWriteMaxRetries = !config.isTesting ? 10 : 2
}

private func createCloundFilePathAndName(date: Date?) -> String {
private func createCloudFilePathAndName(date: Date?) -> String {
var cloudFilePath = "\(self.config.logDirectoryName)"
if cloudFilePath.count != 0 { cloudFilePath += "/" }

Expand All @@ -82,9 +83,11 @@ class CloudLogFileManager: CloudLogFileManagerProtocol {
if let deviceIDForFilename = config.uniqueIDString, deviceIDForFilename.count != 0 {
cloudFilePath += "\(deviceIDForFilename)/"
} else {
#if os(iOS)
if let deviceID = UIDevice.current.identifierForVendor?.uuidString {
cloudFilePath += "\(deviceID)/"
}
#endif
}
cloudFilePath += "\(label)/"

Expand Down Expand Up @@ -157,7 +160,7 @@ class CloudLogFileManager: CloudLogFileManagerProtocol {
completion?()
return
}
let cloudFilePath = self.createCloundFilePathAndName(date: fileAttr.creationDate)
let cloudFilePath = self.createCloudFilePathAndName(date: fileAttr.creationDate)
cloudUploader.uploadFile(from: localLogFile, to: cloudFilePath) { result in
switch result {
case .success(let logFile):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public enum CloudUploadError : Error {
}

/// Protocol the client object must conform to which has the Firebase Storage references and requests the upload and reports back status.
public protocol CloudFileUploaderProtocol: class {
public protocol CloudFileUploaderProtocol: AnyObject {

func uploadFile(from localFile: LocalLogFile, to cloudPath: String, completion: @escaping (Result<LocalLogFile, CloudUploadError>)->Void)
}
25 changes: 18 additions & 7 deletions Sources/SwiftLogFireCloud/LocalLogFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ limitations under the License.
#if canImport(UIKit)
import UIKit
#endif
#if canImport(AppKit)
import AppKit
#endif

enum LocalLogFileError : Error {
case distpatchIOErrorNo(Int)
Expand Down Expand Up @@ -72,13 +75,13 @@ public class LocalLogFile {
/// - label: The label used for the logger creating the log file
/// - config: The loggers `SwiftLogFilreCloudConfig` object, for which the local log file uses the log directory and other aspects.
/// - queue: The dispatch queue used for writing to the local disk.
init(label: String, config: SwiftLogFireCloudConfig, queue: DispatchQueue) {
init(label: String, config: SwiftLogFireCloudConfig, queue: DispatchQueue, tempURL: URL) {
self.config = config
self.label = label
self.bufferSizeToGiveUp = 4 * config.localFileSizeThresholdToPushToCloud
self.writeResponseQueue = queue
self.fileURL = LocalLogFile.createLogFileURL(
localLogDirectoryName: config.logDirectoryName, clientDeviceID: config.uniqueIDString, label: label)
localLogDirectoryName: config.logDirectoryName, clientDeviceID: config.uniqueIDString, label: label, tempDirPath: tempURL)
}

deinit {
Expand All @@ -90,9 +93,18 @@ public class LocalLogFile {
/// - Returns: `String` representation of the log file name.
private static func createLogFileName(deviceId: String?, label: String) -> String {
var deviceIdForFileName = deviceId
if deviceId == nil || deviceId?.count == 0 {

if deviceId == nil || deviceId?.isEmpty ?? true {
#if os(iOS)
deviceIdForFileName = UIDevice.current.identifierForVendor?.uuidString
#elseif os(macOS)
// this is suboptimal, as the uniquestring changes on each get so grouping by device will be problematic
// if the config is not set to something sane and unique across the consuming app. There is no equivalent
// identifierForVendor on macOS allegedly
deviceIdForFileName = ProcessInfo().globallyUniqueString
#endif
}

let fileDateString = LocalLogFile.dateFormatter.string(from: Date())
let bundleString = Bundle.main.bundleIdentifier
let versionNumber =
Expand Down Expand Up @@ -129,14 +141,13 @@ public class LocalLogFile {
/// - clientDeviceID: Client supplied unique identifer for the log
/// - label: the SwiiftLog label specified by the client
/// - Returns: `URL` representation of the log file name.
private static func createLogFileURL(localLogDirectoryName: String, clientDeviceID: String?, label: String) -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
private static func createLogFileURL(localLogDirectoryName: String, clientDeviceID: String?, label: String, tempDirPath: URL) -> URL {

if localLogDirectoryName.count != 0 {
return paths[0].appendingPathComponent(localLogDirectoryName).appendingPathComponent(
return tempDirPath.appendingPathComponent(localLogDirectoryName).appendingPathComponent(
LocalLogFile.createLogFileName(deviceId: clientDeviceID, label: label))
} else {
return paths[0].appendingPathComponent(LocalLogFile.createLogFileName(deviceId: clientDeviceID, label: label))
return tempDirPath.appendingPathComponent(LocalLogFile.createLogFileName(deviceId: clientDeviceID, label: label))
}
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/SwiftLogFireCloud/SwiftLogFireCloudConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public struct SwiftLogFireCloudConfig {

/// An optional uniqueID string to identify the log file that is embedded in the log file name.
///
/// If omitted, the library will utlize the `UIDevice.current.identifierForVendor` to uniquely identify the logfile
/// If omitted, the library will utlize the `UIDevice.current.identifierForVendor`on iOS to uniquely identify the logfile. On macOS
/// if this is omitted the processInfo string is use, but its not constant across the process runs so aggregating log files is problematic.
let uniqueIDString: String?

/// Minimum required local file system space to start or continue logging.
Expand Down
36 changes: 25 additions & 11 deletions Sources/SwiftLogFireCloud/SwiftLogManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import Foundation
#if canImport(UIKit)
import UIKit
#endif
Expand All @@ -36,7 +37,10 @@ internal class SwiftLogManager {
internal var successiveWriteFailures: Int = 0
private let strandedFilesDelay: TimeInterval
private var impairedMessages: Data?

#if os(iOS)
private var backgroundTaskID = UIBackgroundTaskIdentifier.invalid
#endif

private func startWriteTimer(interval: TimeInterval) -> Timer {
return Timer.scheduledTimer(
Expand All @@ -59,23 +63,23 @@ internal class SwiftLogManager {
self.strandedFilesDelay = !config.isTesting ? 15 : 5

writeTimer = startWriteTimer(interval: config.localFileBufferWriteInterval)

#if os(iOS)
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(
self, selector: #selector(appWillResignActive),
name: UIApplication.willResignActiveNotification, object: nil)
notificationCenter.addObserver(
self, selector: #selector(appWillResumeActive),
name: UIApplication.willEnterForegroundNotification, object: nil)

#endif
//wait 15s after startup, then attempt to push any files from previous runs up to cloud
DispatchQueue.main.asyncAfter(deadline: .now() + strandedFilesDelay) {
self.processStrandedFilesAtStartup()
}

#if targetEnvironment(simulator)
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
print("Log File location: \(paths[0].appendingPathComponent(config.logDirectoryName))")
let tempDirPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
print("Log File location: \(tempDirPath.appendingPathComponent(config.logDirectoryName))")
#endif
}

Expand All @@ -84,6 +88,7 @@ internal class SwiftLogManager {
writeTimer = startWriteTimer(interval: config.localFileBufferWriteInterval)
}
}
#if os(iOS)
@objc internal func appWillResignActive(_ application: UIApplication) { //}, _ completionForTesting: (() -> Void)? = nil) {
let backgroundEntitlementStatus = UIApplication.shared.backgroundRefreshStatus
switch backgroundEntitlementStatus {
Expand Down Expand Up @@ -116,13 +121,22 @@ internal class SwiftLogManager {

self.writeTimer?.invalidate()
}
#endif

private func getLocalTempDirectory() -> URL {
#if os(iOS)
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
#elseif os(macOS)
return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
#endif
}

/// Creates the local log file directory for the logger. If the directory already exists, this is essentially an expensive no-op.
internal func createLocalLogDirectory() {
guard config.logDirectoryName.count > 0 else { return }
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
guard !config.logDirectoryName.isEmpty else { return }
let tempDirPath = getLocalTempDirectory()

let pathURL = paths[0].appendingPathComponent(config.logDirectoryName)
let pathURL = tempDirPath.appendingPathComponent(config.logDirectoryName)
do {
try FileManager.default.createDirectory(
at: pathURL, withIntermediateDirectories: true, attributes: nil)
Expand All @@ -135,17 +149,17 @@ internal class SwiftLogManager {
/// Queries the local file system for the list of files currently in the local log directory.
/// - Returns: Array of `LocalLogFile` objects representing the files on disk.
internal func retrieveLocalLogFileListOnDisk() -> [LocalLogFile] {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let tempDirPath = getLocalTempDirectory()

let pathURL = paths[0].appendingPathComponent(self.config.logDirectoryName)
let pathURL = tempDirPath.appendingPathComponent(self.config.logDirectoryName)
var localLogFilesOnDisk = [LocalLogFile]()
do {
let files = try FileManager.default.contentsOfDirectory(
at: pathURL, includingPropertiesForKeys: nil
)
.filter { $0.pathExtension == "log" }
for file in files {
let logFileOnDisk = LocalLogFile(label: label, config: config, queue: localLogQueue)
let logFileOnDisk = LocalLogFile(label: label, config: config, queue: localLogQueue, tempURL: getLocalTempDirectory())
logFileOnDisk.fileURL = file
let attr = logFileOnDisk.getLocalLogFileAttributes()
if let fileSize = attr.fileSize {
Expand Down Expand Up @@ -299,7 +313,7 @@ internal class SwiftLogManager {
}

if self.localLogFile == nil {
self.localLogFile = LocalLogFile(label: self.label, config: self.config, queue: self.localLogQueue)
self.localLogFile = LocalLogFile(label: self.label, config: self.config, queue: self.localLogQueue, tempURL: self.getLocalTempDirectory())
}
let logability = self.assessLocalLogability()

Expand Down
Loading