Skip to content

Commit 2881108

Browse files
authored
Merge pull request #2109 from DataDog/release/2.20.0
Release 2.20.0
2 parents a9a1b28 + abf5174 commit 2881108

File tree

160 files changed

+2228
-1124
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

160 files changed

+2228
-1124
lines changed

.github/PULL_REQUEST_TEMPLATE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ A brief description of implementation details of this PR.
1010
- [ ] Feature or bugfix MUST have appropriate tests (unit, integration)
1111
- [ ] Make sure each commit and the PR mention the Issue number or JIRA reference
1212
- [ ] Add CHANGELOG entry for user facing changes
13-
- [ ] Add Objective-C interface for public APIs (see our [guidelines](https://datadoghq.atlassian.net/wiki/spaces/RUMP/pages/3157787243/RFC+-+Modular+Objective-C+Interface#Recommended-solution) (internal)) and run `make api-surface`
13+
- [ ] Add Objective-C interface for public APIs (see our [guidelines](https://datadoghq.atlassian.net/wiki/spaces/RUMP/pages/3157787243/RFC+-+Modular+Objective-C+Interface#Recommended-solution) [internal]) and run `make api-surface`)

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
# Unreleased
22

3+
# 2.20.0 / 14-11-2024
4+
5+
- [FIX] Fix race condition during consent change, preventing loss of events recorded on the current thread. See [#2063][]
6+
- [IMPROVEMENT] Support mutation of events' attributes. See [#2099][]
7+
- [IMPROVEMENT] Add 'os' and 'device' info to Span events. See [#2104][]
8+
- [FIX] Fix bug in SR that was enforcing full snapshot more often than needed. See [#2092][]
9+
310
# 2.19.0 / 28-10-2024
411

512
- [FEATURE] Add Privacy Overrides in Session Replay. See [#2088][]
613
- [IMPROVEMENT] Add ObjC API for the internal logging/telemetry. See [#2073][]
14+
- [IMPROVEMENT] Support `clipsToBounds` in Session Replay. See [#2083][]
715

816
# 2.18.0 / 25-09-2024
917
- [IMPROVEMENT] Add overwrite required (breaking) param to addViewLoadingTime & usage telemetry. See [#2040][]
@@ -781,6 +789,11 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO
781789
[#2050]: https://github.com/DataDog/dd-sdk-ios/pull/2050
782790
[#2073]: https://github.com/DataDog/dd-sdk-ios/pull/2073
783791
[#2088]: https://github.com/DataDog/dd-sdk-ios/pull/2088
792+
[#2083]: https://github.com/DataDog/dd-sdk-ios/pull/2083
793+
[#2104]: https://github.com/DataDog/dd-sdk-ios/pull/2104
794+
[#2099]: https://github.com/DataDog/dd-sdk-ios/pull/2099
795+
[#2063]: https://github.com/DataDog/dd-sdk-ios/pull/2063
796+
[#2092]: https://github.com/DataDog/dd-sdk-ios/pull/2092
784797
[@00fa9a]: https://github.com/00FA9A
785798
[@britton-earnin]: https://github.com/Britton-Earnin
786799
[@hengyu]: https://github.com/Hengyu

Datadog/Datadog.xcodeproj/project.pbxproj

+18-18
Large diffs are not rendered by default.

Datadog/IntegrationUnitTests/Public/NetworkInstrumentationIntegrationTests.swift

+12-19
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ class NetworkInstrumentationIntegrationTests: XCTestCase {
107107
applicationID: .mockAny(),
108108
urlSessionTracking: .init(
109109
resourceAttributesProvider: { req, resp, data, err in
110-
XCTAssertNotNil(data)
111-
XCTAssertTrue(data!.count > 0)
112-
providerDataCount = data!.count
110+
providerDataCount = data?.count ?? 0
113111
providerExpectation.fulfill()
114112
return [:]
115113
})
@@ -149,17 +147,14 @@ class NetworkInstrumentationIntegrationTests: XCTestCase {
149147
)
150148

151149
let providerExpectation = expectation(description: "provider called")
152-
var providerDataCount = 0
153-
var providerData: Data?
150+
var providerInfo: (resp: URLResponse?, data: Data?, err: Error?)?
151+
154152
RUM.enable(
155153
with: .init(
156154
applicationID: .mockAny(),
157155
urlSessionTracking: .init(
158-
resourceAttributesProvider: { req, resp, data, err in
159-
XCTAssertNotNil(data)
160-
XCTAssertTrue(data!.count > 0)
161-
providerDataCount = data!.count
162-
data.map { providerData = $0 }
156+
resourceAttributesProvider: { _, resp, data, err in
157+
providerInfo = (resp, data, err)
163158
providerExpectation.fulfill()
164159
return [:]
165160
})
@@ -182,20 +177,18 @@ class NetworkInstrumentationIntegrationTests: XCTestCase {
182177
let request = URLRequest(url: URL(string: "https://www.datadoghq.com/")!)
183178

184179
let taskExpectation = self.expectation(description: "task completed")
185-
var taskDataCount = 0
186-
var taskData: Data?
187-
let task = session.dataTask(with: request) { data, _, _ in
188-
XCTAssertNotNil(data)
189-
XCTAssertTrue(data!.count > 0)
190-
taskDataCount = data!.count
191-
data.map { taskData = $0 }
180+
var taskInfo: (resp: URLResponse?, data: Data?, err: Error?)?
181+
182+
let task = session.dataTask(with: request) { resp, data, err in
183+
taskInfo = (data, resp, err)
192184
taskExpectation.fulfill()
193185
}
194186
task.resume()
195187

196188
wait(for: [providerExpectation, taskExpectation], timeout: 10)
197-
XCTAssertEqual(providerDataCount, taskDataCount)
198-
XCTAssertEqual(providerData, taskData)
189+
XCTAssertEqual(providerInfo?.resp, taskInfo?.resp)
190+
XCTAssertEqual(providerInfo?.data, taskInfo?.data)
191+
XCTAssertEqual(providerInfo?.err as? NSError, taskInfo?.err as? NSError)
199192
}
200193

201194
class InstrumentedSessionDelegate: NSObject, URLSessionDataDelegate {

DatadogAlamofireExtension.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "DatadogAlamofireExtension"
3-
s.version = "2.19.0"
3+
s.version = "2.20.0"
44
s.summary = "An Official Extensions of Datadog Swift SDK for Alamofire."
55
s.description = <<-DESC
66
The DatadogAlamofireExtension pod is deprecated and will no longer be maintained.

DatadogCore.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "DatadogCore"
3-
s.version = "2.19.0"
3+
s.version = "2.20.0"
44
s.summary = "Official Datadog Swift SDK for iOS."
55

66
s.homepage = "https://www.datadoghq.com"

DatadogCore/Sources/Core/Context/ApplicationStatePublisher.swift

+10-40
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ import WatchKit
1414
internal final class ApplicationStatePublisher: ContextValuePublisher {
1515
typealias Snapshot = AppStateHistory.Snapshot
1616

17-
private static var currentApplicationState: ApplicationState {
18-
#if canImport(WatchKit)
19-
WKExtension.dd.shared.applicationState
20-
#else
21-
UIApplication.dd.managedShared?.applicationState ?? .active // fallback to most expected state
22-
#endif
23-
}
24-
2517
/// The default publisher queue.
2618
private static let defaultQueue = DispatchQueue(
2719
label: "com.datadoghq.app-state-publisher",
@@ -58,19 +50,21 @@ internal final class ApplicationStatePublisher: ContextValuePublisher {
5850
/// Creates a Application state publisher for publishing application state
5951
/// history.
6052
///
53+
/// **Note**: It must be called on the main thread.
54+
///
6155
/// - Parameters:
62-
/// - initialState: The initial application state.
63-
/// - queue: The queue for publishing the history.
64-
/// - dateProvider: The date provider for the Application state snapshot timestamp.
56+
/// - appStateProvider: The provider to access the current application state.
6557
/// - notificationCenter: The notification center where this publisher observes `UIApplication` notifications.
58+
/// - dateProvider: The date provider for the Application state snapshot timestamp.
59+
/// - queue: The queue for publishing the history.
6660
init(
67-
initialState: AppState,
68-
queue: DispatchQueue = ApplicationStatePublisher.defaultQueue,
69-
dateProvider: DateProvider = SystemDateProvider(),
70-
notificationCenter: NotificationCenter = .default
61+
appStateProvider: AppStateProvider,
62+
notificationCenter: NotificationCenter,
63+
dateProvider: DateProvider,
64+
queue: DispatchQueue = ApplicationStatePublisher.defaultQueue
7165
) {
7266
let initialValue = AppStateHistory(
73-
initialState: initialState,
67+
initialState: appStateProvider.current,
7468
date: dateProvider.now
7569
)
7670

@@ -81,30 +75,6 @@ internal final class ApplicationStatePublisher: ContextValuePublisher {
8175
self.notificationCenter = notificationCenter
8276
}
8377

84-
/// Creates a Application state publisher for publishing application state
85-
/// history.
86-
///
87-
/// **Note**: It must be called on the main thread.
88-
///
89-
/// - Parameters:
90-
/// - applicationState: The current shared `UIApplication` state.
91-
/// - queue: The queue for publishing the history.
92-
/// - dateProvider: The date provider for the Application state snapshot timestamp.
93-
/// - notificationCenter: The notification center where this publisher observes `UIApplication` notifications.
94-
convenience init(
95-
applicationState: ApplicationState = ApplicationStatePublisher.currentApplicationState,
96-
queue: DispatchQueue = ApplicationStatePublisher.defaultQueue,
97-
dateProvider: DateProvider = SystemDateProvider(),
98-
notificationCenter: NotificationCenter = .default
99-
) {
100-
self.init(
101-
initialState: AppState(applicationState),
102-
queue: queue,
103-
dateProvider: dateProvider,
104-
notificationCenter: notificationCenter
105-
)
106-
}
107-
10878
func publish(to receiver: @escaping ContextValueReceiver<AppStateHistory>) {
10979
queue.async { self.receiver = receiver }
11080
notificationCenter.addObserver(self, selector: #selector(applicationDidBecomeActive), name: ApplicationNotifications.didBecomeActive, object: nil)

DatadogCore/Sources/Core/Context/BatteryStatusPublisher.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ internal final class BatteryStatusPublisher: ContextValuePublisher {
2424
/// Creates a battery status publisher from the given device.
2525
///
2626
/// - Parameters:
27-
/// - device: The `UIDevice` instance. `.current` by default.
2827
/// - notificationCenter: The notification center for observing the `UIDevice` battery changes,
28+
/// - device: The `UIDevice` instance.
2929
init(
30-
device: UIDevice = .current,
31-
notificationCenter: NotificationCenter = .default
30+
notificationCenter: NotificationCenter,
31+
device: UIDevice
3232
) {
3333
self.device = device
3434
self.notificationCenter = notificationCenter

DatadogCore/Sources/Core/Context/LowPowerModePublisher.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ internal final class LowPowerModePublisher: ContextValuePublisher {
1919
/// Creates a low power mode publisher.
2020
///
2121
/// - Parameters:
22-
/// - processInfo: The process for reading the initial `isLowPowerModeEnabled`.
2322
/// - notificationCenter: The notification center for observing the `NSProcessInfoPowerStateDidChange`,
23+
/// - processInfo: The process for reading the initial `isLowPowerModeEnabled`.
2424
init(
25-
processInfo: ProcessInfo = .processInfo,
26-
notificationCenter: NotificationCenter = .default
25+
notificationCenter: NotificationCenter,
26+
processInfo: ProcessInfo
2727
) {
2828
self.initialValue = processInfo.isLowPowerModeEnabled
2929
self.notificationCenter = notificationCenter

DatadogCore/Sources/Core/DatadogCore.swift

+17-5
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,12 @@ internal final class DatadogCore {
160160
/// - Parameter trackingConsent: new consent value, which will be applied for all data collected from now on
161161
func set(trackingConsent: TrackingConsent) {
162162
if trackingConsent != consentPublisher.consent {
163-
allStorages.forEach { $0.migrateUnauthorizedData(toConsent: trackingConsent) }
163+
contextProvider.queue.async { [allStorages] in
164+
// RUM-3175: To prevent race conditions with ongoing "event write" operations,
165+
// data migration must be synchronized on the context queue. This guarantees that
166+
// all latest events have been written before migration occurs.
167+
allStorages.forEach { $0.migrateUnauthorizedData(toConsent: trackingConsent) }
168+
}
164169
consentPublisher.consent = trackingConsent
165170
}
166171
}
@@ -400,8 +405,11 @@ extension DatadogContextProvider {
400405
applicationVersion: String,
401406
sdkInitDate: Date,
402407
device: DeviceInfo,
408+
processInfo: ProcessInfo,
403409
dateProvider: DateProvider,
404-
serverDateProvider: ServerDateProvider
410+
serverDateProvider: ServerDateProvider,
411+
notificationCenter: NotificationCenter,
412+
appStateProvider: AppStateProvider
405413
) {
406414
let context = DatadogContext(
407415
site: site,
@@ -442,14 +450,18 @@ extension DatadogContextProvider {
442450
#endif
443451

444452
#if os(iOS) && !targetEnvironment(simulator)
445-
subscribe(\.batteryStatus, to: BatteryStatusPublisher())
446-
subscribe(\.isLowPowerModeEnabled, to: LowPowerModePublisher())
453+
subscribe(\.batteryStatus, to: BatteryStatusPublisher(notificationCenter: notificationCenter, device: .current))
454+
subscribe(\.isLowPowerModeEnabled, to: LowPowerModePublisher(notificationCenter: notificationCenter, processInfo: processInfo))
447455
#endif
448456

449457
#if os(iOS) || os(tvOS)
450458
DispatchQueue.main.async {
451459
// must be call on the main thread to read `UIApplication.State`
452-
let applicationStatePublisher = ApplicationStatePublisher(dateProvider: dateProvider)
460+
let applicationStatePublisher = ApplicationStatePublisher(
461+
appStateProvider: appStateProvider,
462+
notificationCenter: notificationCenter,
463+
dateProvider: dateProvider
464+
)
453465
self.subscribe(\.applicationStateHistory, to: applicationStatePublisher)
454466
}
455467
#endif

0 commit comments

Comments
 (0)