diff --git a/CHANGELOG.md b/CHANGELOG.md index 616f142f8c..584e96a824 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * [FEATURE] Add support for 128 bit trace IDs. See [#1721][] * [FEATURE] Fatal App Hangs are tracked in RUM. See [#1763][] +* [FIX] Avoid name collision with Required Reason APIs. See [#1774][] # 2.9.0 / 11-04-2024 @@ -630,6 +631,7 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO [#1741]: https://github.com/DataDog/dd-sdk-ios/pull/1741 [#1742]: https://github.com/DataDog/dd-sdk-ios/pull/1742 [#1746]: https://github.com/DataDog/dd-sdk-ios/pull/1746 +[#1774]: https://github.com/DataDog/dd-sdk-ios/pull/1774 [#1763]: https://github.com/DataDog/dd-sdk-ios/pull/1763 [#1767]: https://github.com/DataDog/dd-sdk-ios/pull/1767 [#1721]: https://github.com/DataDog/dd-sdk-ios/pull/1721 diff --git a/DatadogCore/Sources/Core/Storage/FilesOrchestrator.swift b/DatadogCore/Sources/Core/Storage/FilesOrchestrator.swift index 11d798c46e..8f587a376f 100644 --- a/DatadogCore/Sources/Core/Storage/FilesOrchestrator.swift +++ b/DatadogCore/Sources/Core/Storage/FilesOrchestrator.swift @@ -137,9 +137,9 @@ internal class FilesOrchestrator: FilesOrchestratorType { func getReadableFiles(excludingFilesNamed excludedFileNames: Set = [], limit: Int = .max) -> [ReadableFile] { do { let filesFromOldest = try directory.files() - .map { (file: $0, creationDate: fileCreationDateFrom(fileName: $0.name)) } - .compactMap { try deleteFileIfItsObsolete(file: $0.file, fileCreationDate: $0.creationDate) } - .sorted(by: { $0.creationDate < $1.creationDate }) + .map { (file: $0, fileCreationDate: fileCreationDateFrom(fileName: $0.name)) } + .compactMap { try deleteFileIfItsObsolete(file: $0.file, fileCreationDate: $0.fileCreationDate) } + .sorted(by: { $0.fileCreationDate < $1.fileCreationDate }) if ignoreFilesAgeWhenReading { return filesFromOldest @@ -149,7 +149,7 @@ internal class FilesOrchestrator: FilesOrchestratorType { let filtered = filesFromOldest .filter { - let fileAge = dateProvider.now.timeIntervalSince($0.creationDate) + let fileAge = dateProvider.now.timeIntervalSince($0.fileCreationDate) return excludedFileNames.contains($0.file.name) == false && fileAge >= performance.minFileAgeForRead } return filtered @@ -178,8 +178,8 @@ internal class FilesOrchestrator: FilesOrchestratorType { /// Removes oldest files from the directory if it becomes too big. private func purgeFilesDirectoryIfNeeded() throws { let filesSortedByCreationDate = try directory.files() - .map { (file: $0, creationDate: fileCreationDateFrom(fileName: $0.name)) } - .sorted { $0.creationDate < $1.creationDate } + .map { (file: $0, fileCreationDate: fileCreationDateFrom(fileName: $0.name)) } + .sorted { $0.fileCreationDate < $1.fileCreationDate } var filesWithSizeSortedByCreationDate = try filesSortedByCreationDate .map { (file: $0.file, size: try $0.file.size()) } @@ -199,7 +199,7 @@ internal class FilesOrchestrator: FilesOrchestratorType { } } - private func deleteFileIfItsObsolete(file: File, fileCreationDate: Date) throws -> (file: File, creationDate: Date)? { + private func deleteFileIfItsObsolete(file: File, fileCreationDate: Date) throws -> (file: File, fileCreationDate: Date)? { let fileAge = dateProvider.now.timeIntervalSince(fileCreationDate) if fileAge > performance.maxFileAgeForRead { @@ -207,7 +207,7 @@ internal class FilesOrchestrator: FilesOrchestratorType { sendBatchDeletedMetric(batchFile: file, deletionReason: .obsolete) return nil } else { - return (file: file, creationDate: fileCreationDate) + return (file: file, fileCreationDate: fileCreationDate) } } diff --git a/DatadogCore/Sources/Kronos/KronosTimeFreeze.swift b/DatadogCore/Sources/Kronos/KronosTimeFreeze.swift index 07aef1ab4c..b559742f4a 100644 --- a/DatadogCore/Sources/Kronos/KronosTimeFreeze.swift +++ b/DatadogCore/Sources/Kronos/KronosTimeFreeze.swift @@ -24,20 +24,20 @@ internal struct KronosTimeFreeze { } /// The stable timestamp (calculated based on the uptime); note that this doesn't have sub-seconds - /// precision. See `systemUptime()` for more information. + /// precision. See `getSystemUptime()` for more information. var stableTimestamp: TimeInterval { - return (KronosTimeFreeze.systemUptime() - self.uptime) + self.timestamp + return (KronosTimeFreeze.getSystemUptime() - self.uptime) + self.timestamp } /// Time interval between now and the time the NTP response represented by this TimeFreeze was received. var timeSinceLastNtpSync: TimeInterval { - return KronosTimeFreeze.systemUptime() - uptime + return KronosTimeFreeze.getSystemUptime() - uptime } init(offset: TimeInterval) { self.offset = offset self.timestamp = kronosCurrentTime() - self.uptime = KronosTimeFreeze.systemUptime() + self.uptime = KronosTimeFreeze.getSystemUptime() } init?(from dictionary: [String: TimeInterval]) { @@ -47,7 +47,7 @@ internal struct KronosTimeFreeze { return nil } - let currentUptime = KronosTimeFreeze.systemUptime() + let currentUptime = KronosTimeFreeze.getSystemUptime() let currentTimestamp = kronosCurrentTime() let currentBoot = currentUptime - currentTimestamp let previousBoot = uptime - timestamp @@ -79,7 +79,7 @@ internal struct KronosTimeFreeze { /// see: https://github.com/darwin-on-arm/xnu/blob/master/osfmk/kern/clock.c#L522. /// /// - returns: An Int measurement of system uptime in microseconds. - static func systemUptime() -> TimeInterval { + private static func getSystemUptime() -> TimeInterval { var mib = [CTL_KERN, KERN_BOOTTIME] var size = MemoryLayout.stride var bootTime = timeval() diff --git a/DatadogCore/Sources/Kronos/KronosTimeStorage.swift b/DatadogCore/Sources/Kronos/KronosTimeStorage.swift index 75b8590d38..54418c27cd 100644 --- a/DatadogCore/Sources/Kronos/KronosTimeStorage.swift +++ b/DatadogCore/Sources/Kronos/KronosTimeStorage.swift @@ -31,7 +31,7 @@ internal enum KronosTimeStoragePolicy { /// Handles saving and retrieving instances of `KronosTimeFreeze` for quick retrieval internal struct KronosTimeStorage { - private var userDefaults: UserDefaults + private var userDefaults: UserDefaults // swiftlint:disable:this required_reason_api_name private let kDefaultsKey = "KronosStableTime" /// The most recent stored `TimeFreeze`. Getting retrieves from the UserDefaults defined by the storage @@ -63,7 +63,7 @@ internal struct KronosTimeStorage { case .standard: self.userDefaults = .standard case .appGroup(let groupName): - let sharedDefaults = UserDefaults(suiteName: groupName) + let sharedDefaults = UserDefaults(suiteName: groupName) // swiftlint:disable:this required_reason_api_name assert(sharedDefaults != nil, "Could not create UserDefaults for group: '\(groupName)'") self.userDefaults = sharedDefaults ?? .standard } diff --git a/tools/lint/sources.swiftlint.yml b/tools/lint/sources.swiftlint.yml index b9e873f2c2..230c323139 100644 --- a/tools/lint/sources.swiftlint.yml +++ b/tools/lint/sources.swiftlint.yml @@ -89,6 +89,61 @@ custom_rules: - doccomment message: "`UIApplication.shared` is unavailable in some environments. Check `UIApplication.managedShared`." severity: error + required_reason_api_name: # prevents from declaring symbols that may conflict with Apple's Required Reason APIs + included: Sources + name: "Required Reason API Conflict" + # The list of Required Reason APIs: + # https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api + regex: > + (\.creationDate)| + (\.creationDateKey)| + (\.modificationDate)| + (\.fileModificationDate)| + (\.contentModificationDateKey)| + (\.creationDateKey)| + (getattrlist\()| + (getattrlistbulk\()| + (fgetattrlist\()| + (stat\.st_)| + (fstat\()| + (fstatat\()| + (lstat\()| + (getattrlistat\()| + (systemUptime)| + (mach_absolute_time\(\))| + (volumeAvailableCapacityKey)| + (volumeAvailableCapacityForImportantUsageKey)| + (volumeAvailableCapacityForOpportunisticUsageKey)| + (volumeTotalCapacityKey)| + (systemFreeSize)| + (systemSize)| + (statfs\()| + (statvfs\()| + (fstatfs\()| + (fstatvfs\()| + (getattrlist\()| + (fgetattrlist\()| + (getattrlistat\()| + (activeInputModes)| + (UserDefaults)| + (NSUserDefaults)| + (NSFileCreationDate)| + (NSFileModificationDate)| + (NSFileSystemFreeSize)| + (NSFileSystemSize)| + (NSURLContentModificationDateKey)| + (NSURLCreationDateKey)| + (NSURLVolumeAvailableCapacityForImportantUsageKey)| + (NSURLVolumeAvailableCapacityForOpportunisticUsageKey)| + (NSURLVolumeAvailableCapacityKey)| + (NSURLVolumeTotalCapacityKey)| + (AppStorage) + excluded_match_kinds: + - comment + - doccomment + - string + message: "Symbol name conflicts with one of Apple's Required Reason APIs. Use different name." + severity: error included: - ../../DatadogInternal/Sources