From 1a71dc07bbe9b2d061312cf097c314d238924451 Mon Sep 17 00:00:00 2001 From: Xavier Gouchet Date: Thu, 8 Jul 2021 09:25:53 +0200 Subject: [PATCH] RUMM-1269 Add configuration to enable/disable background RUM events --- .../Datadog/Core/FeaturesConfiguration.swift | 4 +- Sources/Datadog/DatadogConfiguration.swift | 16 +++++ .../Scopes/RUMApplicationScope.swift | 10 ++- .../RUMMonitor/Scopes/RUMSessionScope.swift | 12 +++- Sources/Datadog/RUMMonitor.swift | 3 +- .../DatadogConfigurationBuilderTests.swift | 4 ++ .../Datadog/Mocks/CoreMocks.swift | 8 ++- .../Datadog/Mocks/RUMFeatureMocks.swift | 12 ++-- .../RUM/Debugging/RUMDebuggingTests.swift | 6 +- .../RUMContext/RUMCurrentContextTests.swift | 12 ++-- .../Scopes/RUMApplicationScopeTests.swift | 16 ++--- .../Scopes/RUMSessionScopeTests.swift | 63 ++++++++++++++----- 12 files changed, 123 insertions(+), 43 deletions(-) diff --git a/Sources/Datadog/Core/FeaturesConfiguration.swift b/Sources/Datadog/Core/FeaturesConfiguration.swift index 052fb55049..7cbd733c93 100644 --- a/Sources/Datadog/Core/FeaturesConfiguration.swift +++ b/Sources/Datadog/Core/FeaturesConfiguration.swift @@ -48,6 +48,7 @@ internal struct FeaturesConfiguration { let errorEventMapper: RUMErrorEventMapper? /// RUM auto instrumentation configuration, `nil` if not enabled. let autoInstrumentation: AutoInstrumentation? + let backgroundEventTrackingEnabled: Bool } struct URLSessionAutoInstrumentation { @@ -197,7 +198,8 @@ extension FeaturesConfiguration { resourceEventMapper: configuration.rumResourceEventMapper, actionEventMapper: configuration.rumActionEventMapper, errorEventMapper: configuration.rumErrorEventMapper, - autoInstrumentation: autoInstrumentation + autoInstrumentation: autoInstrumentation, + backgroundEventTrackingEnabled: configuration.rumBackgroundEventTrackingEnabled ) } else { let error = ProgrammerError( diff --git a/Sources/Datadog/DatadogConfiguration.swift b/Sources/Datadog/DatadogConfiguration.swift index b0dafa676f..9b9605b023 100644 --- a/Sources/Datadog/DatadogConfiguration.swift +++ b/Sources/Datadog/DatadogConfiguration.swift @@ -264,6 +264,7 @@ extension Datadog { private(set) var rumActionEventMapper: RUMActionEventMapper? private(set) var rumErrorEventMapper: RUMErrorEventMapper? private(set) var rumResourceAttributesProvider: URLSessionRUMAttributesProvider? + private(set) var rumBackgroundEventTrackingEnabled: Bool private(set) var batchSize: BatchSize private(set) var uploadFrequency: UploadFrequency private(set) var additionalConfiguration: [String: Any] @@ -335,6 +336,7 @@ extension Datadog { rumActionEventMapper: nil, rumErrorEventMapper: nil, rumResourceAttributesProvider: nil, + rumBackgroundEventTrackingEnabled: false, batchSize: .medium, uploadFrequency: .average, additionalConfiguration: [:], @@ -613,6 +615,20 @@ extension Datadog { return self } + /// Enables or disables automatic tracking of background events (events hapenning when no UIViewController is active). + /// + /// When enabled, the SDK will track RUM Events into an automatically created Background RUM View (named `Background`) + /// + /// **NOTE:** Enabling this option might increase the number of session tracked, and increase your billing. + /// + /// Until this option is enabled, automatic tracking of background event is disabled. + /// + /// - Parameter enabled: `true` by default + public func trackBackgroundEvents(_ enabled: Bool = true) -> Builder { + configuration.rumBackgroundEventTrackingEnabled = enabled + return self + } + #if DD_SDK_ENABLE_EXPERIMENTAL_APIS // MARK: - Crash Reporting Configuration diff --git a/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScope.swift b/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScope.swift index 55634a6460..dd13da288d 100644 --- a/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScope.swift +++ b/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScope.swift @@ -27,6 +27,9 @@ internal class RUMApplicationScope: RUMScope, RUMContextProvider { /// RUM Sessions sampling rate. internal let samplingRate: Float + /// Automatically detect background events + internal let backgroundEventTrackingEnabled: Bool + // MARK: - Initialization let dependencies: RUMScopeDependencies @@ -34,10 +37,12 @@ internal class RUMApplicationScope: RUMScope, RUMContextProvider { init( rumApplicationID: String, dependencies: RUMScopeDependencies, - samplingRate: Float + samplingRate: Float, + backgroundEventTrackingEnabled: Bool ) { self.dependencies = dependencies self.samplingRate = samplingRate + self.backgroundEventTrackingEnabled = backgroundEventTrackingEnabled self.context = RUMContext( rumApplicationID: rumApplicationID, sessionID: .nullUUID, @@ -89,7 +94,8 @@ internal class RUMApplicationScope: RUMScope, RUMContextProvider { parent: self, dependencies: dependencies, samplingRate: samplingRate, - startTime: command.time + startTime: command.time, + backgroundEventTrackingEnabled: backgroundEventTrackingEnabled ) sessionScope = initialSession diff --git a/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScope.swift b/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScope.swift index f8bfc15460..350ae9e95b 100644 --- a/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScope.swift +++ b/Sources/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScope.swift @@ -25,6 +25,9 @@ internal class RUMSessionScope: RUMScope, RUMContextProvider { unowned let parent: RUMContextProvider private let dependencies: RUMScopeDependencies + /// Automatically detect background events + internal let backgroundEventTrackingEnabled: Bool + /// This Session UUID. Equals `.nullUUID` if the Session is sampled. let sessionUUID: RUMUUID /// RUM Session sampling rate. @@ -40,7 +43,8 @@ internal class RUMSessionScope: RUMScope, RUMContextProvider { parent: RUMContextProvider, dependencies: RUMScopeDependencies, samplingRate: Float, - startTime: Date + startTime: Date, + backgroundEventTrackingEnabled: Bool ) { self.parent = parent self.dependencies = dependencies @@ -49,6 +53,7 @@ internal class RUMSessionScope: RUMScope, RUMContextProvider { self.sessionUUID = shouldBeSampledOut ? .nullUUID : dependencies.rumUUIDGenerator.generateUnique() self.sessionStartTime = startTime self.lastInteractionTime = startTime + self.backgroundEventTrackingEnabled = backgroundEventTrackingEnabled } /// Creates a new Session upon expiration of the previous one. @@ -60,7 +65,8 @@ internal class RUMSessionScope: RUMScope, RUMContextProvider { parent: expiredSession.parent, dependencies: expiredSession.dependencies, samplingRate: expiredSession.samplingRate, - startTime: startTime + startTime: startTime, + backgroundEventTrackingEnabled: expiredSession.backgroundEventTrackingEnabled ) // Transfer active Views by creating new `RUMViewScopes` for their identity objects: @@ -136,7 +142,7 @@ internal class RUMSessionScope: RUMScope, RUMContextProvider { // MARK: - Private private func handleOrphanStartCommand(command: RUMCommand) { - if viewScopes.isEmpty { + if viewScopes.isEmpty && backgroundEventTrackingEnabled { viewScopes.append( RUMViewScope( parent: self, diff --git a/Sources/Datadog/RUMMonitor.swift b/Sources/Datadog/RUMMonitor.swift index 5ae7b52c4d..68ba17e305 100644 --- a/Sources/Datadog/RUMMonitor.swift +++ b/Sources/Datadog/RUMMonitor.swift @@ -185,7 +185,8 @@ public class RUMMonitor: DDRUMMonitor, RUMCommandSubscriber { rumUUIDGenerator: DefaultRUMUUIDGenerator(), dateCorrector: rumFeature.dateCorrector ), - samplingRate: rumFeature.configuration.sessionSamplingRate + samplingRate: rumFeature.configuration.sessionSamplingRate, + backgroundEventTrackingEnabled: rumFeature.configuration.backgroundEventTrackingEnabled ), dateProvider: rumFeature.dateProvider ) diff --git a/Tests/DatadogTests/Datadog/DatadogConfigurationBuilderTests.swift b/Tests/DatadogTests/Datadog/DatadogConfigurationBuilderTests.swift index 40812a72c2..e40d2a3349 100644 --- a/Tests/DatadogTests/Datadog/DatadogConfigurationBuilderTests.swift +++ b/Tests/DatadogTests/Datadog/DatadogConfigurationBuilderTests.swift @@ -82,6 +82,7 @@ class DatadogConfigurationBuilderTests: XCTestCase { .trackURLSession(firstPartyHosts: ["example.com"]) .trackUIKitRUMViews(using: UIKitRUMViewsPredicateMock()) .trackUIKitActions(false) + .trackBackgroundEvents(false) .setRUMViewEventMapper { _ in mockRUMViewEvent } .setRUMErrorEventMapper { _ in mockRUMErrorEvent } .setRUMResourceEventMapper { _ in mockRUMResourceEvent } @@ -102,6 +103,7 @@ class DatadogConfigurationBuilderTests: XCTestCase { .builderUsing(rumApplicationID: "rum-app-id", clientToken: "abc-123", environment: "tests") .trackUIKitRUMViews() .trackUIKitActions() + .trackBackgroundEvents() let configuration = customized(defaultBuilder).build() let rumConfiguration = customized(defaultRUMBuilder).build() @@ -132,6 +134,7 @@ class DatadogConfigurationBuilderTests: XCTestCase { XCTAssertEqual(configuration.rumActionEventMapper?(.mockRandom()), mockRUMActionEvent) XCTAssertEqual(configuration.rumErrorEventMapper?(.mockRandom()), mockRUMErrorEvent) XCTAssertEqual(configuration.rumResourceAttributesProvider?(.mockAny(), nil, nil, nil) as? [String: String], ["foo": "bar"]) + XCTAssertFalse(configuration.rumBackgroundEventTrackingEnabled) XCTAssertEqual(configuration.batchSize, .small) XCTAssertEqual(configuration.uploadFrequency, .frequent) XCTAssertEqual(configuration.additionalConfiguration["foo"] as? Int, 42) @@ -140,6 +143,7 @@ class DatadogConfigurationBuilderTests: XCTestCase { XCTAssertTrue(rumConfigurationWithDefaultValues.rumUIKitViewsPredicate is DefaultUIKitRUMViewsPredicate) XCTAssertTrue(rumConfigurationWithDefaultValues.rumUIKitActionsTrackingEnabled) + XCTAssertTrue(rumConfigurationWithDefaultValues.rumBackgroundEventTrackingEnabled) } func testDeprecatedAPIs() { diff --git a/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift b/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift index 418476debc..6005be7b04 100644 --- a/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift +++ b/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift @@ -53,6 +53,7 @@ extension Datadog.Configuration { rumUIKitViewsPredicate: UIKitRUMViewsPredicate? = nil, rumUIKitActionsTrackingEnabled: Bool = false, rumResourceAttributesProvider: URLSessionRUMAttributesProvider? = nil, + rumBackgroundEventTrackingEnabled: Bool = false, batchSize: BatchSize = .medium, uploadFrequency: UploadFrequency = .average, additionalConfiguration: [String: Any] = [:], @@ -79,6 +80,7 @@ extension Datadog.Configuration { rumUIKitViewsPredicate: rumUIKitViewsPredicate, rumUIKitActionsTrackingEnabled: rumUIKitActionsTrackingEnabled, rumResourceAttributesProvider: rumResourceAttributesProvider, + rumBackgroundEventTrackingEnabled: rumBackgroundEventTrackingEnabled, batchSize: batchSize, uploadFrequency: uploadFrequency, additionalConfiguration: additionalConfiguration, @@ -222,7 +224,8 @@ extension FeaturesConfiguration.RUM { resourceEventMapper: RUMResourceEventMapper? = nil, actionEventMapper: RUMActionEventMapper? = nil, errorEventMapper: RUMErrorEventMapper? = nil, - autoInstrumentation: FeaturesConfiguration.RUM.AutoInstrumentation? = nil + autoInstrumentation: FeaturesConfiguration.RUM.AutoInstrumentation? = nil, + backgroundEventTrackingEnabled: Bool = false ) -> Self { return .init( common: common, @@ -233,7 +236,8 @@ extension FeaturesConfiguration.RUM { resourceEventMapper: resourceEventMapper, actionEventMapper: actionEventMapper, errorEventMapper: errorEventMapper, - autoInstrumentation: autoInstrumentation + autoInstrumentation: autoInstrumentation, + backgroundEventTrackingEnabled: backgroundEventTrackingEnabled ) } } diff --git a/Tests/DatadogTests/Datadog/Mocks/RUMFeatureMocks.swift b/Tests/DatadogTests/Datadog/Mocks/RUMFeatureMocks.swift index 5274e82db3..44c3cd841f 100644 --- a/Tests/DatadogTests/Datadog/Mocks/RUMFeatureMocks.swift +++ b/Tests/DatadogTests/Datadog/Mocks/RUMFeatureMocks.swift @@ -453,12 +453,14 @@ extension RUMApplicationScope { static func mockWith( rumApplicationID: String = .mockAny(), dependencies: RUMScopeDependencies = .mockAny(), - samplingRate: Float = 100 + samplingRate: Float = 100, + backgroundEventTrackingEnabled: Bool = .mockAny() ) -> RUMApplicationScope { return RUMApplicationScope( rumApplicationID: rumApplicationID, dependencies: dependencies, - samplingRate: samplingRate + samplingRate: samplingRate, + backgroundEventTrackingEnabled: backgroundEventTrackingEnabled ) } } @@ -472,13 +474,15 @@ extension RUMSessionScope { parent: RUMApplicationScope = .mockAny(), dependencies: RUMScopeDependencies = .mockAny(), samplingRate: Float = 100, - startTime: Date = .mockAny() + startTime: Date = .mockAny(), + backgroundEventTrackingEnabled: Bool = .mockAny() ) -> RUMSessionScope { return RUMSessionScope( parent: parent, dependencies: dependencies, samplingRate: samplingRate, - startTime: startTime + startTime: startTime, + backgroundEventTrackingEnabled: backgroundEventTrackingEnabled ) } } diff --git a/Tests/DatadogTests/Datadog/RUM/Debugging/RUMDebuggingTests.swift b/Tests/DatadogTests/Datadog/RUM/Debugging/RUMDebuggingTests.swift index b1ab21135e..9fcd133eb8 100644 --- a/Tests/DatadogTests/Datadog/RUM/Debugging/RUMDebuggingTests.swift +++ b/Tests/DatadogTests/Datadog/RUM/Debugging/RUMDebuggingTests.swift @@ -16,7 +16,8 @@ class RUMDebuggingTests: XCTestCase { let applicationScope = RUMApplicationScope( rumApplicationID: "abc-123", dependencies: .mockAny(), - samplingRate: 100 + samplingRate: 100, + backgroundEventTrackingEnabled: .mockAny() ) _ = applicationScope.process( command: RUMStartViewCommand.mockWith(identity: mockView, name: "FirstView") @@ -47,7 +48,8 @@ class RUMDebuggingTests: XCTestCase { let applicationScope = RUMApplicationScope( rumApplicationID: "abc-123", dependencies: .mockAny(), - samplingRate: 100 + samplingRate: 100, + backgroundEventTrackingEnabled: .mockAny() ) _ = applicationScope.process( command: RUMStartViewCommand.mockWith(identity: mockView, name: "FirstView") diff --git a/Tests/DatadogTests/Datadog/RUM/RUMContext/RUMCurrentContextTests.swift b/Tests/DatadogTests/Datadog/RUM/RUMContext/RUMCurrentContextTests.swift index 6684c2e178..e1da601b29 100644 --- a/Tests/DatadogTests/Datadog/RUM/RUMContext/RUMCurrentContextTests.swift +++ b/Tests/DatadogTests/Datadog/RUM/RUMContext/RUMCurrentContextTests.swift @@ -13,7 +13,7 @@ class RUMCurrentContextTests: XCTestCase { private let queue = DispatchQueue(label: "\(#file)") func testContextAfterInitializingTheApplication() { - let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: .mockAny()) + let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: .mockAny(), backgroundEventTrackingEnabled: .mockAny()) let provider = RUMCurrentContext(applicationScope: applicationScope, queue: queue) XCTAssertEqual( @@ -30,7 +30,7 @@ class RUMCurrentContextTests: XCTestCase { } func testContextAfterStartingView() throws { - let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100) + let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) let provider = RUMCurrentContext(applicationScope: applicationScope, queue: queue) _ = applicationScope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) @@ -49,7 +49,7 @@ class RUMCurrentContextTests: XCTestCase { } func testContextWhilePendingUserAction() throws { - let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100) + let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) let provider = RUMCurrentContext(applicationScope: applicationScope, queue: queue) _ = applicationScope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) @@ -69,7 +69,7 @@ class RUMCurrentContextTests: XCTestCase { } func testContextChangeWhenNavigatingBetweenViews() throws { - let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100) + let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) let provider = RUMCurrentContext(applicationScope: applicationScope, queue: queue) let firstView = createMockViewInWindow() @@ -97,7 +97,7 @@ class RUMCurrentContextTests: XCTestCase { func testContextChangeWhenSessionIsRenewed() throws { var currentTime = Date() - let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100) + let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) let provider = RUMCurrentContext(applicationScope: applicationScope, queue: queue) let view = createMockViewInWindow() @@ -140,7 +140,7 @@ class RUMCurrentContextTests: XCTestCase { } func testContextWhenSessionIsSampled() throws { - let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 0) + let applicationScope = RUMApplicationScope(rumApplicationID: "rum-123", dependencies: .mockAny(), samplingRate: 0, backgroundEventTrackingEnabled: .mockAny()) let provider = RUMCurrentContext(applicationScope: applicationScope, queue: queue) _ = applicationScope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) diff --git a/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScopeTests.swift b/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScopeTests.swift index 59e6d2a0f2..73c80190fd 100644 --- a/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScopeTests.swift +++ b/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMApplicationScopeTests.swift @@ -12,7 +12,8 @@ class RUMApplicationScopeTests: XCTestCase { let scope = RUMApplicationScope( rumApplicationID: "abc-123", dependencies: .mockAny(), - samplingRate: .mockAny() + samplingRate: .mockAny(), + backgroundEventTrackingEnabled: .mockAny() ) XCTAssertEqual(scope.context.rumApplicationID, "abc-123") @@ -23,15 +24,16 @@ class RUMApplicationScopeTests: XCTestCase { } func testWhenFirstViewIsStarted_itStartsNewSession() { - let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: .mockAny(), samplingRate: 100) + let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) XCTAssertNil(scope.sessionScope) XCTAssertTrue(scope.process(command: RUMStartViewCommand.mockAny())) XCTAssertNotNil(scope.sessionScope) + XCTAssertEqual(scope.sessionScope?.backgroundEventTrackingEnabled, scope.backgroundEventTrackingEnabled) } func testWhenSessionExpires_itStartsANewOneAndTransfersActiveViews() throws { - let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: .mockAny(), samplingRate: 100) + let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) var currentTime = Date() let view = createMockViewInWindow() @@ -53,7 +55,7 @@ class RUMApplicationScopeTests: XCTestCase { } func testUntilSessionIsStarted_itIgnoresOtherCommands() { - let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: .mockAny(), samplingRate: 100) + let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: .mockAny(), samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) XCTAssertTrue(scope.process(command: RUMStopViewCommand.mockAny())) XCTAssertTrue(scope.process(command: RUMAddUserActionCommand.mockAny())) @@ -67,7 +69,7 @@ class RUMApplicationScopeTests: XCTestCase { let output = RUMEventOutputMock() let dependencies: RUMScopeDependencies = .mockWith(eventOutput: output) - let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: dependencies, samplingRate: 100) + let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: dependencies, samplingRate: 100, backgroundEventTrackingEnabled: .mockAny()) _ = scope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) _ = scope.process(command: RUMStopViewCommand.mockWith(identity: mockView)) @@ -79,7 +81,7 @@ class RUMApplicationScopeTests: XCTestCase { let output = RUMEventOutputMock() let dependencies: RUMScopeDependencies = .mockWith(eventOutput: output) - let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: dependencies, samplingRate: 0) + let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: dependencies, samplingRate: 0, backgroundEventTrackingEnabled: .mockAny()) _ = scope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) _ = scope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) @@ -91,7 +93,7 @@ class RUMApplicationScopeTests: XCTestCase { let output = RUMEventOutputMock() let dependencies: RUMScopeDependencies = .mockWith(eventOutput: output) - let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: dependencies, samplingRate: 50) + let scope = RUMApplicationScope(rumApplicationID: .mockAny(), dependencies: dependencies, samplingRate: 50, backgroundEventTrackingEnabled: .mockAny()) var currentTime = Date() let simulatedSessionsCount = 200 diff --git a/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScopeTests.swift b/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScopeTests.swift index 2ec0c622a7..33c0e75623 100644 --- a/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScopeTests.swift +++ b/Tests/DatadogTests/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScopeTests.swift @@ -12,7 +12,7 @@ class RUMSessionScopeTests: XCTestCase { func testDefaultContext() { let parent: RUMApplicationScope = .mockWith(rumApplicationID: "rum-123") - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: .mockAny()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: .mockAny(), backgroundEventTrackingEnabled: .mockAny()) XCTAssertEqual(scope.context.rumApplicationID, "rum-123") XCTAssertNotEqual(scope.context.sessionID, .nullUUID) @@ -23,7 +23,7 @@ class RUMSessionScopeTests: XCTestCase { func testContextWhenSessionIsSampled() { let parent: RUMApplicationScope = .mockWith(rumApplicationID: "rum-123") - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 0, startTime: .mockAny()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 0, startTime: .mockAny(), backgroundEventTrackingEnabled: .mockAny()) XCTAssertEqual(scope.context.rumApplicationID, "rum-123") XCTAssertEqual(scope.context.sessionID, .nullUUID) @@ -35,7 +35,7 @@ class RUMSessionScopeTests: XCTestCase { func testWhenSessionExceedsMaxDuration_itGetsClosed() { var currentTime = Date() let parent = RUMContextProviderMock() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 50, startTime: currentTime) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 50, startTime: currentTime, backgroundEventTrackingEnabled: .mockAny()) XCTAssertTrue(scope.process(command: RUMCommandMock(time: currentTime))) @@ -48,7 +48,7 @@ class RUMSessionScopeTests: XCTestCase { func testWhenSessionIsInactiveForCertainDuration_itGetsClosed() { var currentTime = Date() let parent = RUMContextProviderMock() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 50, startTime: currentTime) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 50, startTime: currentTime, backgroundEventTrackingEnabled: .mockAny()) XCTAssertTrue(scope.process(command: RUMCommandMock(time: currentTime))) @@ -66,7 +66,7 @@ class RUMSessionScopeTests: XCTestCase { func testItManagesViewScopeLifecycle() { let parent = RUMContextProviderMock() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: .mockAny()) XCTAssertEqual(scope.viewScopes.count, 0) _ = scope.process(command: RUMStartViewCommand.mockWith(identity: mockView)) XCTAssertEqual(scope.viewScopes.count, 1) @@ -83,11 +83,11 @@ class RUMSessionScopeTests: XCTestCase { let parent = RUMContextProviderMock() let currentTime = Date() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: true) _ = scope.process(command: RUMStartResourceCommand.mockWith(resourceKey: "/resource/1", time: currentTime)) - XCTAssertEqual(scope.viewScopes.count,1) + XCTAssertEqual(scope.viewScopes.count, 1) XCTAssertEqual(scope.viewScopes[0].viewStartTime, currentTime) XCTAssertEqual(scope.viewScopes[0].viewName, RUMViewScope.Constants.backgroundViewName) XCTAssertEqual(scope.viewScopes[0].viewPath, RUMViewScope.Constants.backgroundViewURL) @@ -97,11 +97,11 @@ class RUMSessionScopeTests: XCTestCase { let parent = RUMContextProviderMock() let currentTime = Date() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: true) _ = scope.process(command: RUMStartUserActionCommand.mockWith(time: currentTime)) - XCTAssertEqual(scope.viewScopes.count,1) + XCTAssertEqual(scope.viewScopes.count, 1) XCTAssertEqual(scope.viewScopes[0].viewStartTime, currentTime) XCTAssertEqual(scope.viewScopes[0].viewName, RUMViewScope.Constants.backgroundViewName) XCTAssertEqual(scope.viewScopes[0].viewPath, RUMViewScope.Constants.backgroundViewURL) @@ -111,30 +111,63 @@ class RUMSessionScopeTests: XCTestCase { let parent = RUMContextProviderMock() let currentTime = Date() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: true) _ = scope.process(command: RUMAddUserActionCommand.mockWith(time: currentTime)) - XCTAssertEqual(scope.viewScopes.count,1) + XCTAssertEqual(scope.viewScopes.count, 1) XCTAssertEqual(scope.viewScopes[0].viewStartTime, currentTime) XCTAssertEqual(scope.viewScopes[0].viewName, RUMViewScope.Constants.backgroundViewName) XCTAssertEqual(scope.viewScopes[0].viewPath, RUMViewScope.Constants.backgroundViewURL) } + func testWhenNoViewScope_andReceivedStartResourceCommand_andBackgroundDisabled_itDoesNotCreateNewViewScope() { + let parent = RUMContextProviderMock() + let currentTime = Date() + + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: false) + + _ = scope.process(command: RUMStartResourceCommand.mockWith(resourceKey: "/resource/1", time: currentTime)) + + XCTAssertEqual(scope.viewScopes.count, 0) + } + + func testWhenNoViewScope_andReceivedStartActionCommand_andBackgroundDisabled_itDoesNotCreateNewViewScope() { + let parent = RUMContextProviderMock() + let currentTime = Date() + + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: false) + + _ = scope.process(command: RUMStartUserActionCommand.mockWith(time: currentTime)) + + XCTAssertEqual(scope.viewScopes.count, 0) + } + + func testWhenNoViewScope_andReceivedAddUserActionCommand_andBackgroundDisabled_itDoesNotCreateNewViewScope() { + let parent = RUMContextProviderMock() + let currentTime = Date() + + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: false) + + _ = scope.process(command: RUMAddUserActionCommand.mockWith(time: currentTime)) + + XCTAssertEqual(scope.viewScopes.count, 0) + } + func testWhenActiveViewScope_andReceivingStartCommand_itDoesNotCreateNewViewScope() { let parent = RUMContextProviderMock() let currentTime = Date() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: .mockAny()) _ = scope.process(command: generateRandomNotValidStartCommand()) _ = scope.process(command: RUMAddUserActionCommand.mockWith(time: currentTime)) - XCTAssertEqual(scope.viewScopes.count, 1) + XCTAssertEqual(scope.viewScopes.count, 0) } func testWhenNoActiveViewScope_andReceivingNotValidStartCommand_itDoesNotCreateNewViewScope() { let parent = RUMContextProviderMock() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 100, startTime: Date(), backgroundEventTrackingEnabled: .mockAny()) _ = scope.process(command: generateRandomNotValidStartCommand()) XCTAssertEqual(scope.viewScopes.count, 0) } @@ -142,7 +175,7 @@ class RUMSessionScopeTests: XCTestCase { func testWhenSessionIsSampled_itDoesNotCreateViewScopes() { let parent = RUMContextProviderMock() - let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 0, startTime: Date()) + let scope = RUMSessionScope(parent: parent, dependencies: .mockAny(), samplingRate: 0, startTime: Date(), backgroundEventTrackingEnabled: .mockAny()) XCTAssertEqual(scope.viewScopes.count, 0) XCTAssertTrue( scope.process(command: RUMStartViewCommand.mockWith(identity: mockView)),