From d7fe1daa0dbd1a902ee464bdb6048a92b7eb53b3 Mon Sep 17 00:00:00 2001 From: Maciej Burda Date: Fri, 26 Apr 2024 14:56:14 +0100 Subject: [PATCH 1/6] RUM-3284 Add background activity when run from extension --- DatadogCore/Sources/Core/DatadogCore.swift | 8 +++++- .../Sources/Core/Storage/Directories.swift | 4 +-- .../Upload/BackgroundTaskCoordinator.swift | 28 ++++++++++++++++++- .../Sources/Core/Upload/FeatureUpload.swift | 13 +++++++-- DatadogCore/Sources/Datadog.swift | 6 ++-- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/DatadogCore/Sources/Core/DatadogCore.swift b/DatadogCore/Sources/Core/DatadogCore.swift index 7e4e98dfe3..b483ad99f2 100644 --- a/DatadogCore/Sources/Core/DatadogCore.swift +++ b/DatadogCore/Sources/Core/DatadogCore.swift @@ -68,6 +68,9 @@ internal final class DatadogCore { /// Flag defining if background tasks are enabled. internal let backgroundTasksEnabled: Bool + /// Flag defining if the SDK is run from an extension. + internal let isRunFromExtension: Bool + /// Maximum number of batches per upload. internal let maxBatchesPerUpload: Int @@ -92,7 +95,8 @@ internal final class DatadogCore { contextProvider: DatadogContextProvider, applicationVersion: String, maxBatchesPerUpload: Int, - backgroundTasksEnabled: Bool + backgroundTasksEnabled: Bool, + isRunFromExtension: Bool ) { self.directory = directory self.dateProvider = dateProvider @@ -102,6 +106,7 @@ internal final class DatadogCore { self.contextProvider = contextProvider self.maxBatchesPerUpload = maxBatchesPerUpload self.backgroundTasksEnabled = backgroundTasksEnabled + self.isRunFromExtension = isRunFromExtension self.applicationVersionPublisher = ApplicationVersionPublisher(version: applicationVersion) self.consentPublisher = TrackingConsentPublisher(consent: initialConsent) @@ -258,6 +263,7 @@ extension DatadogCore: DatadogCoreProtocol { performance: performancePreset, backgroundTasksEnabled: backgroundTasksEnabled, maxBatchesPerUpload: maxBatchesPerUpload, + isRunFromExtension: isRunFromExtension, telemetry: telemetry ) diff --git a/DatadogCore/Sources/Core/Storage/Directories.swift b/DatadogCore/Sources/Core/Storage/Directories.swift index 6451020799..05bfe74870 100644 --- a/DatadogCore/Sources/Core/Storage/Directories.swift +++ b/DatadogCore/Sources/Core/Storage/Directories.swift @@ -44,8 +44,8 @@ internal extension CoreDirectory { /// - osDirectory: the root OS directory (`/Library/Caches`) to create core directory inside. /// - instancenName: The core instance name. /// - site: The cor instance site. - init(in osDirectory: Directory, instancenName: String, site: DatadogSite) throws { - let sdkInstanceUUID = sha256("\(instancenName)\(site)") + init(in osDirectory: Directory, instanceName: String, site: DatadogSite) throws { + let sdkInstanceUUID = sha256("\(instanceName)\(site)") let path = "com.datadoghq/v2/\(sdkInstanceUUID)" self.init( diff --git a/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift b/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift index 561d70d61d..38d9a063b4 100644 --- a/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift +++ b/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift @@ -28,7 +28,7 @@ internal protocol UIKitAppBackgroundTaskCoordinator { extension UIApplication: UIKitAppBackgroundTaskCoordinator {} -internal class UIKitBackgroundTaskCoordinator: BackgroundTaskCoordinator { +internal class AppBackgroundTaskCoordinator: BackgroundTaskCoordinator { private let app: UIKitAppBackgroundTaskCoordinator? @ReadWriteLock @@ -60,4 +60,30 @@ internal class UIKitBackgroundTaskCoordinator: BackgroundTaskCoordinator { self.currentTaskId = nil } } + +internal class ExtensionBackgroundTaskCoordinator: BackgroundTaskCoordinator { + private let processInfo: ProcessInfo + + @ReadWriteLock + private var currentActivity: NSObjectProtocol? + + internal init( + processInfo: ProcessInfo = .init() + ) { + self.processInfo = processInfo + } + + internal func beginBackgroundTask() { + endBackgroundTask() + currentActivity = processInfo.beginActivity(options: [.background], reason: "Datadog background upload") + } + + internal func endBackgroundTask() { + guard let currentActivity = currentActivity else { + return + } + ProcessInfo().endActivity(currentActivity) + self.currentActivity = nil + } +} #endif diff --git a/DatadogCore/Sources/Core/Upload/FeatureUpload.swift b/DatadogCore/Sources/Core/Upload/FeatureUpload.swift index 6e86010343..dcdd25d1a8 100644 --- a/DatadogCore/Sources/Core/Upload/FeatureUpload.swift +++ b/DatadogCore/Sources/Core/Upload/FeatureUpload.swift @@ -20,6 +20,7 @@ internal struct FeatureUpload { performance: PerformancePreset, backgroundTasksEnabled: Bool, maxBatchesPerUpload: Int, + isRunFromExtension: Bool, telemetry: Telemetry ) { let uploadQueue = DispatchQueue( @@ -34,9 +35,15 @@ internal struct FeatureUpload { ) #if canImport(UIKit) - let backgroundTaskCoordinator = backgroundTasksEnabled - ? UIKitBackgroundTaskCoordinator() - : nil + let backgroundTaskCoordinator: BackgroundTaskCoordinator? + switch (backgroundTasksEnabled, isRunFromExtension) { + case (true, false): + backgroundTaskCoordinator = AppBackgroundTaskCoordinator() + case (true, true): + backgroundTaskCoordinator = ExtensionBackgroundTaskCoordinator() + case (false, _): + backgroundTaskCoordinator = nil + } #else let backgroundTaskCoordinator: BackgroundTaskCoordinator? = nil #endif diff --git a/DatadogCore/Sources/Datadog.swift b/DatadogCore/Sources/Datadog.swift index 4cb14c1dd5..d7f32e57b4 100644 --- a/DatadogCore/Sources/Datadog.swift +++ b/DatadogCore/Sources/Datadog.swift @@ -430,12 +430,13 @@ public enum Datadog { uploadFrequency: debug ? .frequent : configuration.uploadFrequency, bundleType: bundleType ) + let isRunFromExtension = bundleType == .iOSAppExtension // Set default `DatadogCore`: let core = DatadogCore( directory: try CoreDirectory( in: configuration.systemDirectory(), - instancenName: instanceName, + instanceName: instanceName, site: configuration.site ), dateProvider: configuration.dateProvider, @@ -466,7 +467,8 @@ public enum Datadog { ), applicationVersion: applicationVersion, maxBatchesPerUpload: configuration.batchProcessingLevel.maxBatchesPerUpload, - backgroundTasksEnabled: configuration.backgroundTasksEnabled + backgroundTasksEnabled: configuration.backgroundTasksEnabled, + isRunFromExtension: isRunFromExtension ) core.telemetry.configuration( From 13ec282be76aeea3739e09f8ea43f76ceff120e0 Mon Sep 17 00:00:00 2001 From: Maciej Burda Date: Fri, 26 Apr 2024 16:48:43 +0100 Subject: [PATCH 2/6] RUM-3284 Provide process info background tasks for extensions --- Datadog/Datadog.xcodeproj/project.pbxproj | 18 +++-- DatadogCore/Sources/Core/DatadogCore.swift | 2 +- .../Upload/BackgroundTaskCoordinator.swift | 16 +++-- .../Tests/Datadog/Core/DirectoriesTests.swift | 4 +- ...> AppBackgroundTaskCoordinatorTests.swift} | 6 +- ...ensionBackgroundTaskCoordinatorTests.swift | 66 +++++++++++++++++++ 6 files changed, 96 insertions(+), 16 deletions(-) rename DatadogCore/Tests/Datadog/Core/Upload/{UIKitBackgroundTaskCoordinatorTests.swift => AppBackgroundTaskCoordinatorTests.swift} (92%) create mode 100644 DatadogCore/Tests/Datadog/Core/Upload/ExtensionBackgroundTaskCoordinatorTests.swift diff --git a/Datadog/Datadog.xcodeproj/project.pbxproj b/Datadog/Datadog.xcodeproj/project.pbxproj index 3a2ed98c4b..baa78fe3b1 100644 --- a/Datadog/Datadog.xcodeproj/project.pbxproj +++ b/Datadog/Datadog.xcodeproj/project.pbxproj @@ -582,6 +582,8 @@ A74A72852B10CC6700771FEB /* ResourceRequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74A72842B10CC6700771FEB /* ResourceRequestBuilderTests.swift */; }; A74A72872B10CE4100771FEB /* ResourceMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74A72862B10CE4100771FEB /* ResourceMocks.swift */; }; A74A72892B10D95D00771FEB /* MultipartBuilderSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74A72882B10D95D00771FEB /* MultipartBuilderSpy.swift */; }; + A78B87732BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */; }; + A78B87742BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */; }; A795069C2B974C8200AC4814 /* SessionReplay+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A795069B2B974C8100AC4814 /* SessionReplay+objc.swift */; }; A79B0F64292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */; }; A79B0F65292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */; }; @@ -592,8 +594,8 @@ A7B932FC2B1F6A0A00AE6477 /* SRDataModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B932F82B1F6A0A00AE6477 /* SRDataModels.swift */; }; A7B932FD2B1F6A0A00AE6477 /* EnrichedResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B932F92B1F6A0A00AE6477 /* EnrichedResource.swift */; }; A7B932FE2B1F6A0A00AE6477 /* SRDataModels+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B932FA2B1F6A0A00AE6477 /* SRDataModels+UIKit.swift */; }; - A7C816AB2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C816AA2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift */; }; - A7C816AC2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C816AA2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift */; }; + A7C816AB2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */; }; + A7C816AC2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */; }; A7D9528A2B28BD94004C79B1 /* ResourceProcessorSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D952892B28BD94004C79B1 /* ResourceProcessorSpy.swift */; }; A7D9528C2B28C18D004C79B1 /* ResourceProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D9528B2B28C18D004C79B1 /* ResourceProcessorTests.swift */; }; A7DA18042AB0C91200F76337 /* DDUIKitRUMViewsPredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DA18022AB0C8A700F76337 /* DDUIKitRUMViewsPredicateTests.swift */; }; @@ -2563,6 +2565,7 @@ A74A72842B10CC6700771FEB /* ResourceRequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceRequestBuilderTests.swift; sourceTree = ""; }; A74A72862B10CE4100771FEB /* ResourceMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceMocks.swift; sourceTree = ""; }; A74A72882B10D95D00771FEB /* MultipartBuilderSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartBuilderSpy.swift; sourceTree = ""; }; + A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; A795069B2B974C8100AC4814 /* SessionReplay+objc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SessionReplay+objc.swift"; sourceTree = ""; }; A795069D2B974CAA00AC4814 /* DDSessionReplay+apiTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "DDSessionReplay+apiTests.m"; sourceTree = ""; }; A79B0F5A292B7C06008742B3 /* B3HTTPHeadersWriterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = B3HTTPHeadersWriterTests.swift; sourceTree = ""; }; @@ -2574,7 +2577,7 @@ A7B932F82B1F6A0A00AE6477 /* SRDataModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SRDataModels.swift; sourceTree = ""; }; A7B932F92B1F6A0A00AE6477 /* EnrichedResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnrichedResource.swift; sourceTree = ""; }; A7B932FA2B1F6A0A00AE6477 /* SRDataModels+UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SRDataModels+UIKit.swift"; sourceTree = ""; }; - A7C816AA2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; + A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; A7D952892B28BD94004C79B1 /* ResourceProcessorSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceProcessorSpy.swift; sourceTree = ""; }; A7D9528B2B28C18D004C79B1 /* ResourceProcessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceProcessorTests.swift; sourceTree = ""; }; A7DA18022AB0C8A700F76337 /* DDUIKitRUMViewsPredicateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDUIKitRUMViewsPredicateTests.swift; sourceTree = ""; }; @@ -4134,7 +4137,8 @@ 61133C322423990D00786299 /* DataUploaderTests.swift */, 61133C342423990D00786299 /* URLSessionClientTests.swift */, 61133C332423990D00786299 /* RequestBuilderTests.swift */, - A7C816AA2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift */, + A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */, + A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */, ); path = Upload; sourceTree = ""; @@ -7723,7 +7727,7 @@ 61B8BA91281812F60068AFF4 /* KronosInternetAddressTests.swift in Sources */, 614798962A459AA80095CB02 /* DDTraceTests.swift in Sources */, D25085102976E30000E931C3 /* DatadogRemoteFeatureMock.swift in Sources */, - A7C816AB2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift in Sources */, + A7C816AB2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */, 6167E6DD2B811A8300C3CA2D /* AppHangsMonitoringTests.swift in Sources */, 612C13D02AA772FA0086B5D1 /* SRRequestMatcher.swift in Sources */, 61A1A44929643254007909E7 /* DatadogCoreProxy.swift in Sources */, @@ -7855,6 +7859,7 @@ 614B78F1296D7B63009C6B92 /* LowPowerModePublisherTests.swift in Sources */, 61F2724925C943C500D54BF8 /* CrashReporterTests.swift in Sources */, 61F930C52BA1C4EB005F0EE2 /* TLVBlockReaderTests.swift in Sources */, + A78B87732BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */, 6172472725D673D7007085B3 /* CrashContextTests.swift in Sources */, 61A2CC242A44454D0000FF25 /* DDRUMTests.swift in Sources */, D2A1EE26287C35DE00D28DFB /* ContextValueReaderMock.swift in Sources */, @@ -8933,7 +8938,7 @@ D24C9C7229A7D57A002057CF /* DirectoriesMock.swift in Sources */, 61DA8CB3286215DE0074A606 /* CryptographyTests.swift in Sources */, D2CB6F0427C520D400A62B57 /* DDTracerTests.swift in Sources */, - A7C816AC2A98CEBA00BF097B /* UIKitBackgroundTaskCoordinatorTests.swift in Sources */, + A7C816AC2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */, D24C9C6129A7CB0C002057CF /* DatadogLogsFeatureTests.swift in Sources */, D29A9FCF29DDC4BC005C54A4 /* RUMFeatureMocks.swift in Sources */, D22743DE29DEB8B5001A7EF9 /* VitalInfoSamplerTests.swift in Sources */, @@ -8976,6 +8981,7 @@ D2CB6F3027C520D400A62B57 /* DatadogExtensions.swift in Sources */, D2CB6F3227C520D400A62B57 /* JSONDataMatcher.swift in Sources */, 6136CB4B2A69C29C00AC265D /* FilesOrchestrator+MetricsTests.swift in Sources */, + A78B87742BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */, D25085112976E30000E931C3 /* DatadogRemoteFeatureMock.swift in Sources */, D2CB6F3327C520D400A62B57 /* FilesOrchestratorTests.swift in Sources */, D2FB1258292E0F10005B13F8 /* TrackingConsentPublisherTests.swift in Sources */, diff --git a/DatadogCore/Sources/Core/DatadogCore.swift b/DatadogCore/Sources/Core/DatadogCore.swift index b483ad99f2..98c80e516d 100644 --- a/DatadogCore/Sources/Core/DatadogCore.swift +++ b/DatadogCore/Sources/Core/DatadogCore.swift @@ -96,7 +96,7 @@ internal final class DatadogCore { applicationVersion: String, maxBatchesPerUpload: Int, backgroundTasksEnabled: Bool, - isRunFromExtension: Bool + isRunFromExtension: Bool = false ) { self.directory = directory self.dateProvider = dateProvider diff --git a/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift b/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift index 38d9a063b4..90b1adbabb 100644 --- a/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift +++ b/DatadogCore/Sources/Core/Upload/BackgroundTaskCoordinator.swift @@ -61,28 +61,36 @@ internal class AppBackgroundTaskCoordinator: BackgroundTaskCoordinator { } } +/// Bridge protocol that matches `UIApplication` interface for background tasks. Allows easier testablity. +internal protocol ProcessInfoActivityCoordinator { + func beginActivity(options: ProcessInfo.ActivityOptions, reason: String) -> any NSObjectProtocol + func endActivity(_ activity: any NSObjectProtocol) +} + +extension ProcessInfo: ProcessInfoActivityCoordinator {} + internal class ExtensionBackgroundTaskCoordinator: BackgroundTaskCoordinator { - private let processInfo: ProcessInfo + private let processInfo: ProcessInfoActivityCoordinator @ReadWriteLock private var currentActivity: NSObjectProtocol? internal init( - processInfo: ProcessInfo = .init() + processInfo: ProcessInfoActivityCoordinator = ProcessInfo() ) { self.processInfo = processInfo } internal func beginBackgroundTask() { endBackgroundTask() - currentActivity = processInfo.beginActivity(options: [.background], reason: "Datadog background upload") + currentActivity = processInfo.beginActivity(options: [.background], reason: "Datadog SDK background upload") } internal func endBackgroundTask() { guard let currentActivity = currentActivity else { return } - ProcessInfo().endActivity(currentActivity) + processInfo.endActivity(currentActivity) self.currentActivity = nil } } diff --git a/DatadogCore/Tests/Datadog/Core/DirectoriesTests.swift b/DatadogCore/Tests/Datadog/Core/DirectoriesTests.swift index 42a110fd1d..3cb2b68ac4 100644 --- a/DatadogCore/Tests/Datadog/Core/DirectoriesTests.swift +++ b/DatadogCore/Tests/Datadog/Core/DirectoriesTests.swift @@ -43,7 +43,7 @@ class DirectoriesTests: XCTestCase { let coreDirectories = try fixtures.map { instancenName, site, _ in try CoreDirectory( in: directory, - instancenName: instancenName, + instanceName: instancenName, site: site ) } @@ -65,7 +65,7 @@ class DirectoriesTests: XCTestCase { let coreDirectories = try (0..<50).map { index in try CoreDirectory( in: directory, - instancenName: .mockRandom(among: .alphanumerics, length: 31) + "\(index)", + instanceName: .mockRandom(among: .alphanumerics, length: 31) + "\(index)", site: .mockRandom() ) } diff --git a/DatadogCore/Tests/Datadog/Core/Upload/UIKitBackgroundTaskCoordinatorTests.swift b/DatadogCore/Tests/Datadog/Core/Upload/AppBackgroundTaskCoordinatorTests.swift similarity index 92% rename from DatadogCore/Tests/Datadog/Core/Upload/UIKitBackgroundTaskCoordinatorTests.swift rename to DatadogCore/Tests/Datadog/Core/Upload/AppBackgroundTaskCoordinatorTests.swift index c827f48b67..49d358f0ac 100644 --- a/DatadogCore/Tests/Datadog/Core/Upload/UIKitBackgroundTaskCoordinatorTests.swift +++ b/DatadogCore/Tests/Datadog/Core/Upload/AppBackgroundTaskCoordinatorTests.swift @@ -8,14 +8,14 @@ import XCTest import DatadogInternal @testable import DatadogCore -class UIKitBackgroundTaskCoordinatorTests: XCTestCase { +class AppBackgroundTaskCoordinatorTests: XCTestCase { var appSpy: AppSpy? - var coordinator: UIKitBackgroundTaskCoordinator? + var coordinator: AppBackgroundTaskCoordinator? override func setUp() { super.setUp() appSpy = AppSpy() - coordinator = UIKitBackgroundTaskCoordinator( + coordinator = AppBackgroundTaskCoordinator( app: appSpy ) } diff --git a/DatadogCore/Tests/Datadog/Core/Upload/ExtensionBackgroundTaskCoordinatorTests.swift b/DatadogCore/Tests/Datadog/Core/Upload/ExtensionBackgroundTaskCoordinatorTests.swift new file mode 100644 index 0000000000..ca31127a20 --- /dev/null +++ b/DatadogCore/Tests/Datadog/Core/Upload/ExtensionBackgroundTaskCoordinatorTests.swift @@ -0,0 +1,66 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + */ + +import XCTest +import DatadogInternal +@testable import DatadogCore + +class ExtensionBackgroundTaskCoordinatorTests: XCTestCase { + var processInfoSpy: ProcessInfoSpy! // swiftlint:disable:this implicitly_unwrapped_optional + var coordinator: ExtensionBackgroundTaskCoordinator! // swiftlint:disable:this implicitly_unwrapped_optional + + override func setUp() { + super.setUp() + processInfoSpy = ProcessInfoSpy() + coordinator = ExtensionBackgroundTaskCoordinator( + processInfo: processInfoSpy + ) + } + + func testBeginBackgroundTask() { + coordinator?.beginBackgroundTask() + + XCTAssertEqual(processInfoSpy?.beginBackgroundTaskCalled, true) + XCTAssertEqual(processInfoSpy?.endBackgroundTaskCalled, false) + } + + func testEndBackgroundTask() throws { + coordinator?.beginBackgroundTask() + coordinator?.endBackgroundTask() + + XCTAssertEqual(processInfoSpy?.beginBackgroundTaskCalled, true) + XCTAssertEqual(processInfoSpy?.endBackgroundTaskCalled, true) + } + + func testEndBackgroundTaskNotCalledWhenNotBegan() throws { + coordinator?.endBackgroundTask() + + XCTAssertEqual(processInfoSpy?.beginBackgroundTaskCalled, false) + XCTAssertEqual(processInfoSpy?.endBackgroundTaskCalled, false) + } + + func testBeginEndsPreviousTask() throws { + coordinator?.beginBackgroundTask() + coordinator?.beginBackgroundTask() + + XCTAssertEqual(processInfoSpy?.beginBackgroundTaskCalled, true) + XCTAssertEqual(processInfoSpy?.endBackgroundTaskCalled, true) + } +} + +class ProcessInfoSpy: ProcessInfoActivityCoordinator { + var beginBackgroundTaskCalled = false + var endBackgroundTaskCalled = false + + func beginActivity(options: ProcessInfo.ActivityOptions, reason: String) -> any NSObjectProtocol { + beginBackgroundTaskCalled = true + return NSObject() + } + + func endActivity(_ activity: any NSObjectProtocol) { + endBackgroundTaskCalled = true + } +} From 23bc3dfe8d2026a0a907b165092f390cc3a04b8a Mon Sep 17 00:00:00 2001 From: Maciej Burda Date: Mon, 6 May 2024 16:13:08 +0100 Subject: [PATCH 3/6] RUM-3284 Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a67e511c7c..a560373eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ # 2.10.1 / 02-05-2024 - [FIX] Use trace and span id as decimal. See [#1807][] +- [FIX] Add background upload capability to extensions in order to mitigate `0xdead10cc` crash. See [#1803][] # 2.10.0 / 23-04-2024 @@ -655,6 +656,7 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO [#1798]: https://github.com/DataDog/dd-sdk-ios/pull/1798 [#1776]: https://github.com/DataDog/dd-sdk-ios/pull/1776 [#1721]: https://github.com/DataDog/dd-sdk-ios/pull/1721 +[#1803]: https://github.com/DataDog/dd-sdk-ios/pull/1803 [#1807]: https://github.com/DataDog/dd-sdk-ios/pull/1807 [@00fa9a]: https://github.com/00FA9A [@britton-earnin]: https://github.com/Britton-Earnin From 08ff6dd5d4171ca9d227f683aa1ff0e8ac23a164 Mon Sep 17 00:00:00 2001 From: Maciej Burda Date: Wed, 8 May 2024 10:44:51 +0100 Subject: [PATCH 4/6] Update DatadogCore/Sources/Core/Storage/Directories.swift Co-authored-by: Maciek Grzybowski --- DatadogCore/Sources/Core/Storage/Directories.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DatadogCore/Sources/Core/Storage/Directories.swift b/DatadogCore/Sources/Core/Storage/Directories.swift index 05bfe74870..22282515cb 100644 --- a/DatadogCore/Sources/Core/Storage/Directories.swift +++ b/DatadogCore/Sources/Core/Storage/Directories.swift @@ -42,7 +42,7 @@ internal extension CoreDirectory { /// /// - Parameters: /// - osDirectory: the root OS directory (`/Library/Caches`) to create core directory inside. - /// - instancenName: The core instance name. + /// - instanceName: The core instance name. /// - site: The cor instance site. init(in osDirectory: Directory, instanceName: String, site: DatadogSite) throws { let sdkInstanceUUID = sha256("\(instanceName)\(site)") From 1c2c466746237b519bc4b84573aeaf0083e46c96 Mon Sep 17 00:00:00 2001 From: Maciej Burda Date: Wed, 8 May 2024 12:21:36 +0100 Subject: [PATCH 5/6] RUM-3284 Fix after rebase --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a560373eb1..5301103f2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,11 @@ - [FEATURE] Support WebView recording in Session Replay. See [#1776][] - [IMPROVEMENT] Add `isInitialized` and `stopInstance` methods to ObjC API. See [#1800][] - [IMPROVEMENT] Add `addUserExtraInfo` method to ObjC API. See [#1799][] +- [FIX] Add background upload capability to extensions in order to mitigate `0xdead10cc` crash. See [#1803][] # 2.10.1 / 02-05-2024 - [FIX] Use trace and span id as decimal. See [#1807][] -- [FIX] Add background upload capability to extensions in order to mitigate `0xdead10cc` crash. See [#1803][] # 2.10.0 / 23-04-2024 From a14f506afed7bd519f9e4dc0cf4d75e6cea122ff Mon Sep 17 00:00:00 2001 From: Maciej Burda Date: Wed, 8 May 2024 14:17:43 +0100 Subject: [PATCH 6/6] RUM-3284 Clean up after rebase --- Datadog/Datadog.xcodeproj/project.pbxproj | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Datadog/Datadog.xcodeproj/project.pbxproj b/Datadog/Datadog.xcodeproj/project.pbxproj index baa78fe3b1..407bcaca8e 100644 --- a/Datadog/Datadog.xcodeproj/project.pbxproj +++ b/Datadog/Datadog.xcodeproj/project.pbxproj @@ -582,8 +582,6 @@ A74A72852B10CC6700771FEB /* ResourceRequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74A72842B10CC6700771FEB /* ResourceRequestBuilderTests.swift */; }; A74A72872B10CE4100771FEB /* ResourceMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74A72862B10CE4100771FEB /* ResourceMocks.swift */; }; A74A72892B10D95D00771FEB /* MultipartBuilderSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74A72882B10D95D00771FEB /* MultipartBuilderSpy.swift */; }; - A78B87732BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */; }; - A78B87742BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */; }; A795069C2B974C8200AC4814 /* SessionReplay+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A795069B2B974C8100AC4814 /* SessionReplay+objc.swift */; }; A79B0F64292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */; }; A79B0F65292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */; }; @@ -594,8 +592,10 @@ A7B932FC2B1F6A0A00AE6477 /* SRDataModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B932F82B1F6A0A00AE6477 /* SRDataModels.swift */; }; A7B932FD2B1F6A0A00AE6477 /* EnrichedResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B932F92B1F6A0A00AE6477 /* EnrichedResource.swift */; }; A7B932FE2B1F6A0A00AE6477 /* SRDataModels+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B932FA2B1F6A0A00AE6477 /* SRDataModels+UIKit.swift */; }; - A7C816AB2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */; }; - A7C816AC2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */; }; + A7CA21802BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA217F2BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift */; }; + A7CA21812BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA217F2BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift */; }; + A7CA21832BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA21822BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift */; }; + A7CA21842BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA21822BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift */; }; A7D9528A2B28BD94004C79B1 /* ResourceProcessorSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D952892B28BD94004C79B1 /* ResourceProcessorSpy.swift */; }; A7D9528C2B28C18D004C79B1 /* ResourceProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D9528B2B28C18D004C79B1 /* ResourceProcessorTests.swift */; }; A7DA18042AB0C91200F76337 /* DDUIKitRUMViewsPredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DA18022AB0C8A700F76337 /* DDUIKitRUMViewsPredicateTests.swift */; }; @@ -2565,7 +2565,6 @@ A74A72842B10CC6700771FEB /* ResourceRequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceRequestBuilderTests.swift; sourceTree = ""; }; A74A72862B10CE4100771FEB /* ResourceMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceMocks.swift; sourceTree = ""; }; A74A72882B10D95D00771FEB /* MultipartBuilderSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartBuilderSpy.swift; sourceTree = ""; }; - A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; A795069B2B974C8100AC4814 /* SessionReplay+objc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SessionReplay+objc.swift"; sourceTree = ""; }; A795069D2B974CAA00AC4814 /* DDSessionReplay+apiTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "DDSessionReplay+apiTests.m"; sourceTree = ""; }; A79B0F5A292B7C06008742B3 /* B3HTTPHeadersWriterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = B3HTTPHeadersWriterTests.swift; sourceTree = ""; }; @@ -2577,7 +2576,8 @@ A7B932F82B1F6A0A00AE6477 /* SRDataModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SRDataModels.swift; sourceTree = ""; }; A7B932F92B1F6A0A00AE6477 /* EnrichedResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnrichedResource.swift; sourceTree = ""; }; A7B932FA2B1F6A0A00AE6477 /* SRDataModels+UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SRDataModels+UIKit.swift"; sourceTree = ""; }; - A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; + A7CA217F2BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; + A7CA21822BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionBackgroundTaskCoordinatorTests.swift; sourceTree = ""; }; A7D952892B28BD94004C79B1 /* ResourceProcessorSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceProcessorSpy.swift; sourceTree = ""; }; A7D9528B2B28C18D004C79B1 /* ResourceProcessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceProcessorTests.swift; sourceTree = ""; }; A7DA18022AB0C8A700F76337 /* DDUIKitRUMViewsPredicateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDUIKitRUMViewsPredicateTests.swift; sourceTree = ""; }; @@ -4130,6 +4130,8 @@ 61133C2E2423990D00786299 /* Upload */ = { isa = PBXGroup; children = ( + A7CA21822BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift */, + A7CA217F2BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift */, 61133C2F2423990D00786299 /* DataUploadWorkerTests.swift */, 61133C302423990D00786299 /* DataUploadConditionsTests.swift */, 61133C312423990D00786299 /* DataUploadDelayTests.swift */, @@ -4137,8 +4139,6 @@ 61133C322423990D00786299 /* DataUploaderTests.swift */, 61133C342423990D00786299 /* URLSessionClientTests.swift */, 61133C332423990D00786299 /* RequestBuilderTests.swift */, - A7C816AA2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift */, - A78B87722BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift */, ); path = Upload; sourceTree = ""; @@ -7727,7 +7727,6 @@ 61B8BA91281812F60068AFF4 /* KronosInternetAddressTests.swift in Sources */, 614798962A459AA80095CB02 /* DDTraceTests.swift in Sources */, D25085102976E30000E931C3 /* DatadogRemoteFeatureMock.swift in Sources */, - A7C816AB2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */, 6167E6DD2B811A8300C3CA2D /* AppHangsMonitoringTests.swift in Sources */, 612C13D02AA772FA0086B5D1 /* SRRequestMatcher.swift in Sources */, 61A1A44929643254007909E7 /* DatadogCoreProxy.swift in Sources */, @@ -7836,8 +7835,10 @@ D2B3F052282E827700C2B5EE /* DDHTTPHeadersWriter+apiTests.m in Sources */, D20605B92875729E0047275C /* ContextValuePublisherMock.swift in Sources */, D24C9C4D29A7BA3F002057CF /* LogsMocks.swift in Sources */, + A7CA21832BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */, 61B5E42B26DFC433000B0A5F /* DDNSURLSessionDelegate+apiTests.m in Sources */, 6167E7062B82A9FD00C3CA2D /* GeneratingBacktraceTests.swift in Sources */, + A7CA21802BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift in Sources */, D20605C52875895E0047275C /* KronosClockMock.swift in Sources */, 61133C642423990D00786299 /* LoggerTests.swift in Sources */, 6134CDB12A691E850061CCD9 /* CoreMetricsTests.swift in Sources */, @@ -7859,7 +7860,6 @@ 614B78F1296D7B63009C6B92 /* LowPowerModePublisherTests.swift in Sources */, 61F2724925C943C500D54BF8 /* CrashReporterTests.swift in Sources */, 61F930C52BA1C4EB005F0EE2 /* TLVBlockReaderTests.swift in Sources */, - A78B87732BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */, 6172472725D673D7007085B3 /* CrashContextTests.swift in Sources */, 61A2CC242A44454D0000FF25 /* DDRUMTests.swift in Sources */, D2A1EE26287C35DE00D28DFB /* ContextValueReaderMock.swift in Sources */, @@ -8938,7 +8938,6 @@ D24C9C7229A7D57A002057CF /* DirectoriesMock.swift in Sources */, 61DA8CB3286215DE0074A606 /* CryptographyTests.swift in Sources */, D2CB6F0427C520D400A62B57 /* DDTracerTests.swift in Sources */, - A7C816AC2A98CEBA00BF097B /* AppBackgroundTaskCoordinatorTests.swift in Sources */, D24C9C6129A7CB0C002057CF /* DatadogLogsFeatureTests.swift in Sources */, D29A9FCF29DDC4BC005C54A4 /* RUMFeatureMocks.swift in Sources */, D22743DE29DEB8B5001A7EF9 /* VitalInfoSamplerTests.swift in Sources */, @@ -8981,8 +8980,8 @@ D2CB6F3027C520D400A62B57 /* DatadogExtensions.swift in Sources */, D2CB6F3227C520D400A62B57 /* JSONDataMatcher.swift in Sources */, 6136CB4B2A69C29C00AC265D /* FilesOrchestrator+MetricsTests.swift in Sources */, - A78B87742BDC015C00135F78 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */, D25085112976E30000E931C3 /* DatadogRemoteFeatureMock.swift in Sources */, + A7CA21842BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */, D2CB6F3327C520D400A62B57 /* FilesOrchestratorTests.swift in Sources */, D2FB1258292E0F10005B13F8 /* TrackingConsentPublisherTests.swift in Sources */, D2CB6F3B27C520D400A62B57 /* NSURLSessionBridge.m in Sources */, @@ -9003,6 +9002,7 @@ D22743EC29DEC9E6001A7EF9 /* Casting+RUM.swift in Sources */, D2CB6F4D27C520D400A62B57 /* DataUploadStatusTests.swift in Sources */, D2CB6F4F27C520D400A62B57 /* RetryingTests.swift in Sources */, + A7CA21812BEBB1E800732571 /* AppBackgroundTaskCoordinatorTests.swift in Sources */, D2CB6F5027C520D400A62B57 /* DDDatadogTests.swift in Sources */, D2B3F0452823EE8400C2B5EE /* TLVBlockTests.swift in Sources */, D2CB6F5327C520D400A62B57 /* DirectoryTests.swift in Sources */,