-
Notifications
You must be signed in to change notification settings - Fork 175
Expand file tree
/
Copy pathRecordingComponents.swift
More file actions
140 lines (126 loc) · 5.59 KB
/
Copy pathRecordingComponents.swift
File metadata and controls
140 lines (126 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* 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.
*/
#if os(iOS)
import Foundation
import DatadogInternal
internal struct RecordingComponents {
let recordingCoordinator: any RecordingController
let messageReceiver: any FeatureMessageReceiver
let contextReceiver: RUMContextReceiver
init(
core: DatadogCoreProtocol,
configuration: SessionReplay.Configuration
) throws {
if #available(iOS 13.0, tvOS 13.0, *), configuration.featureFlags[.layerTreeRecording] {
// This is purely defensive, as `SessionReplay.enable()` initializes on the main thread
self = try runOnMainThreadSync {
try MainActor.assumeIsolated {
try .layerTreeRecordingComponents(core: core, configuration: configuration)
}
}
} else {
self = try .viewTreeRecordingComponents(core: core, configuration: configuration)
}
}
private init(
recordingCoordinator: any RecordingController,
messageReceiver: any FeatureMessageReceiver,
contextReceiver: RUMContextReceiver
) {
self.recordingCoordinator = recordingCoordinator
self.messageReceiver = messageReceiver
self.contextReceiver = contextReceiver
}
private static func viewTreeRecordingComponents(
core: DatadogCoreProtocol,
configuration: SessionReplay.Configuration
) throws -> Self {
let processorsQueue = BackgroundAsyncQueue(label: "com.datadoghq.session-replay.processors", qos: .utility)
// The telemetry queue targets the processors queue with a lower qos.
let telemetryQueue = BackgroundAsyncQueue(
label: "com.datadoghq.session-replay.telemetry",
qos: .background,
target: processorsQueue
)
let telemetry = SessionReplayTelemetry(
telemetry: core.telemetry,
queue: telemetryQueue
)
let resourceProcessor = ResourceProcessor(
queue: processorsQueue,
resourcesWriter: ResourcesWriter(scope: core.scope(for: ResourcesFeature.self))
)
let snapshotProcessor = SnapshotProcessor(
queue: processorsQueue,
recordWriter: RecordWriter(core: core),
resourceProcessor: resourceProcessor,
srContextPublisher: SRContextPublisher(core: core),
telemetry: telemetry
)
let recorder = try Recorder(
snapshotProcessor: snapshotProcessor,
additionalNodeRecorders: configuration._additionalNodeRecorders,
core: core,
featureFlags: configuration.featureFlags
)
let scheduler = ScreenChangeScheduler(minimumInterval: 0.1, telemetry: telemetry)
let contextReceiver = RUMContextReceiver()
let recordingCoordinator = RecordingCoordinator(
scheduler: scheduler,
textAndInputPrivacy: configuration.textAndInputPrivacyLevel,
imagePrivacy: configuration.imagePrivacyLevel,
touchPrivacy: configuration.touchPrivacyLevel,
rumContextObserver: contextReceiver,
srContextPublisher: SRContextPublisher(core: core),
recorder: recorder,
replaySampleRate: configuration.debugSDK ? 100 : configuration.replaySampleRate,
telemetry: telemetry,
startRecordingImmediately: configuration.startRecordingImmediately
)
return .init(
recordingCoordinator: recordingCoordinator,
messageReceiver: NOPFeatureMessageReceiver(),
contextReceiver: contextReceiver
)
}
@available(iOS 13.0, tvOS 13.0, *)
@MainActor
private static func layerTreeRecordingComponents(
core: DatadogCoreProtocol,
configuration: SessionReplay.Configuration
) throws -> Self {
let telemetryQueue = BackgroundAsyncQueue(label: "com.datadoghq.session-replay.telemetry", qos: .background)
let telemetry = SessionReplayTelemetry(
telemetry: core.telemetry,
queue: telemetryQueue
)
let keyWindowObserver = KeyWindowObserver()
let touchSnapshotProducer = WindowTouchSnapshotProducer(windowObserver: keyWindowObserver)
let layerRecorder = LayerRecorder(
snapshotBuilder: LayerTreeSnapshotBuilder(layerProvider: keyWindowObserver),
uiApplicationSwizzler: try UIApplicationSwizzler(handler: touchSnapshotProducer),
touchSnapshotProducer: touchSnapshotProducer
)
let screenChangeMonitor = try ScreenChangeMonitor(minimumDeliveryInterval: 0.1)
let recordingCoordinator = LayerTreeRecordingCoordinator(
screenChangeMonitor: screenChangeMonitor,
textAndInputPrivacy: configuration.textAndInputPrivacyLevel,
imagePrivacy: configuration.imagePrivacyLevel,
touchPrivacy: configuration.touchPrivacyLevel,
srContextPublisher: SRContextPublisher(core: core),
layerRecording: layerRecorder,
replaySampleRate: configuration.debugSDK ? 100 : configuration.replaySampleRate,
telemetry: telemetry,
startRecordingImmediately: configuration.startRecordingImmediately
)
return .init(
recordingCoordinator: recordingCoordinator,
messageReceiver: recordingCoordinator,
contextReceiver: RUMContextReceiver()
)
}
}
#endif