Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RUMM-1269 Add configuration to enable/disable background RUM events #537

Merged
Merged
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
4 changes: 3 additions & 1 deletion Sources/Datadog/Core/FeaturesConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down
16 changes: 16 additions & 0 deletions Sources/Datadog/DatadogConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -335,6 +336,7 @@ extension Datadog {
rumActionEventMapper: nil,
rumErrorEventMapper: nil,
rumResourceAttributesProvider: nil,
rumBackgroundEventTrackingEnabled: false,
batchSize: .medium,
uploadFrequency: .average,
additionalConfiguration: [:],
Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,22 @@ 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

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,
Expand Down Expand Up @@ -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
Expand Down
12 changes: 9 additions & 3 deletions Sources/Datadog/RUM/RUMMonitor/Scopes/RUMSessionScope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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:
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion Sources/Datadog/RUMMonitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -140,6 +143,7 @@ class DatadogConfigurationBuilderTests: XCTestCase {

XCTAssertTrue(rumConfigurationWithDefaultValues.rumUIKitViewsPredicate is DefaultUIKitRUMViewsPredicate)
XCTAssertTrue(rumConfigurationWithDefaultValues.rumUIKitActionsTrackingEnabled)
XCTAssertTrue(rumConfigurationWithDefaultValues.rumBackgroundEventTrackingEnabled)
}

func testDeprecatedAPIs() {
Expand Down
8 changes: 6 additions & 2 deletions Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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] = [:],
Expand All @@ -79,6 +80,7 @@ extension Datadog.Configuration {
rumUIKitViewsPredicate: rumUIKitViewsPredicate,
rumUIKitActionsTrackingEnabled: rumUIKitActionsTrackingEnabled,
rumResourceAttributesProvider: rumResourceAttributesProvider,
rumBackgroundEventTrackingEnabled: rumBackgroundEventTrackingEnabled,
batchSize: batchSize,
uploadFrequency: uploadFrequency,
additionalConfiguration: additionalConfiguration,
Expand Down Expand Up @@ -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,
Expand All @@ -233,7 +236,8 @@ extension FeaturesConfiguration.RUM {
resourceEventMapper: resourceEventMapper,
actionEventMapper: actionEventMapper,
errorEventMapper: errorEventMapper,
autoInstrumentation: autoInstrumentation
autoInstrumentation: autoInstrumentation,
backgroundEventTrackingEnabled: backgroundEventTrackingEnabled
)
}
}
Expand Down
12 changes: 8 additions & 4 deletions Tests/DatadogTests/Datadog/Mocks/RUMFeatureMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
}
}
Expand All @@ -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
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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()
Expand All @@ -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()))
Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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
Expand Down
Loading