Skip to content

Commit

Permalink
Merge branch 'develop' into ncreated/REPLAY-1965/fix-sr-url-for-ap1-dc
Browse files Browse the repository at this point in the history
  • Loading branch information
ncreated authored Aug 18, 2023
2 parents f53c5a3 + cbb720c commit 3203401
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [BUGFIX] Do not propagate attributes from Errors and LongTasks to Views.
- [IMPROVEMENT] Upgrade to PLCrashReporter 1.11.1.
- [FEATURE] Report session sample rate to the backend with RUM events. See [#1410][]
- [IMPROVEMENT] Expose Session Replay to Objective-C. see [#1419][]

# 2.0.0 / 31-07-2023

Expand Down Expand Up @@ -497,6 +498,7 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO
[#1410]: https://github.com/DataDog/dd-sdk-ios/pull/1410
[#1413]: https://github.com/DataDog/dd-sdk-ios/pull/1413
[#1418]: https://github.com/DataDog/dd-sdk-ios/pull/1418
[#1419]: https://github.com/DataDog/dd-sdk-ios/pull/1419
[@00fa9a]: https://github.com/00FA9A
[@britton-earnin]: https://github.com/Britton-Earnin
[@hengyu]: https://github.com/Hengyu
Expand Down
109 changes: 51 additions & 58 deletions Datadog/Datadog.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions DatadogCore/Tests/DatadogObjc/DDSessionReplayTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 XCTest
import TestUtilities
import DatadogInternal

@testable import DatadogObjc
@testable import DatadogSessionReplay

class DDSessionReplayTests: XCTestCase {
func testDefaultConfiguration() {
// Given
let sampleRate: Float = .mockRandom(min: 0, max: 100)

// When
let config = DDSessionReplayConfiguration(replaySampleRate: sampleRate)

// Then
XCTAssertEqual(config._swift.replaySampleRate, sampleRate)
XCTAssertEqual(config._swift.defaultPrivacyLevel, .mask)
XCTAssertNil(config._swift.customEndpoint)
}

func testConfigurationOverrides() {
// Given
let sampleRate: Float = .mockRandom(min: 0, max: 100)
let privacy: DDSessionReplayConfigurationPrivacyLevel = [.allow, .mask, .maskUserInput].randomElement()!
let url: URL = .mockRandom()

// When
let config = DDSessionReplayConfiguration(replaySampleRate: 100)
config.replaySampleRate = sampleRate
config.defaultPrivacyLevel = privacy
config.customEndpoint = url

// Then
XCTAssertEqual(config._swift.replaySampleRate, sampleRate)
XCTAssertEqual(config._swift.defaultPrivacyLevel, privacy._swift)
XCTAssertEqual(config._swift.customEndpoint, url)
}

func testPrivacyLevelsInterop() {
XCTAssertEqual(DDSessionReplayConfigurationPrivacyLevel.allow._swift, .allow)
XCTAssertEqual(DDSessionReplayConfigurationPrivacyLevel.mask._swift, .mask)
XCTAssertEqual(DDSessionReplayConfigurationPrivacyLevel.maskUserInput._swift, .maskUserInput)

XCTAssertEqual(DDSessionReplayConfigurationPrivacyLevel(.allow), .allow)
XCTAssertEqual(DDSessionReplayConfigurationPrivacyLevel(.mask), .mask)
XCTAssertEqual(DDSessionReplayConfigurationPrivacyLevel(.maskUserInput), .maskUserInput)
}

func testWhenEnabled() throws {
// Given
let core = FeatureRegistrationCoreMock()
CoreRegistry.register(default: core)
defer { CoreRegistry.unregisterDefault() }

let config = DDSessionReplayConfiguration(replaySampleRate: 42)

// When
DDSessionReplay.enable(with: config)

// Then
let sr = try XCTUnwrap(core.get(feature: SessionReplayFeature.self))
let requestBuilder = try XCTUnwrap(sr.requestBuilder as? DatadogSessionReplay.RequestBuilder)
XCTAssertEqual(sr.recordingCoordinator.sampler.samplingRate, 42)
XCTAssertEqual(sr.recordingCoordinator.privacy, .mask)
XCTAssertNil(requestBuilder.customUploadURL)
}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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.
*/

#import <XCTest/XCTest.h>

#if TARGET_OS_IOS

@import DatadogObjc;

@interface DDSessionReplay_apiTests : XCTestCase
@end

@implementation DDSessionReplay_apiTests

- (void)testConfiguration {
DDSessionReplayConfiguration *configuration = [[DDSessionReplayConfiguration alloc] initWithReplaySampleRate:100];
configuration.defaultPrivacyLevel = DDSessionReplayConfigurationPrivacyLevelAllow;
configuration.customEndpoint = [NSURL new];

[DDSessionReplay enableWith:configuration];
}

@end

#endif
1 change: 1 addition & 0 deletions DatadogObjc.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ Pod::Spec.new do |s|
s.dependency 'DatadogRUM', s.version.to_s
s.dependency 'DatadogLogs', s.version.to_s
s.dependency 'DatadogTrace', s.version.to_s
s.dependency 'DatadogSessionReplay', s.version.to_s
end
File renamed without changes.
File renamed without changes.
109 changes: 109 additions & 0 deletions DatadogObjc/Sources/SessionReplay/SessionReplay+objc.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* 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.
*/

import Foundation
#if os(iOS)
import DatadogSessionReplay

/// An entry point to Datadog Session Replay feature.
@objc
public final class DDSessionReplay: NSObject {
override private init() { }

/// Enables Datadog Session Replay feature.
///
/// Recording will start automatically after enabling Session Replay.
///
/// Note: Session Replay requires the RUM feature to be enabled.
///
/// - Parameters:
/// - configuration: Configuration of the feature.
@objc
public static func enable(with configuration: DDSessionReplayConfiguration) {
SessionReplay.enable(with: configuration._swift)
}
}

/// Session Replay feature configuration.
@objc
public final class DDSessionReplayConfiguration: NSObject {
internal var _swift: SessionReplay.Configuration = .init(replaySampleRate: 0)

/// The sampling rate for Session Replay. It is applied in addition to the RUM session sample rate.
///
/// It must be a number between 0.0 and 100.0, where 0 means no replays will be recorded
/// and 100 means all RUM sessions will contain replay.
///
/// Note: This sample rate is applied in addition to the RUM sample rate. For example, if RUM uses a sample rate of 80%
/// and Session Replay uses a sample rate of 20%, it means that out of all user sessions, 80% will be included in RUM,
/// and within those sessions, only 20% will have replays.
@objc public var replaySampleRate: Float {
set { _swift.replaySampleRate = newValue }
get { _swift.replaySampleRate }
}

/// Defines the way sensitive content (e.g. text) should be masked.
///
/// Default: `.mask`.
@objc public var defaultPrivacyLevel: DDSessionReplayConfigurationPrivacyLevel {
set { _swift.defaultPrivacyLevel = newValue._swift }
get { .init(_swift.defaultPrivacyLevel) }
}

/// Custom server url for sending replay data.
///
/// Default: `nil`.
@objc public var customEndpoint: URL? {
set { _swift.customEndpoint = newValue }
get { _swift.customEndpoint }
}

/// Creates Session Replay configuration.
///
/// - Parameters:
/// - replaySampleRate: The sampling rate for Session Replay. It is applied in addition to the RUM session sample rate.
@objc
public required init(
replaySampleRate: Float
) {
_swift = SessionReplay.Configuration(
replaySampleRate: replaySampleRate
)
super.init()
}
}

/// Available privacy levels for content masking.
@objc
public enum DDSessionReplayConfigurationPrivacyLevel: Int {
/// Record all content.
case allow

/// Mask all content.
case mask

/// Mask input elements, but record all other content.
case maskUserInput

internal var _swift: SessionReplay.Configuration.PrivacyLevel {
switch self {
case .allow: return .allow
case .mask: return .mask
case .maskUserInput: return .maskUserInput
default: return .mask
}
}

internal init(_ swift: SessionReplay.Configuration.PrivacyLevel) {
switch swift {
case .allow: self = .allow
case .mask: self = .mask
case .maskUserInput: self = .maskUserInput
}
}
}

#endif
File renamed without changes.
1 change: 1 addition & 0 deletions DatadogSDKObjc.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ Pod::Spec.new do |s|
s.dependency 'DatadogRUM', s.version.to_s
s.dependency 'DatadogLogs', s.version.to_s
s.dependency 'DatadogTrace', s.version.to_s
s.dependency 'DatadogSessionReplay', s.version.to_s
end
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ let package = Package(
.target(name: "DatadogLogs"),
.target(name: "DatadogTrace"),
.target(name: "DatadogRUM"),
.target(name: "DatadogSessionReplay"),
],
path: "DatadogObjc/Sources"
),
Expand Down

0 comments on commit 3203401

Please sign in to comment.