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

Add Tracking Consent feature #347

Merged
merged 28 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
73d69fc
RUMM-829 Configure "authorized" and "unauthorized" data folder for ea…
ncreated Dec 1, 2020
92f6101
RUMM-829 Add `ConsentAwareDataWriter`
ncreated Dec 1, 2020
f4c9506
RUMM-830 Add `ConsentProvider`
ncreated Dec 1, 2020
4800a91
RUMM-830 Plug `ConsentProvider` into `ConsentAwareDataWriter`
ncreated Dec 1, 2020
461e91c
Merge pull request #326 from DataDog/ncreated/RUMM-829-add-consent-aw…
ncreated Dec 7, 2020
6471e79
Merge pull request #328 from DataDog/ncreated/RUMM-830-add-consent-pr…
ncreated Dec 7, 2020
a9d1d43
Merge branch 'master' into tracking-consent
ncreated Dec 7, 2020
77528b5
RUMM-831 Synchronize `FileWriter` and `FileReader` through `DataWrite…
ncreated Dec 2, 2020
806a1bf
RUMM-831 Introduce `DataProcessor` delegating writes to `Writer`
ncreated Dec 2, 2020
6610e2e
RUMM-832 Add data migrators
ncreated Dec 7, 2020
b0ac660
RUMM-832 Migrate data on tracking consent change
ncreated Dec 8, 2020
fe119ab
RUMM-832 Add data privacy tests for `FeatureStorage`
ncreated Dec 8, 2020
54c407d
RUMM-832 Renaming
ncreated Dec 8, 2020
f3a074f
RUMM-832 Make benchmarks compile
ncreated Dec 8, 2020
6a84b11
RUMM-833 Add tracking consent public API
ncreated Dec 8, 2020
4faaef8
RUMM-833 Add tracking consent public API in DatadogObjc
ncreated Dec 8, 2020
363d431
Merge pull request #330 from DataDog/ncreated/RUMM-831-introduce-data…
ncreated Dec 8, 2020
3b739a3
RUMM-833 Add consent tests for `Logger`, `Tracer` and `RUMMonitor`
ncreated Dec 8, 2020
312ac0a
RUMM-833 Update api-surface
ncreated Dec 8, 2020
c80ce8a
RUMM-779 Differentiate tracking consent value for each TestScenario
ncreated Dec 9, 2020
f807d0c
RUMM-779 Reorganize test scenarios so it is easier to add new ones
ncreated Dec 9, 2020
f1dcd77
RUMM-779 Build UI for tracking consent integration tests
ncreated Dec 9, 2020
46de2b9
RUMM-779 Build UI for tracking consent scenario
ncreated Dec 9, 2020
3c26f01
RUMM-779 Define tracking consent integration tests
ncreated Dec 10, 2020
be15318
RUMM-832 Retry data migration up to 3 times
ncreated Dec 16, 2020
a6f0a7d
Merge pull request #334 from DataDog/ncreated/RUMM-832-add-data-migra…
ncreated Dec 16, 2020
a3a3a44
Merge pull request #335 from DataDog/ncreated/RUMM-833-add-tracking-c…
ncreated Dec 16, 2020
3ec66f3
Merge pull request #338 from DataDog/ncreated/RUMM-779-tracking-conse…
ncreated Dec 16, 2020
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
252 changes: 241 additions & 11 deletions Datadog/Datadog.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@
value = "RUMResourcesScenario"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "DD_TEST_SCENARIO_IDENTIFIER"
value = "TrackingConsentStartPendingScenario"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "DD_TEST_SCENARIO_IDENTIFIER"
value = "TrackingConsentStartGrantedScenario"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
Expand Down
17 changes: 15 additions & 2 deletions Datadog/Example/AppConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import UIKit
import Datadog

protocol AppConfiguration {
/// The tracking consent value applied when initializing the SDK.
var initialTrackingConsent: TrackingConsent { get }

/// Datadog SDK configuration for given app configuration.
func sdkConfiguration() -> Datadog.Configuration

Expand All @@ -23,6 +26,8 @@ struct ExampleAppConfiguration: AppConfiguration {
let serviceName = "ios-sdk-example-app"
let testScenario = Environment.testScenario()

let initialTrackingConsent: TrackingConsent = .granted

func sdkConfiguration() -> Datadog.Configuration {
let configuration = Datadog.Configuration
.builderUsing(
Expand Down Expand Up @@ -52,9 +57,17 @@ struct ExampleAppConfiguration: AppConfiguration {
struct UITestsAppConfiguration: AppConfiguration {
let testScenario = Environment.testScenario()

func sdkConfiguration() -> Datadog.Configuration {
deletePersistedSDKData()
init() {
if Environment.shouldClearPersistentData() {
deletePersistedSDKData()
}
}

var initialTrackingConsent: TrackingConsent {
return testScenario!.initialTrackingConsent
}

func sdkConfiguration() -> Datadog.Configuration {
let configuration = Datadog.Configuration
.builderUsing(
rumApplicationID: "rum-application-id",
Expand Down
9 changes: 7 additions & 2 deletions Datadog/Example/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ internal struct Environment {
static let serverMockConfiguration = "DD_TEST_SERVER_MOCK_CONFIGURATION"
}
struct Argument {
static let isRunningUnitTests = "IS_RUNNING_UNIT_TESTS"
static let isRunningUITests = "IS_RUNNING_UI_TESTS"
static let isRunningUnitTests = "IS_RUNNING_UNIT_TESTS"
static let isRunningUITests = "IS_RUNNING_UI_TESTS"
static let doNotClearPersistentData = "DO_NOT_CLEAR_PERSISTENT_DATA"
}
struct InfoPlistKey {
static let clientToken = "DatadogClientToken"
Expand All @@ -58,6 +59,10 @@ internal struct Environment {
return ProcessInfo.processInfo.arguments.contains(Argument.isRunningUITests)
}

static func shouldClearPersistentData() -> Bool {
return !ProcessInfo.processInfo.arguments.contains(Argument.doNotClearPersistentData)
}

// MARK: - Launch Variables

static func testScenario() -> TestScenario? {
Expand Down
1 change: 1 addition & 0 deletions Datadog/Example/ExampleAppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ExampleAppDelegate: UIResponder, UIApplicationDelegate {
// Initialize Datadog SDK
Datadog.initialize(
appContext: .init(),
trackingConsent: appConfiguration.initialTrackingConsent,
configuration: appConfiguration.sdkConfiguration()
)

Expand Down
16 changes: 16 additions & 0 deletions Datadog/Example/Scenarios/Logging/LoggingScenarios.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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-2020 Datadog, Inc.
*/

import Datadog

let allLoggingScenarios: [TestScenario.Type] = [
LoggingManualInstrumentationScenario.self,
]

/// Scenario which starts a view controller that sends bunch of logs to the server.
struct LoggingManualInstrumentationScenario: TestScenario {
static let storyboardName = "LoggingManualInstrumentationScenario"
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Jlq-WO-Qzl">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Jlq-WO-Qzl">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -24,12 +25,12 @@
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="gNT-5l-zGn"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="4yI-pe-L5M" firstAttribute="centerX" secondItem="cdr-c3-9K3" secondAttribute="centerX" id="Tqb-5A-Dxp"/>
<constraint firstItem="4yI-pe-L5M" firstAttribute="centerY" secondItem="cdr-c3-9K3" secondAttribute="centerY" id="rot-Hg-hZg"/>
</constraints>
<viewLayoutGuide key="safeArea" id="gNT-5l-zGn"/>
</view>
<navigationItem key="navigationItem" id="gZZ-Us-17W"/>
</viewController>
Expand All @@ -38,4 +39,9 @@
<point key="canvasLocation" x="-1386" y="1233"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
145 changes: 145 additions & 0 deletions Datadog/Example/Scenarios/RUM/RUMScenarios.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* 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-2020 Datadog, Inc.
*/

import UIKit
import Datadog

let allRUMScenarios: [TestScenario.Type] = [
RUMManualInstrumentationScenario.self,
RUMNavigationControllerScenario.self,
RUMTabBarAutoInstrumentationScenario.self,
RUMModalViewsAutoInstrumentationScenario.self,
RUMTapActionScenario.self,
RUMResourcesScenario.self,
]

/// Scenario which starts a navigation controller. Each view controller pushed to this navigation
/// uses the RUM manual instrumentation API to send RUM events to the server.
struct RUMManualInstrumentationScenario: TestScenario {
static let storyboardName = "RUMManualInstrumentationScenario"
}

/// Scenario which starts a navigation controller and runs through 4 different view controllers by navigating
/// back and forth. Tracks view controllers as RUM Views.
struct RUMNavigationControllerScenario: TestScenario {
static let storyboardName = "RUMNavigationControllerScenario"

private class Predicate: UIKitRUMViewsPredicate {
func rumView(for viewController: UIViewController) -> RUMView? {
switch viewController.accessibilityLabel {
case "Screen 1":
return .init(path: "Screen1")
case "Screen 2":
return .init(path: "Screen2")
case "Screen 3":
return .init(path: "Screen3")
case "Screen 4":
return .init(path: "Screen4")
default:
return nil
}
}
}

func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.trackUIKitRUMViews(using: Predicate())
.enableLogging(false)
.enableTracing(false)
}
}

/// Scenario which presents `UITabBarController`-based hierarchy and navigates through
/// its view controllers. Tracks view controllers as RUM Views.
struct RUMTabBarAutoInstrumentationScenario: TestScenario {
static var storyboardName: String = "RUMTabBarAutoInstrumentationScenario"

private class Predicate: UIKitRUMViewsPredicate {
func rumView(for viewController: UIViewController) -> RUMView? {
if let viewName = viewController.accessibilityLabel {
return .init(path: viewName)
} else {
return nil
}
}
}

func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.trackUIKitRUMViews(using: Predicate())
.enableLogging(false)
.enableTracing(false)
}
}

/// Scenario based on `UINavigationController` hierarchy, which presents different VCs modally.
/// Tracks view controllers as RUM Views.
struct RUMModalViewsAutoInstrumentationScenario: TestScenario {
static var storyboardName: String = "RUMModalViewsAutoInstrumentationScenario"

private class Predicate: UIKitRUMViewsPredicate {
func rumView(for viewController: UIViewController) -> RUMView? {
if let viewName = viewController.accessibilityLabel {
return .init(path: viewName)
} else {
return nil
}
}
}

func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.trackUIKitRUMViews(using: Predicate())
.enableLogging(false)
.enableTracing(false)
}
}

/// Scenario which interacts with various interactive elements laid between different view controllers,
/// including `UITableViewController` and `UICollectionViewController`. Tapped views
/// and controls are tracked as RUM Actions.
struct RUMTapActionScenario: TestScenario {
static var storyboardName: String = "RUMTapActionScenario"

private class Predicate: UIKitRUMViewsPredicate {
func rumView(for viewController: UIViewController) -> RUMView? {
switch NSStringFromClass(type(of: viewController)) {
case "Example.RUMTASScreen1ViewController":
return .init(path: "MenuViewController")
case "Example.RUMTASTableViewController":
return .init(path: "TableViewController")
case "Example.RUMTASCollectionViewController":
return .init(path: "CollectionViewController")
case "Example.RUMTASVariousUIControllsViewController":
return .init(path: "UIControlsViewController")
default:
return nil
}
}
}

func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.trackUIKitRUMViews(using: Predicate())
.trackUIKitActions(true)
.enableLogging(false)
.enableTracing(false)
}
}

/// Scenario which uses RUM and Tracing auto instrumentation features to track bunch of network requests
/// sent with `URLSession` from two VCs. The first VC calls first party resources, the second one calls third parties.
final class RUMResourcesScenario: URLSessionBaseScenario, TestScenario {
static let storyboardName = "URLSessionScenario"
static func envIdentifier() -> String { "RUMResourcesScenario" }

override func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.trackUIKitRUMViews(using: DefaultUIKitRUMViewsPredicate())

super.configureSDK(builder: builder) // applies the `track(firstPartyHosts:)`
}
}
49 changes: 49 additions & 0 deletions Datadog/Example/Scenarios/TestScenarios.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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-2020 Datadog, Inc.
*/

import Datadog

protocol TestScenario {
/// The name of the storyboard containing this scenario.
static var storyboardName: String { get }

/// An identifier for this scenario used to pass its reference in environment variable.
/// Defaults to `storyboardName`.
static func envIdentifier() -> String

/// The value of initial tracking consent for this scenario.
/// Defaults to `.granted`
var initialTrackingConsent: TrackingConsent { get }

/// Applies additional SDK configuration for running this scenario.
/// Defaults to no-op.
func configureSDK(builder: Datadog.Configuration.Builder)

init()
}

/// Defaults.
extension TestScenario {
static func envIdentifier() -> String { storyboardName }
var initialTrackingConsent: TrackingConsent { .granted }
func configureSDK(builder: Datadog.Configuration.Builder) { /* no-op */ }
}

/// Returns `TestScenario` for given env identifier.
func createTestScenario(for envIdentifier: String) -> TestScenario {
let allScenarios = allLoggingScenarios
+ allTracingScenarios
+ allRUMScenarios
+ allTrackingConsentScenarios

let scenarioClass = allScenarios.first { $0.envIdentifier() == envIdentifier }

guard let scenario = scenarioClass?.init() else {
fatalError("Cannot find `TestScenario` for `envIdentifier`: \(envIdentifier)")
}

return scenario
}
48 changes: 48 additions & 0 deletions Datadog/Example/Scenarios/Tracing/TracingScenarios.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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-2020 Datadog, Inc.
*/

import Datadog

let allTracingScenarios: [TestScenario.Type] = [
TracingManualInstrumentationScenario.self,
TracingURLSessionScenario.self,
TracingNSURLSessionScenario.self,
]

/// Scenario which starts a view controller that sends bunch of spans using manual API of `Tracer`.
/// It also uses the `span.log()` to send logs.
struct TracingManualInstrumentationScenario: TestScenario {
static let storyboardName = "TracingManualInstrumentationScenario"
}

/// Scenario which uses Tracing auto instrumentation feature to track bunch of first party network requests
/// sent with `URLSession` (Swift) from the first VC and ignores other third party requests send from second VC.
final class TracingURLSessionScenario: URLSessionBaseScenario, TestScenario {
static let storyboardName = "URLSessionScenario"
static func envIdentifier() -> String { "TracingURLSessionScenario" }

override func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.enableRUM(false)

super.configureSDK(builder: builder)
}
}

/// Scenario which uses Tracing auto instrumentation feature to track bunch of first party network requests
/// sent with `NSURLSession` (Objective-C) from the first VC and ignores other third party requests send from second VC.
@objc
final class TracingNSURLSessionScenario: URLSessionBaseScenario, TestScenario {
static let storyboardName = "NSURLSessionScenario"
static func envIdentifier() -> String { "TracingNSURLSessionScenario" }

override func configureSDK(builder: Datadog.Configuration.Builder) {
_ = builder
.enableRUM(false)

super.configureSDK(builder: builder)
}
}
Loading