From a33837fd7dbabe00ba86d7e59b473f6feecdeffc Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Mon, 22 Jan 2024 12:05:50 +0100 Subject: [PATCH 1/5] Add make option to generate RUM or SR models for certain commit of `rum-events-format` --- Makefile | 6 ++++-- tools/rum-models-generator/run.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 1dedd57754..f5e7907295 100644 --- a/Makefile +++ b/Makefile @@ -110,9 +110,10 @@ test-xcframeworks: @cd dependency-manager-tests/xcframeworks && $(MAKE) # Generate RUM data models from rum-events-format JSON Schemas +# - run with `git_ref=` argument to generate models for given schema commit or branch name (default is 'master'). rum-models-generate: @echo "⚙️ Generating RUM models..." - ./tools/rum-models-generator/run.py generate rum + ./tools/rum-models-generator/run.py generate rum --git_ref=$(if $(git_ref),$(git_ref),master) @echo "OK 👌" # Verify if RUM data models follow rum-events-format JSON Schemas @@ -122,9 +123,10 @@ rum-models-verify: @echo "OK 👌" # Generate Session Replay data models from rum-events-format JSON Schemas +# - run with `git_ref=` argument to generate models for given schema commit or branch name (default is 'master'). sr-models-generate: @echo "⚙️ Generating Session Replay models..." - ./tools/rum-models-generator/run.py generate sr + ./tools/rum-models-generator/run.py generate sr --git_ref=$(if $(git_ref),$(git_ref),master) @echo "OK 👌" # Verify if Session Replay data models follow rum-events-format JSON Schemas diff --git a/tools/rum-models-generator/run.py b/tools/rum-models-generator/run.py index ebadc2fa21..bb5b4dd7b6 100755 --- a/tools/rum-models-generator/run.py +++ b/tools/rum-models-generator/run.py @@ -37,6 +37,9 @@ class Context: # Resolved path to JSON schema describing Session Replay events sr_schema_path: str + # Git reference to clone schemas repo at. + git_ref: str + # Resolved path to source code file with RUM model definitions (Swift) rum_swift_generated_file_path: str @@ -50,6 +53,7 @@ def __repr__(self): return f""" - cli_executable_path = {self.cli_executable_path}, - rum_schema_path = {self.rum_schema_path} + - git_ref = {self.git_ref} - sr_schema_path = {self.sr_schema_path} - rum_swift_generated_file_path = {self.rum_swift_generated_file_path} - rum_objc_generated_file_path = {self.rum_objc_generated_file_path} @@ -159,7 +163,7 @@ def validate_code(ctx: Context, language: str, convention: str, json_schema: str def generate_rum_models(ctx: Context): - sha = clone_schemas_repo(git_ref='master') + sha = clone_schemas_repo(git_ref=ctx.git_ref) with open(ctx.rum_swift_generated_file_path, 'w') as file: code = generate_code(ctx, language='swift', convention='rum', json_schema=ctx.rum_schema_path, git_sha=sha) @@ -171,7 +175,7 @@ def generate_rum_models(ctx: Context): def generate_sr_models(ctx: Context): - sha = clone_schemas_repo(git_ref='master') + sha = clone_schemas_repo(git_ref=ctx.git_ref) with open(ctx.sr_swift_generated_file_path, 'w') as file: code = generate_code(ctx, language='swift', convention='sr', json_schema=ctx.sr_schema_path, git_sha=sha) @@ -213,6 +217,7 @@ def validate_sr_models(ctx: Context): parser = argparse.ArgumentParser() parser.add_argument("command", choices=['generate', 'verify'], help="Run mode") parser.add_argument("product", choices=['rum', 'sr'], help="Either 'rum' (RUM) or 'sr' (Session Replay)") + parser.add_argument("--git_ref", help="The git reference to clone `rum-events-format` repo at (only effective for `generate` command).") args = parser.parse_args() try: @@ -220,6 +225,7 @@ def validate_sr_models(ctx: Context): cli_executable_path=build_swift_cli(), rum_schema_path=os.path.abspath(f'{script_dir}/{RUM_SCHEMA_PATH}'), sr_schema_path=os.path.abspath(f'{script_dir}/{SR_SCHEMA_PATH}'), + git_ref=args.git_ref if args.command else None, rum_swift_generated_file_path=os.path.abspath(f'{repository_root}/{RUM_SWIFT_GENERATED_FILE_PATH}'), rum_objc_generated_file_path=os.path.abspath(f'{repository_root}/{RUM_OBJC_GENERATED_FILE_PATH}'), sr_swift_generated_file_path=os.path.abspath(f'{repository_root}/{SR_SWIFT_GENERATED_FILE_PATH}'), From 8b13817f361eb50db61a3ae26ea62458f38ec999 Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Mon, 22 Jan 2024 12:32:06 +0100 Subject: [PATCH 2/5] [RUM models generation] Support enum cases that start with digits --- .../Swift/JSONToSwiftTypeTransformer.swift | 11 +- .../JSONToSwiftTypeTransformerTests.swift | 108 ++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift b/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift index 9122f3379a..84b6adb1b6 100644 --- a/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift +++ b/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift @@ -92,8 +92,17 @@ internal class JSONToSwiftTypeTransformer { cases: jsonEnumeration.values.map { value in switch value { case .string(let value): - return SwiftEnum.Case(label: value, rawValue: .string(value: value)) + // In Swift, enum case names cannot start with digits. In such situation prefix the + // case with the name of enumeration so it is transformed into valid `SwiftEnum.Case`. + var labelValue = value + if let first = value.first?.unicodeScalars.first, CharacterSet.decimalDigits.contains(first) { + labelValue = "\(jsonEnumeration.name)\(value)" + } + + return SwiftEnum.Case(label: labelValue, rawValue: .string(value: value)) case .integer(let value): + // In Swift, enum case names cannot start with digits, so prefix the case with the name + // of enumeration so it is transformed into valid `SwiftEnum.Case`. return SwiftEnum.Case(label: "\(jsonEnumeration.name)\(value)", rawValue: .integer(value: value)) } }, diff --git a/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift b/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift index 442255718a..7e183c5a06 100644 --- a/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift +++ b/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift @@ -158,6 +158,114 @@ final class JSONToSwiftTypeTransformerTests: XCTestCase { XCTAssertEqual(expected, actual[0]) } + func testTransformingJSONObjectWithStringEnumerationIntoSwiftStruct() throws { + let object = JSONObject( + name: "Container", + comment: nil, + properties: [ + JSONObject.Property( + name: "enumeration", + comment: nil, + type: JSONEnumeration( + name: "Foo", + comment: "Description of Foo", + values: [ + .string(value: "case1"), + .string(value: "case2"), + .string(value: "3case"), // case name starting with number + .string(value: "4case"), + ] + ), + defaultValue: nil, + isRequired: false, + isReadOnly: false + ) + ] + ) + + let expected = SwiftStruct( + name: "Container", + properties: [ + SwiftStruct.Property( + name: "enumeration", + type: SwiftEnum( + name: "Foo", + comment: "Description of Foo", + cases: [ + SwiftEnum.Case(label: "case1", rawValue: .string(value: "case1")), + SwiftEnum.Case(label: "case2", rawValue: .string(value: "case2")), + SwiftEnum.Case(label: "Foo3case", rawValue: .string(value: "3case")), + SwiftEnum.Case(label: "Foo4case", rawValue: .string(value: "4case")), + ], + conformance: [] + ), + isOptional: true, + mutability: .mutable, + codingKey: .static(value: "enumeration") + ) + ], + conformance: [] + ) + + let actual = try JSONToSwiftTypeTransformer().transform(jsonType: object) + + XCTAssertEqual(actual.count, 1) + XCTAssertEqual(expected, actual[0]) + } + + func testTransformingJSONObjectWithIntegerEnumerationIntoSwiftStruct() throws { + let object = JSONObject( + name: "Container", + comment: nil, + properties: [ + JSONObject.Property( + name: "enumeration", + comment: nil, + type: JSONEnumeration( + name: "Foo", + comment: "Description of Foo", + values: [ + .integer(value: 1), + .integer(value: 2), + .integer(value: 3), + ] + ), + defaultValue: nil, + isRequired: false, + isReadOnly: false + ) + ] + ) + + let expected = SwiftStruct( + name: "Container", + properties: [ + SwiftStruct.Property( + name: "enumeration", + type: SwiftEnum( + name: "Foo", + comment: "Description of Foo", + cases: [ + SwiftEnum.Case(label: "Foo1", rawValue: .integer(value: 1)), + SwiftEnum.Case(label: "Foo2", rawValue: .integer(value: 2)), + SwiftEnum.Case(label: "Foo3", rawValue: .integer(value: 3)), + ], + conformance: [] + ), + isOptional: true, + mutability: .mutable, + codingKey: .static(value: "enumeration") + ) + ], + conformance: [] + ) + + let actual = try JSONToSwiftTypeTransformer().transform(jsonType: object) + + XCTAssertEqual(actual.count, 1) + XCTAssertEqual(expected, actual[0]) + } + // MARK: - Transforming `additionalProperties` func testTransformingNestedJSONObjectWithIntAdditionalPropertiesIntoSwiftDictionaryInsideRootStruct() throws { From 5b060f9a88ad8ea56666e16ab31ef78c7821fbaf Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Mon, 22 Jan 2024 12:51:41 +0100 Subject: [PATCH 3/5] [RUM models generation] Fix optionality for enum cases named as "none" as it was causing compiler ambiguity with `Optional.none`. --- .../Transformers/Swift/JSONToSwiftTypeTransformer.swift | 8 +++++++- .../Transformers/JSONToSwiftTypeTransformerTests.swift | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift b/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift index 84b6adb1b6..c2eb817ba9 100644 --- a/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift +++ b/tools/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/JSONToSwiftTypeTransformer.swift @@ -96,7 +96,13 @@ internal class JSONToSwiftTypeTransformer { // case with the name of enumeration so it is transformed into valid `SwiftEnum.Case`. var labelValue = value if let first = value.first?.unicodeScalars.first, CharacterSet.decimalDigits.contains(first) { - labelValue = "\(jsonEnumeration.name)\(value)" + labelValue = "\(jsonEnumeration.name.lowercasingFirst)\(value)" + } + // In Swift, naming case a "none" might clash with `Optional.none` type if the property of + // this enum value is declared as optional. For that reason, prefix "none" case with the + // name of enumeration to avoid compiler ambiguity. + if labelValue == "none" { + labelValue = "\(jsonEnumeration.name.lowercasingFirst)\(labelValue.uppercasingFirst)" } return SwiftEnum.Case(label: labelValue, rawValue: .string(value: value)) diff --git a/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift b/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift index 7e183c5a06..8ade6d58e6 100644 --- a/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift +++ b/tools/rum-models-generator/Tests/CodeGenerationTests/Generate/Transformers/JSONToSwiftTypeTransformerTests.swift @@ -173,7 +173,7 @@ final class JSONToSwiftTypeTransformerTests: XCTestCase { .string(value: "case1"), .string(value: "case2"), .string(value: "3case"), // case name starting with number - .string(value: "4case"), + .string(value: "none"), // explicit case named as "none" ] ), defaultValue: nil, @@ -194,8 +194,8 @@ final class JSONToSwiftTypeTransformerTests: XCTestCase { cases: [ SwiftEnum.Case(label: "case1", rawValue: .string(value: "case1")), SwiftEnum.Case(label: "case2", rawValue: .string(value: "case2")), - SwiftEnum.Case(label: "Foo3case", rawValue: .string(value: "3case")), - SwiftEnum.Case(label: "Foo4case", rawValue: .string(value: "4case")), + SwiftEnum.Case(label: "foo3case", rawValue: .string(value: "3case")), + SwiftEnum.Case(label: "fooNone", rawValue: .string(value: "none")), ], conformance: [] ), From ff78c4835a597a59a6df043d2743d1e8224983f2 Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Mon, 22 Jan 2024 13:00:44 +0100 Subject: [PATCH 4/5] Update RUM models (`make rum-models-generate`) --- .../Sources/RUM/RUMDataModels+objc.swift | 332 ++++++++++++++---- .../Sources/DataModels/RUMDataModels.swift | 18 +- 2 files changed, 271 insertions(+), 79 deletions(-) diff --git a/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift b/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift index 05b84a218b..b18e9c6268 100644 --- a/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift +++ b/DatadogObjc/Sources/RUM/RUMDataModels+objc.swift @@ -510,8 +510,12 @@ public class DDRUMActionEventRUMConnectivity: NSObject { root.swiftModel.connectivity!.cellular != nil ? DDRUMActionEventRUMConnectivityCellular(root: root) : nil } - @objc public var interfaces: [Int] { - root.swiftModel.connectivity!.interfaces.map { DDRUMActionEventRUMConnectivityInterfaces(swift: $0).rawValue } + @objc public var effectiveType: DDRUMActionEventRUMConnectivityEffectiveType { + .init(swift: root.swiftModel.connectivity!.effectiveType) + } + + @objc public var interfaces: [Int]? { + root.swiftModel.connectivity!.interfaces?.map { DDRUMActionEventRUMConnectivityInterfaces(swift: $0).rawValue } } @objc public var status: DDRUMActionEventRUMConnectivityStatus { @@ -536,24 +540,55 @@ public class DDRUMActionEventRUMConnectivityCellular: NSObject { } } +@objc +public enum DDRUMActionEventRUMConnectivityEffectiveType: Int { + internal init(swift: RUMConnectivity.EffectiveType?) { + switch swift { + case nil: self = .none + case .slow2g?: self = .slow2g + case .effectiveType2g?: self = .effectiveType2g + case .effectiveType3g?: self = .effectiveType3g + case .effectiveType4g?: self = .effectiveType4g + } + } + + internal var toSwift: RUMConnectivity.EffectiveType? { + switch self { + case .none: return nil + case .slow2g: return .slow2g + case .effectiveType2g: return .effectiveType2g + case .effectiveType3g: return .effectiveType3g + case .effectiveType4g: return .effectiveType4g + } + } + + case none + case slow2g + case effectiveType2g + case effectiveType3g + case effectiveType4g +} + @objc public enum DDRUMActionEventRUMConnectivityInterfaces: Int { - internal init(swift: RUMConnectivity.Interfaces) { + internal init(swift: RUMConnectivity.Interfaces?) { switch swift { - case .bluetooth: self = .bluetooth - case .cellular: self = .cellular - case .ethernet: self = .ethernet - case .wifi: self = .wifi - case .wimax: self = .wimax - case .mixed: self = .mixed - case .other: self = .other - case .unknown: self = .unknown - case .none: self = .none + case nil: self = .none + case .bluetooth?: self = .bluetooth + case .cellular?: self = .cellular + case .ethernet?: self = .ethernet + case .wifi?: self = .wifi + case .wimax?: self = .wimax + case .mixed?: self = .mixed + case .other?: self = .other + case .unknown?: self = .unknown + case .interfacesNone?: self = .interfacesNone } } - internal var toSwift: RUMConnectivity.Interfaces { + internal var toSwift: RUMConnectivity.Interfaces? { switch self { + case .none: return nil case .bluetooth: return .bluetooth case .cellular: return .cellular case .ethernet: return .ethernet @@ -562,10 +597,11 @@ public enum DDRUMActionEventRUMConnectivityInterfaces: Int { case .mixed: return .mixed case .other: return .other case .unknown: return .unknown - case .none: return .none + case .interfacesNone: return .interfacesNone } } + case none case bluetooth case cellular case ethernet @@ -574,7 +610,7 @@ public enum DDRUMActionEventRUMConnectivityInterfaces: Int { case mixed case other case unknown - case none + case interfacesNone } @objc @@ -1253,8 +1289,12 @@ public class DDRUMErrorEventRUMConnectivity: NSObject { root.swiftModel.connectivity!.cellular != nil ? DDRUMErrorEventRUMConnectivityCellular(root: root) : nil } - @objc public var interfaces: [Int] { - root.swiftModel.connectivity!.interfaces.map { DDRUMErrorEventRUMConnectivityInterfaces(swift: $0).rawValue } + @objc public var effectiveType: DDRUMErrorEventRUMConnectivityEffectiveType { + .init(swift: root.swiftModel.connectivity!.effectiveType) + } + + @objc public var interfaces: [Int]? { + root.swiftModel.connectivity!.interfaces?.map { DDRUMErrorEventRUMConnectivityInterfaces(swift: $0).rawValue } } @objc public var status: DDRUMErrorEventRUMConnectivityStatus { @@ -1279,24 +1319,55 @@ public class DDRUMErrorEventRUMConnectivityCellular: NSObject { } } +@objc +public enum DDRUMErrorEventRUMConnectivityEffectiveType: Int { + internal init(swift: RUMConnectivity.EffectiveType?) { + switch swift { + case nil: self = .none + case .slow2g?: self = .slow2g + case .effectiveType2g?: self = .effectiveType2g + case .effectiveType3g?: self = .effectiveType3g + case .effectiveType4g?: self = .effectiveType4g + } + } + + internal var toSwift: RUMConnectivity.EffectiveType? { + switch self { + case .none: return nil + case .slow2g: return .slow2g + case .effectiveType2g: return .effectiveType2g + case .effectiveType3g: return .effectiveType3g + case .effectiveType4g: return .effectiveType4g + } + } + + case none + case slow2g + case effectiveType2g + case effectiveType3g + case effectiveType4g +} + @objc public enum DDRUMErrorEventRUMConnectivityInterfaces: Int { - internal init(swift: RUMConnectivity.Interfaces) { + internal init(swift: RUMConnectivity.Interfaces?) { switch swift { - case .bluetooth: self = .bluetooth - case .cellular: self = .cellular - case .ethernet: self = .ethernet - case .wifi: self = .wifi - case .wimax: self = .wimax - case .mixed: self = .mixed - case .other: self = .other - case .unknown: self = .unknown - case .none: self = .none + case nil: self = .none + case .bluetooth?: self = .bluetooth + case .cellular?: self = .cellular + case .ethernet?: self = .ethernet + case .wifi?: self = .wifi + case .wimax?: self = .wimax + case .mixed?: self = .mixed + case .other?: self = .other + case .unknown?: self = .unknown + case .interfacesNone?: self = .interfacesNone } } - internal var toSwift: RUMConnectivity.Interfaces { + internal var toSwift: RUMConnectivity.Interfaces? { switch self { + case .none: return nil case .bluetooth: return .bluetooth case .cellular: return .cellular case .ethernet: return .ethernet @@ -1305,10 +1376,11 @@ public enum DDRUMErrorEventRUMConnectivityInterfaces: Int { case .mixed: return .mixed case .other: return .other case .unknown: return .unknown - case .none: return .none + case .interfacesNone: return .interfacesNone } } + case none case bluetooth case cellular case ethernet @@ -1317,7 +1389,7 @@ public enum DDRUMErrorEventRUMConnectivityInterfaces: Int { case mixed case other case unknown - case none + case interfacesNone } @objc @@ -2370,8 +2442,12 @@ public class DDRUMLongTaskEventRUMConnectivity: NSObject { root.swiftModel.connectivity!.cellular != nil ? DDRUMLongTaskEventRUMConnectivityCellular(root: root) : nil } - @objc public var interfaces: [Int] { - root.swiftModel.connectivity!.interfaces.map { DDRUMLongTaskEventRUMConnectivityInterfaces(swift: $0).rawValue } + @objc public var effectiveType: DDRUMLongTaskEventRUMConnectivityEffectiveType { + .init(swift: root.swiftModel.connectivity!.effectiveType) + } + + @objc public var interfaces: [Int]? { + root.swiftModel.connectivity!.interfaces?.map { DDRUMLongTaskEventRUMConnectivityInterfaces(swift: $0).rawValue } } @objc public var status: DDRUMLongTaskEventRUMConnectivityStatus { @@ -2396,24 +2472,55 @@ public class DDRUMLongTaskEventRUMConnectivityCellular: NSObject { } } +@objc +public enum DDRUMLongTaskEventRUMConnectivityEffectiveType: Int { + internal init(swift: RUMConnectivity.EffectiveType?) { + switch swift { + case nil: self = .none + case .slow2g?: self = .slow2g + case .effectiveType2g?: self = .effectiveType2g + case .effectiveType3g?: self = .effectiveType3g + case .effectiveType4g?: self = .effectiveType4g + } + } + + internal var toSwift: RUMConnectivity.EffectiveType? { + switch self { + case .none: return nil + case .slow2g: return .slow2g + case .effectiveType2g: return .effectiveType2g + case .effectiveType3g: return .effectiveType3g + case .effectiveType4g: return .effectiveType4g + } + } + + case none + case slow2g + case effectiveType2g + case effectiveType3g + case effectiveType4g +} + @objc public enum DDRUMLongTaskEventRUMConnectivityInterfaces: Int { - internal init(swift: RUMConnectivity.Interfaces) { + internal init(swift: RUMConnectivity.Interfaces?) { switch swift { - case .bluetooth: self = .bluetooth - case .cellular: self = .cellular - case .ethernet: self = .ethernet - case .wifi: self = .wifi - case .wimax: self = .wimax - case .mixed: self = .mixed - case .other: self = .other - case .unknown: self = .unknown - case .none: self = .none + case nil: self = .none + case .bluetooth?: self = .bluetooth + case .cellular?: self = .cellular + case .ethernet?: self = .ethernet + case .wifi?: self = .wifi + case .wimax?: self = .wimax + case .mixed?: self = .mixed + case .other?: self = .other + case .unknown?: self = .unknown + case .interfacesNone?: self = .interfacesNone } } - internal var toSwift: RUMConnectivity.Interfaces { + internal var toSwift: RUMConnectivity.Interfaces? { switch self { + case .none: return nil case .bluetooth: return .bluetooth case .cellular: return .cellular case .ethernet: return .ethernet @@ -2422,10 +2529,11 @@ public enum DDRUMLongTaskEventRUMConnectivityInterfaces: Int { case .mixed: return .mixed case .other: return .other case .unknown: return .unknown - case .none: return .none + case .interfacesNone: return .interfacesNone } } + case none case bluetooth case cellular case ethernet @@ -2434,7 +2542,7 @@ public enum DDRUMLongTaskEventRUMConnectivityInterfaces: Int { case mixed case other case unknown - case none + case interfacesNone } @objc @@ -3142,8 +3250,12 @@ public class DDRUMResourceEventRUMConnectivity: NSObject { root.swiftModel.connectivity!.cellular != nil ? DDRUMResourceEventRUMConnectivityCellular(root: root) : nil } - @objc public var interfaces: [Int] { - root.swiftModel.connectivity!.interfaces.map { DDRUMResourceEventRUMConnectivityInterfaces(swift: $0).rawValue } + @objc public var effectiveType: DDRUMResourceEventRUMConnectivityEffectiveType { + .init(swift: root.swiftModel.connectivity!.effectiveType) + } + + @objc public var interfaces: [Int]? { + root.swiftModel.connectivity!.interfaces?.map { DDRUMResourceEventRUMConnectivityInterfaces(swift: $0).rawValue } } @objc public var status: DDRUMResourceEventRUMConnectivityStatus { @@ -3168,24 +3280,55 @@ public class DDRUMResourceEventRUMConnectivityCellular: NSObject { } } +@objc +public enum DDRUMResourceEventRUMConnectivityEffectiveType: Int { + internal init(swift: RUMConnectivity.EffectiveType?) { + switch swift { + case nil: self = .none + case .slow2g?: self = .slow2g + case .effectiveType2g?: self = .effectiveType2g + case .effectiveType3g?: self = .effectiveType3g + case .effectiveType4g?: self = .effectiveType4g + } + } + + internal var toSwift: RUMConnectivity.EffectiveType? { + switch self { + case .none: return nil + case .slow2g: return .slow2g + case .effectiveType2g: return .effectiveType2g + case .effectiveType3g: return .effectiveType3g + case .effectiveType4g: return .effectiveType4g + } + } + + case none + case slow2g + case effectiveType2g + case effectiveType3g + case effectiveType4g +} + @objc public enum DDRUMResourceEventRUMConnectivityInterfaces: Int { - internal init(swift: RUMConnectivity.Interfaces) { + internal init(swift: RUMConnectivity.Interfaces?) { switch swift { - case .bluetooth: self = .bluetooth - case .cellular: self = .cellular - case .ethernet: self = .ethernet - case .wifi: self = .wifi - case .wimax: self = .wimax - case .mixed: self = .mixed - case .other: self = .other - case .unknown: self = .unknown - case .none: self = .none + case nil: self = .none + case .bluetooth?: self = .bluetooth + case .cellular?: self = .cellular + case .ethernet?: self = .ethernet + case .wifi?: self = .wifi + case .wimax?: self = .wimax + case .mixed?: self = .mixed + case .other?: self = .other + case .unknown?: self = .unknown + case .interfacesNone?: self = .interfacesNone } } - internal var toSwift: RUMConnectivity.Interfaces { + internal var toSwift: RUMConnectivity.Interfaces? { switch self { + case .none: return nil case .bluetooth: return .bluetooth case .cellular: return .cellular case .ethernet: return .ethernet @@ -3194,10 +3337,11 @@ public enum DDRUMResourceEventRUMConnectivityInterfaces: Int { case .mixed: return .mixed case .other: return .other case .unknown: return .unknown - case .none: return .none + case .interfacesNone: return .interfacesNone } } + case none case bluetooth case cellular case ethernet @@ -3206,7 +3350,7 @@ public enum DDRUMResourceEventRUMConnectivityInterfaces: Int { case mixed case other case unknown - case none + case interfacesNone } @objc @@ -4309,8 +4453,12 @@ public class DDRUMViewEventRUMConnectivity: NSObject { root.swiftModel.connectivity!.cellular != nil ? DDRUMViewEventRUMConnectivityCellular(root: root) : nil } - @objc public var interfaces: [Int] { - root.swiftModel.connectivity!.interfaces.map { DDRUMViewEventRUMConnectivityInterfaces(swift: $0).rawValue } + @objc public var effectiveType: DDRUMViewEventRUMConnectivityEffectiveType { + .init(swift: root.swiftModel.connectivity!.effectiveType) + } + + @objc public var interfaces: [Int]? { + root.swiftModel.connectivity!.interfaces?.map { DDRUMViewEventRUMConnectivityInterfaces(swift: $0).rawValue } } @objc public var status: DDRUMViewEventRUMConnectivityStatus { @@ -4335,24 +4483,55 @@ public class DDRUMViewEventRUMConnectivityCellular: NSObject { } } +@objc +public enum DDRUMViewEventRUMConnectivityEffectiveType: Int { + internal init(swift: RUMConnectivity.EffectiveType?) { + switch swift { + case nil: self = .none + case .slow2g?: self = .slow2g + case .effectiveType2g?: self = .effectiveType2g + case .effectiveType3g?: self = .effectiveType3g + case .effectiveType4g?: self = .effectiveType4g + } + } + + internal var toSwift: RUMConnectivity.EffectiveType? { + switch self { + case .none: return nil + case .slow2g: return .slow2g + case .effectiveType2g: return .effectiveType2g + case .effectiveType3g: return .effectiveType3g + case .effectiveType4g: return .effectiveType4g + } + } + + case none + case slow2g + case effectiveType2g + case effectiveType3g + case effectiveType4g +} + @objc public enum DDRUMViewEventRUMConnectivityInterfaces: Int { - internal init(swift: RUMConnectivity.Interfaces) { + internal init(swift: RUMConnectivity.Interfaces?) { switch swift { - case .bluetooth: self = .bluetooth - case .cellular: self = .cellular - case .ethernet: self = .ethernet - case .wifi: self = .wifi - case .wimax: self = .wimax - case .mixed: self = .mixed - case .other: self = .other - case .unknown: self = .unknown - case .none: self = .none + case nil: self = .none + case .bluetooth?: self = .bluetooth + case .cellular?: self = .cellular + case .ethernet?: self = .ethernet + case .wifi?: self = .wifi + case .wimax?: self = .wimax + case .mixed?: self = .mixed + case .other?: self = .other + case .unknown?: self = .unknown + case .interfacesNone?: self = .interfacesNone } } - internal var toSwift: RUMConnectivity.Interfaces { + internal var toSwift: RUMConnectivity.Interfaces? { switch self { + case .none: return nil case .bluetooth: return .bluetooth case .cellular: return .cellular case .ethernet: return .ethernet @@ -4361,10 +4540,11 @@ public enum DDRUMViewEventRUMConnectivityInterfaces: Int { case .mixed: return .mixed case .other: return .other case .unknown: return .unknown - case .none: return .none + case .interfacesNone: return .interfacesNone } } + case none case bluetooth case cellular case ethernet @@ -4373,7 +4553,7 @@ public enum DDRUMViewEventRUMConnectivityInterfaces: Int { case mixed case other case unknown - case none + case interfacesNone } @objc @@ -6123,4 +6303,4 @@ public class DDTelemetryConfigurationEventView: NSObject { // swiftlint:enable force_unwrapping -// Generated from https://github.com/DataDog/rum-events-format/tree/83f8760b46e9a117b5975cfb592b1803d643ee3e +// Generated from https://github.com/DataDog/rum-events-format/tree/389581be98dcf8efbfcfe7bffaa32d53f960fb6f diff --git a/DatadogRUM/Sources/DataModels/RUMDataModels.swift b/DatadogRUM/Sources/DataModels/RUMDataModels.swift index a1b747f1ed..c499e6e7a8 100644 --- a/DatadogRUM/Sources/DataModels/RUMDataModels.swift +++ b/DatadogRUM/Sources/DataModels/RUMDataModels.swift @@ -3287,14 +3287,18 @@ public struct RUMConnectivity: Codable { /// Cellular connectivity properties public let cellular: Cellular? + /// Cellular connection type reflecting the measured network performance + public let effectiveType: EffectiveType? + /// The list of available network interfaces - public let interfaces: [Interfaces] + public let interfaces: [Interfaces]? /// Status of the device connectivity public let status: Status enum CodingKeys: String, CodingKey { case cellular = "cellular" + case effectiveType = "effective_type" case interfaces = "interfaces" case status = "status" } @@ -3313,6 +3317,14 @@ public struct RUMConnectivity: Codable { } } + /// Cellular connection type reflecting the measured network performance + public enum EffectiveType: String, Codable { + case slow2g = "slow_2g" + case effectiveType2g = "2g" + case effectiveType3g = "3g" + case effectiveType4g = "4g" + } + public enum Interfaces: String, Codable { case bluetooth = "bluetooth" case cellular = "cellular" @@ -3322,7 +3334,7 @@ public struct RUMConnectivity: Codable { case mixed = "mixed" case other = "other" case unknown = "unknown" - case none = "none" + case interfacesNone = "none" } /// Status of the device connectivity @@ -3555,4 +3567,4 @@ public enum RUMMethod: String, Codable { case patch = "PATCH" } -// Generated from https://github.com/DataDog/rum-events-format/tree/83f8760b46e9a117b5975cfb592b1803d643ee3e +// Generated from https://github.com/DataDog/rum-events-format/tree/389581be98dcf8efbfcfe7bffaa32d53f960fb6f From 9334f28c503e2a931b6d59a37b420d6ba55a9beb Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Mon, 22 Jan 2024 13:02:44 +0100 Subject: [PATCH 5/5] Make RUM compile for updated RUM models --- DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift | 1 + DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift | 1 + DatadogRUM/Sources/RUMEvent/RUMConnectivityInfoProvider.swift | 3 ++- DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift b/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift index 4f77e9b098..af2928cb53 100644 --- a/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift +++ b/DatadogCore/Tests/Datadog/Mocks/RUMDataModelMocks.swift @@ -26,6 +26,7 @@ extension RUMConnectivity { carrierName: .mockRandom(), technology: .mockRandom() ), + effectiveType: nil, interfaces: [.bluetooth, .cellular].randomElements(), status: [.connected, .maybe, .notConnected].randomElement()! ) diff --git a/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift b/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift index 9dcf403544..e10170d75e 100644 --- a/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift +++ b/DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift @@ -690,6 +690,7 @@ class RUMMonitorTests: XCTestCase { let rumEventMatchers = try core.waitAndReturnRUMEventMatchers() let expectedConnectivityInfo = RUMConnectivity( cellular: RUMConnectivity.Cellular(carrierName: "Carrier Name", technology: "GPRS"), + effectiveType: nil, interfaces: [.cellular], status: .connected ) diff --git a/DatadogRUM/Sources/RUMEvent/RUMConnectivityInfoProvider.swift b/DatadogRUM/Sources/RUMEvent/RUMConnectivityInfoProvider.swift index 8eb7887a96..4a6c980363 100644 --- a/DatadogRUM/Sources/RUMEvent/RUMConnectivityInfoProvider.swift +++ b/DatadogRUM/Sources/RUMEvent/RUMConnectivityInfoProvider.swift @@ -22,6 +22,7 @@ extension RUMConnectivity { self.init( cellular: carrierInfo.flatMap { RUMConnectivity.connectivityCellularInfo(for: $0) }, + effectiveType: nil, interfaces: RUMConnectivity.connectivityInterfaces(for: networkInfo), status: RUMConnectivity.connectivityStatus(for: networkInfo) ) @@ -39,7 +40,7 @@ extension RUMConnectivity { private static func connectivityInterfaces(for networkInfo: NetworkConnectionInfo) -> [RUMConnectivity.Interfaces] { guard let availableInterfaces = networkInfo.availableInterfaces, !availableInterfaces.isEmpty else { - return [.none] + return [.interfacesNone] } return availableInterfaces.map { interface in diff --git a/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift b/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift index ab2dea5e77..a523f86be6 100644 --- a/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift +++ b/DatadogRUM/Tests/Mocks/RUMDataModelMocks.swift @@ -39,6 +39,7 @@ extension RUMConnectivity: RandomMockable { carrierName: .mockRandom(), technology: .mockRandom() ), + effectiveType: nil, interfaces: [.bluetooth, .cellular].randomElements(), status: [.connected, .maybe, .notConnected].randomElement()! )