From 6c9ac6af3e1e7fe11137d5c1d8fa74b0949c80b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sima=CC=83o=20Seic=CC=A7a?= Date: Sat, 14 Dec 2024 11:00:45 +0000 Subject: [PATCH] RUM-6850: Add more precision to Effective Sample Rate --- .../CoreTelemetryIntegrationTests.swift | 10 ++-- .../Datadog/Mocks/RUMDataModelMocks.swift | 2 + .../Tests/Datadog/RUM/RUMMonitorTests.swift | 2 +- .../Sources/RUM/RUMDataModels+objc.swift | 56 ++++++++++++++++++- .../Sources/DataModels/RUMDataModels.swift | 26 +++++++-- .../Integrations/TelemetryReceiver.swift | 11 ++-- DatadogRUM/Sources/RUMEvent/RUMUser.swift | 1 + .../Tests/Mocks/RUMDataModelMocks.swift | 2 + api-surface-objc | 12 ++++ api-surface-swift | 14 +++-- 10 files changed, 115 insertions(+), 21 deletions(-) diff --git a/Datadog/IntegrationUnitTests/Public/CoreTelemetryIntegrationTests.swift b/Datadog/IntegrationUnitTests/Public/CoreTelemetryIntegrationTests.swift index 587a2e4eea..8971d5900c 100644 --- a/Datadog/IntegrationUnitTests/Public/CoreTelemetryIntegrationTests.swift +++ b/Datadog/IntegrationUnitTests/Public/CoreTelemetryIntegrationTests.swift @@ -235,27 +235,27 @@ class CoreTelemetryIntegrationTests: XCTestCase { XCTAssertGreaterThan(usageEvents.count, 0) let debug = try XCTUnwrap(debugEvents.first(where: { $0.telemetry.message == "Debug Telemetry" })) - XCTAssertEqual(debug.effectiveSampleRate, Int64(withNoOverflow: config.telemetrySampleRate)) + XCTAssertEqual(debug.effectiveSampleRate, Double(config.telemetrySampleRate)) let error = try XCTUnwrap(errorEvents.first(where: { $0.telemetry.message == "Error Telemetry" })) - XCTAssertEqual(error.effectiveSampleRate, Int64(withNoOverflow: config.telemetrySampleRate)) + XCTAssertEqual(error.effectiveSampleRate, Double(config.telemetrySampleRate)) let mobileMetric = try XCTUnwrap(debugEvents.first(where: { $0.telemetry.message == "[Mobile Metric] Metric Name" })) XCTAssertEqual( mobileMetric.effectiveSampleRate, - Int64(withNoOverflow: config.telemetrySampleRate.composed(with: metricsSampleRate)) + Double(config.telemetrySampleRate.composed(with: metricsSampleRate)) ) let methodCalledMetric = try XCTUnwrap(debugEvents.first(where: { $0.telemetry.message == "[Mobile Metric] Method Called" })) XCTAssertEqual( methodCalledMetric.effectiveSampleRate, - Int64(withNoOverflow: config.telemetrySampleRate.composed(with: metricsSampleRate).composed(with: headSampleRate)) + Double(config.telemetrySampleRate.composed(with: metricsSampleRate).composed(with: headSampleRate)) ) let usage = try XCTUnwrap(usageEvents.first) XCTAssertEqual( usage.effectiveSampleRate, - Int64(withNoOverflow: config.telemetrySampleRate.composed(with: metricsSampleRate)) + Double(config.telemetrySampleRate.composed(with: metricsSampleRate)) ) } } diff --git a/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift b/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift index b6aace9816..2936adc277 100644 --- a/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift +++ b/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift @@ -11,6 +11,7 @@ import TestUtilities extension RUMUser { static func mockRandom() -> RUMUser { return RUMUser( + anonymousId: .mockRandom(), email: .mockRandom(), id: .mockRandom(), name: .mockRandom(), @@ -524,6 +525,7 @@ extension TelemetryConfigurationEvent: RandomMockable { batchProcessingLevel: .mockRandom(), batchSize: .mockAny(), batchUploadFrequency: .mockAny(), + collectFeatureFlagsOn: nil, compressIntakeRequests: nil, defaultPrivacyLevel: .mockAny(), forwardConsoleLogs: nil, diff --git a/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift b/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift index 2fdc953ad7..c43eac2801 100644 --- a/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift +++ b/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift @@ -642,7 +642,7 @@ class RUMMonitorTests: XCTestCase { monitor.stopView(viewController: mockView) let rumEventMatchers = try core.waitAndReturnRUMEventMatchers() - let expectedUserInfo = RUMUser(email: "foo@bar.com", id: "abc-123", name: "Foo", usrInfo: [ + let expectedUserInfo = RUMUser(anonymousId: nil, email: "foo@bar.com", id: "abc-123", name: "Foo", usrInfo: [ "str": AnyEncodable("value"), "int": AnyEncodable(11_235), "bool": AnyEncodable(true) diff --git a/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift b/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift index 2c063f9572..a39cf11248 100644 --- a/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift +++ b/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift @@ -991,6 +991,10 @@ public class DDRUMActionEventRUMUser: NSObject { self.root = root } + @objc public var anonymousId: String? { + root.swiftModel.usr!.anonymousId + } + @objc public var email: String? { root.swiftModel.usr!.email } @@ -2381,6 +2385,10 @@ public class DDRUMErrorEventRUMUser: NSObject { self.root = root } + @objc public var anonymousId: String? { + root.swiftModel.usr!.anonymousId + } + @objc public var email: String? { root.swiftModel.usr!.email } @@ -3329,6 +3337,10 @@ public class DDRUMLongTaskEventRUMUser: NSObject { self.root = root } + @objc public var anonymousId: String? { + root.swiftModel.usr!.anonymousId + } + @objc public var email: String? { root.swiftModel.usr!.email } @@ -4611,6 +4623,10 @@ public class DDRUMResourceEventRUMUser: NSObject { self.root = root } + @objc public var anonymousId: String? { + root.swiftModel.usr!.anonymousId + } + @objc public var email: String? { root.swiftModel.usr!.email } @@ -5525,6 +5541,10 @@ public class DDRUMViewEventRUMUser: NSObject { self.root = root } + @objc public var anonymousId: String? { + root.swiftModel.usr!.anonymousId + } + @objc public var email: String? { root.swiftModel.usr!.email } @@ -6674,6 +6694,10 @@ public class DDRUMVitalEventRUMUser: NSObject { self.root = root } + @objc public var anonymousId: String? { + root.swiftModel.usr!.anonymousId + } + @objc public var email: String? { root.swiftModel.usr!.email } @@ -7486,6 +7510,10 @@ public class DDTelemetryConfigurationEventTelemetryConfiguration: NSObject { root.swiftModel.telemetry.configuration.batchUploadFrequency as NSNumber? } + @objc public var collectFeatureFlagsOn: [Int]? { + root.swiftModel.telemetry.configuration.collectFeatureFlagsOn?.map { DDTelemetryConfigurationEventTelemetryConfigurationCollectFeatureFlagsOn(swift: $0).rawValue } + } + @objc public var compressIntakeRequests: NSNumber? { root.swiftModel.telemetry.configuration.compressIntakeRequests as NSNumber? } @@ -7779,6 +7807,32 @@ public class DDTelemetryConfigurationEventTelemetryConfiguration: NSObject { } } +@objc +public enum DDTelemetryConfigurationEventTelemetryConfigurationCollectFeatureFlagsOn: Int { + internal init(swift: TelemetryConfigurationEvent.Telemetry.Configuration.CollectFeatureFlagsOn?) { + switch swift { + case nil: self = .none + case .view?: self = .view + case .error?: self = .error + case .vital?: self = .vital + } + } + + internal var toSwift: TelemetryConfigurationEvent.Telemetry.Configuration.CollectFeatureFlagsOn? { + switch self { + case .none: return nil + case .view: return .view + case .error: return .error + case .vital: return .vital + } + } + + case none + case view + case error + case vital +} + @objc public class DDTelemetryConfigurationEventTelemetryConfigurationForwardConsoleLogs: NSObject { internal let root: DDTelemetryConfigurationEvent @@ -8008,4 +8062,4 @@ public class DDTelemetryConfigurationEventView: NSObject { // swiftlint:enable force_unwrapping -// Generated from https://github.com/DataDog/rum-events-format/tree/f0fb6383cc401f2f3db120d1f3e2d95d8e03b981 +// Generated from https://github.com/DataDog/rum-events-format/tree/81c3d7401cba2a2faf48b5f4c0e8aca05c759662 diff --git a/DatadogRUM/Sources/DataModels/RUMDataModels.swift b/DatadogRUM/Sources/DataModels/RUMDataModels.swift index 3db6a5df27..ecdb28fe44 100644 --- a/DatadogRUM/Sources/DataModels/RUMDataModels.swift +++ b/DatadogRUM/Sources/DataModels/RUMDataModels.swift @@ -3167,7 +3167,7 @@ public struct TelemetryErrorEvent: RUMDataModel { public let date: Int64 /// The actual percentage of telemetry usage per event - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? /// Enabled experimental features public let experimentalFeatures: [String]? @@ -3373,7 +3373,7 @@ public struct TelemetryDebugEvent: RUMDataModel { public let date: Int64 /// The actual percentage of telemetry usage per event - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? /// Enabled experimental features public let experimentalFeatures: [String]? @@ -3559,7 +3559,7 @@ public struct TelemetryConfigurationEvent: RUMDataModel { public let date: Int64 /// The actual percentage of telemetry usage per event - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? /// Enabled experimental features public let experimentalFeatures: [String]? @@ -3701,6 +3701,9 @@ public struct TelemetryConfigurationEvent: RUMDataModel { /// The upload frequency of batches (in milliseconds) public let batchUploadFrequency: Int64? + /// The list of events that include feature flags collection + public let collectFeatureFlagsOn: [CollectFeatureFlagsOn]? + /// Whether intake requests are compressed public let compressIntakeRequests: Bool? @@ -3902,6 +3905,7 @@ public struct TelemetryConfigurationEvent: RUMDataModel { case batchProcessingLevel = "batch_processing_level" case batchSize = "batch_size" case batchUploadFrequency = "batch_upload_frequency" + case collectFeatureFlagsOn = "collect_feature_flags_on" case compressIntakeRequests = "compress_intake_requests" case dartVersion = "dart_version" case defaultPrivacyLevel = "default_privacy_level" @@ -3968,6 +3972,12 @@ public struct TelemetryConfigurationEvent: RUMDataModel { case viewTrackingStrategy = "view_tracking_strategy" } + public enum CollectFeatureFlagsOn: String, Codable { + case view = "view" + case error = "error" + case vital = "vital" + } + /// The console.* tracked public enum ForwardConsoleLogs: Codable { case stringsArray(value: [String]) @@ -4190,7 +4200,7 @@ public struct TelemetryUsageEvent: RUMDataModel { public let date: Int64 /// The actual percentage of telemetry usage per event - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? /// Enabled experimental features public let experimentalFeatures: [String]? @@ -4818,6 +4828,9 @@ public struct RUMSyntheticsTest: Codable { /// User properties public struct RUMUser: Codable { + /// Identifier of the user across sessions + public let anonymousId: String? + /// Email of the user public let email: String? @@ -4830,6 +4843,7 @@ public struct RUMUser: Codable { public var usrInfo: [String: Encodable] enum StaticCodingKeys: String, CodingKey { + case anonymousId = "anonymous_id" case email = "email" case id = "id" case name = "name" @@ -4840,6 +4854,7 @@ extension RUMUser { public func encode(to encoder: Encoder) throws { // Encode static properties: var staticContainer = encoder.container(keyedBy: StaticCodingKeys.self) + try staticContainer.encodeIfPresent(anonymousId, forKey: .anonymousId) try staticContainer.encodeIfPresent(email, forKey: .email) try staticContainer.encodeIfPresent(id, forKey: .id) try staticContainer.encodeIfPresent(name, forKey: .name) @@ -4855,6 +4870,7 @@ extension RUMUser { public init(from decoder: Decoder) throws { // Decode static properties: let staticContainer = try decoder.container(keyedBy: StaticCodingKeys.self) + self.anonymousId = try staticContainer.decodeIfPresent(String.self, forKey: .anonymousId) self.email = try staticContainer.decodeIfPresent(String.self, forKey: .email) self.id = try staticContainer.decodeIfPresent(String.self, forKey: .id) self.name = try staticContainer.decodeIfPresent(String.self, forKey: .name) @@ -4964,4 +4980,4 @@ public struct RUMTelemetryOperatingSystem: Codable { } } -// Generated from https://github.com/DataDog/rum-events-format/tree/f0fb6383cc401f2f3db120d1f3e2d95d8e03b981 +// Generated from https://github.com/DataDog/rum-events-format/tree/81c3d7401cba2a2faf48b5f4c0e8aca05c759662 diff --git a/DatadogRUM/Sources/Integrations/TelemetryReceiver.swift b/DatadogRUM/Sources/Integrations/TelemetryReceiver.swift index 9ab127fb96..3e46b0473a 100644 --- a/DatadogRUM/Sources/Integrations/TelemetryReceiver.swift +++ b/DatadogRUM/Sources/Integrations/TelemetryReceiver.swift @@ -117,7 +117,7 @@ internal final class TelemetryReceiver: FeatureMessageReceiver { action: rum?.userActionID.map { .init(id: $0) }, application: rum.map { .init(id: $0.applicationID) }, date: date.addingTimeInterval(context.serverTimeOffset).timeIntervalSince1970.toInt64Milliseconds, - effectiveSampleRate: Int64(withNoOverflow: self.sampler.samplingRate), + effectiveSampleRate: Double(self.sampler.samplingRate), experimentalFeatures: nil, service: "dd-sdk-ios", session: rum.map { .init(id: $0.sessionID) }, @@ -158,7 +158,7 @@ internal final class TelemetryReceiver: FeatureMessageReceiver { action: rum?.userActionID.map { .init(id: $0) }, application: rum.map { .init(id: $0.applicationID) }, date: date.addingTimeInterval(context.serverTimeOffset).timeIntervalSince1970.toInt64Milliseconds, - effectiveSampleRate: Int64(withNoOverflow: self.sampler.samplingRate), + effectiveSampleRate: Double(self.sampler.samplingRate), experimentalFeatures: nil, service: "dd-sdk-ios", session: rum.map { .init(id: $0.sessionID) }, @@ -189,7 +189,7 @@ internal final class TelemetryReceiver: FeatureMessageReceiver { action: rum?.userActionID.map { .init(id: $0) }, application: rum.map { .init(id: $0.applicationID) }, date: date.addingTimeInterval(context.serverTimeOffset).timeIntervalSince1970.toInt64Milliseconds, - effectiveSampleRate: Int64(withNoOverflow: usage.sampleRate.composed(with: self.sampler.samplingRate)), + effectiveSampleRate: Double(usage.sampleRate.composed(with: self.sampler.samplingRate)), experimentalFeatures: nil, service: "dd-sdk-ios", session: rum.map { .init(id: $0.sessionID) }, @@ -229,7 +229,7 @@ internal final class TelemetryReceiver: FeatureMessageReceiver { action: rum?.userActionID.map { .init(id: $0) }, application: rum.map { .init(id: $0.applicationID) }, date: date.addingTimeInterval(context.serverTimeOffset).timeIntervalSince1970.toInt64Milliseconds, - effectiveSampleRate: Int64(withNoOverflow: self.configurationExtraSampler.samplingRate.composed(with: self.sampler.samplingRate)), + effectiveSampleRate: Double(self.configurationExtraSampler.samplingRate.composed(with: self.sampler.samplingRate)), experimentalFeatures: nil, service: "dd-sdk-ios", session: rum.map { .init(id: $0.sessionID) }, @@ -270,7 +270,7 @@ internal final class TelemetryReceiver: FeatureMessageReceiver { action: rum?.userActionID.map { .init(id: $0) }, application: rum.map { .init(id: $0.applicationID) }, date: date.addingTimeInterval(context.serverTimeOffset).timeIntervalSince1970.toInt64Milliseconds, - effectiveSampleRate: Int64(withNoOverflow: effectiveSampleRate), + effectiveSampleRate: Double(effectiveSampleRate), experimentalFeatures: nil, service: "dd-sdk-ios", session: sessionID.map { .init(id: $0) }, @@ -376,6 +376,7 @@ private extension TelemetryConfigurationEvent.Telemetry.Configuration { batchProcessingLevel: configuration.batchProcessingLevel, batchSize: configuration.batchSize, batchUploadFrequency: configuration.batchUploadFrequency, + collectFeatureFlagsOn: nil, compressIntakeRequests: nil, dartVersion: configuration.dartVersion, defaultPrivacyLevel: nil, diff --git a/DatadogRUM/Sources/RUMEvent/RUMUser.swift b/DatadogRUM/Sources/RUMEvent/RUMUser.swift index 80ce68e9de..d760f916a3 100644 --- a/DatadogRUM/Sources/RUMEvent/RUMUser.swift +++ b/DatadogRUM/Sources/RUMEvent/RUMUser.swift @@ -22,6 +22,7 @@ extension RUMUser { init(userInfo: UserInfo) { self.init( + anonymousId: nil, email: userInfo.email, id: userInfo.id, name: userInfo.name, diff --git a/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift b/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift index 1e796891e0..faeecd7fe4 100644 --- a/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift +++ b/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift @@ -24,6 +24,7 @@ internal func randomRUMEvent() -> RUMDataModel { extension RUMUser: RandomMockable { public static func mockRandom() -> RUMUser { return RUMUser( + anonymousId: .mockRandom(), email: .mockRandom(), id: .mockRandom(), name: .mockRandom(), @@ -542,6 +543,7 @@ extension TelemetryConfigurationEvent: RandomMockable { batchProcessingLevel: .mockRandom(), batchSize: .mockAny(), batchUploadFrequency: .mockRandom(), + collectFeatureFlagsOn: nil, compressIntakeRequests: nil, defaultPrivacyLevel: .mockRandom(), forwardConsoleLogs: nil, diff --git a/api-surface-objc b/api-surface-objc index 317cabe95e..e231505072 100644 --- a/api-surface-objc +++ b/api-surface-objc @@ -577,6 +577,7 @@ public class DDRUMActionEventRUMSyntheticsTest: NSObject @objc public var resultId: String @objc public var testId: String public class DDRUMActionEventRUMUser: NSObject + @objc public var anonymousId: String? @objc public var email: String? @objc public var id: String? @objc public var name: String? @@ -867,6 +868,7 @@ public class DDRUMErrorEventRUMSyntheticsTest: NSObject @objc public var resultId: String @objc public var testId: String public class DDRUMErrorEventRUMUser: NSObject + @objc public var anonymousId: String? @objc public var email: String? @objc public var id: String? @objc public var name: String? @@ -1061,6 +1063,7 @@ public class DDRUMLongTaskEventRUMSyntheticsTest: NSObject @objc public var resultId: String @objc public var testId: String public class DDRUMLongTaskEventRUMUser: NSObject + @objc public var anonymousId: String? @objc public var email: String? @objc public var id: String? @objc public var name: String? @@ -1327,6 +1330,7 @@ public class DDRUMResourceEventRUMSyntheticsTest: NSObject @objc public var resultId: String @objc public var testId: String public class DDRUMResourceEventRUMUser: NSObject + @objc public var anonymousId: String? @objc public var email: String? @objc public var id: String? @objc public var name: String? @@ -1512,6 +1516,7 @@ public class DDRUMViewEventRUMSyntheticsTest: NSObject @objc public var resultId: String @objc public var testId: String public class DDRUMViewEventRUMUser: NSObject + @objc public var anonymousId: String? @objc public var email: String? @objc public var id: String? @objc public var name: String? @@ -1750,6 +1755,7 @@ public class DDRUMVitalEventRUMSyntheticsTest: NSObject @objc public var resultId: String @objc public var testId: String public class DDRUMVitalEventRUMUser: NSObject + @objc public var anonymousId: String? @objc public var email: String? @objc public var id: String? @objc public var name: String? @@ -1911,6 +1917,7 @@ public class DDTelemetryConfigurationEventTelemetryConfiguration: NSObject @objc public var batchProcessingLevel: NSNumber? @objc public var batchSize: NSNumber? @objc public var batchUploadFrequency: NSNumber? + @objc public var collectFeatureFlagsOn: [Int]? @objc public var compressIntakeRequests: NSNumber? @objc public var dartVersion: String? @objc public var defaultPrivacyLevel: String? @@ -1975,6 +1982,11 @@ public class DDTelemetryConfigurationEventTelemetryConfiguration: NSObject @objc public var useTracing: NSNumber? @objc public var useWorkerUrl: NSNumber? @objc public var viewTrackingStrategy: DDTelemetryConfigurationEventTelemetryConfigurationViewTrackingStrategy +public enum DDTelemetryConfigurationEventTelemetryConfigurationCollectFeatureFlagsOn: Int + case none + case view + case error + case vital public class DDTelemetryConfigurationEventTelemetryConfigurationForwardConsoleLogs: NSObject @objc public var stringsArray: [String]? @objc public var string: String? diff --git a/api-surface-swift b/api-surface-swift index 988025f5cc..311e06211f 100644 --- a/api-surface-swift +++ b/api-surface-swift @@ -1244,7 +1244,7 @@ public struct TelemetryErrorEvent: RUMDataModel public let action: Action? public let application: Application? public let date: Int64 - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? public let experimentalFeatures: [String]? public let service: String public let session: Session? @@ -1290,7 +1290,7 @@ public struct TelemetryDebugEvent: RUMDataModel public let action: Action? public let application: Application? public let date: Int64 - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? public let experimentalFeatures: [String]? public let service: String public let session: Session? @@ -1332,7 +1332,7 @@ public struct TelemetryConfigurationEvent: RUMDataModel public let action: Action? public let application: Application? public let date: Int64 - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? public let experimentalFeatures: [String]? public let service: String public let session: Session? @@ -1372,6 +1372,7 @@ public struct TelemetryConfigurationEvent: RUMDataModel public let batchProcessingLevel: Int64? public let batchSize: Int64? public let batchUploadFrequency: Int64? + public let collectFeatureFlagsOn: [CollectFeatureFlagsOn]? public let compressIntakeRequests: Bool? public var dartVersion: String? public var defaultPrivacyLevel: String? @@ -1436,6 +1437,10 @@ public struct TelemetryConfigurationEvent: RUMDataModel public let useTracing: Bool? public let useWorkerUrl: Bool? public let viewTrackingStrategy: ViewTrackingStrategy? + public enum CollectFeatureFlagsOn: String, Codable + case view = "view" + case error = "error" + case vital = "vital" public enum ForwardConsoleLogs: Codable case stringsArray(value: [String]) case string(value: String) @@ -1479,7 +1484,7 @@ public struct TelemetryUsageEvent: RUMDataModel public let action: Action? public let application: Application? public let date: Int64 - public let effectiveSampleRate: Int64? + public let effectiveSampleRate: Double? public let experimentalFeatures: [String]? public let service: String public let session: Session? @@ -1631,6 +1636,7 @@ public struct RUMSyntheticsTest: Codable public let resultId: String public let testId: String public struct RUMUser: Codable + public let anonymousId: String? public let email: String? public let id: String? public let name: String?