Skip to content

Commit

Permalink
fix(ios): data ingestion failure
Browse files Browse the repository at this point in the history
* refactor(ios): update example apps bundle id

* refactor(ios): make all uuids lowercased

* refactor(ios): update request json to default to empty string instead of null

* refactor(ios): update view_name to class_name

* fix(ios): ignore native view controller tracking

* refactor(ios): remove cyclic navigation from example apps

* fix(ios): generate accurate thread name

* chore(ios): add missing attributes

* chore(ios): add sessionator data
  • Loading branch information
adwinross authored Dec 18, 2024
1 parent dfa99e1 commit 92f1f03
Show file tree
Hide file tree
Showing 50 changed files with 137 additions and 96 deletions.
20 changes: 2 additions & 18 deletions ios/DemoApp/Controller/ObjcDetailViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ - (UIView *)createTableHeaderView {
// Create the header view
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 100)];

NSArray *buttonTitles = @[@"SwiftUI Controller", @"Swift Controller", @"Objc Controller", @"Collection Controller"];
NSArray *buttonTitles = @[@"SwiftUI Controller", @"Collection Controller"];

// Create two vertical stack views
UIStackView *verticalStackView1 = [[UIStackView alloc] init];
Expand All @@ -78,7 +78,7 @@ - (UIView *)createTableHeaderView {
button.tag = i;
[button addTarget:self action:@selector(headerButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

if (i < 2) {
if (i % 2 == 0) {
[verticalStackView1 addArrangedSubview:button];
} else {
[verticalStackView2 addArrangedSubview:button];
Expand Down Expand Up @@ -113,29 +113,13 @@ - (void)headerButtonTapped:(UIButton *)sender {
[self navigateToSwiftUIView];
break;
case 1:
[self transitionToSwiftViewController];
break;
case 2:
[self transitionToObjcViewController];
break;
case 3:
[self transitionToCollectionViewController];
break;
default:
break;
}
}

-(void)transitionToObjcViewController {
ObjcDetailViewController *controller = [[ObjcDetailViewController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
}

-(void)transitionToSwiftViewController {
ViewController *controller = [[ViewController alloc] init];
[[self navigationController] pushViewController:controller animated:YES];
}

-(void)transitionToCollectionViewController {
CollectionViewController *controller = [[CollectionViewController alloc] init];
[[self navigationController] pushViewController:controller animated:YES];
Expand Down
36 changes: 11 additions & 25 deletions ios/DemoApp/Controller/SwiftUIDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Adwin Ross on 27/09/24.
//

import MeasureSDK
import SwiftUI
import UIKit

Expand All @@ -27,34 +28,19 @@ struct SwiftUIDetailViewController: View {
]

var body: some View {
NavigationView {
VStack {
headerView

List(crashTypes, id: \.self) { crashType in
Text(crashType)
.onTapGesture {
triggerCrash(type: crashType)
}
MsrMoniterView("DetailListView") {
NavigationView {
VStack {
List(crashTypes, id: \.self) { crashType in
Text(crashType)
.onTapGesture {
triggerCrash(type: crashType)
}
}
.navigationBarTitle("SwiftUI View Controller", displayMode: .inline)
}
.navigationBarTitle("SwiftUI View Controller", displayMode: .inline)
}
}
}

var headerView: some View {
HStack(spacing: 10) {
Button("Swift Controller") {
pushViewController(ViewController())
}
.frame(maxWidth: .infinity)

Button("ObjC Controller") {
pushViewController(ObjcDetailViewController())
}
.frame(maxWidth: .infinity)
}
.padding()
}

// MARK: - Crash Triggers
Expand Down
9 changes: 3 additions & 6 deletions ios/DemoApp/Controller/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import MeasureSDK
func createTableHeaderView() -> UIView {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 150))

let buttonTitles = ["SwiftUI Controller", "Swift Controller", "Objc Controller", "Collection Controller", "System Controls"]
let buttonTitles = ["SwiftUI Controller", "Objc Controller", "Collection Controller", "System Controls"]

// Create vertical stack views to hold two buttons each
let verticalStackView1 = UIStackView()
Expand Down Expand Up @@ -103,15 +103,12 @@ import MeasureSDK
let hostingController = UIHostingController(rootView: swiftUIView)
self.navigationController?.pushViewController(hostingController, animated: true)
case 1:
let controller = ViewController()
self.navigationController?.pushViewController(controller, animated: true)
case 2:
let controller = ObjcDetailViewController()
self.navigationController?.pushViewController(controller, animated: true)
case 3:
case 2:
let controller = CollectionViewController()
self.navigationController?.pushViewController(controller, animated: true)
case 4:
case 3:
if let controller = self.storyboard?.instantiateViewController(withIdentifier: "ControlsViewController") {
self.navigationController?.pushViewController(controller, animated: true)
}
Expand Down
12 changes: 6 additions & 6 deletions ios/MeasureSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,7 @@
);
MARKETING_VERSION = 1.0;
OTHER_SWIFT_FLAGS = "-DINTERNAL_LOGGING";
PRODUCT_BUNDLE_IDENTIFIER = com.measure.TestApp;
PRODUCT_BUNDLE_IDENTIFIER = sh.measure.TestApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
Expand All @@ -1867,7 +1867,7 @@
);
MARKETING_VERSION = 1.0;
OTHER_SWIFT_FLAGS = "-DINTERNAL_LOGGING";
PRODUCT_BUNDLE_IDENTIFIER = com.measure.TestApp;
PRODUCT_BUNDLE_IDENTIFIER = sh.measure.TestApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
Expand Down Expand Up @@ -1927,7 +1927,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.measure.SwiftUIDemo;
PRODUCT_BUNDLE_IDENTIFIER = sh.measure.SwiftUIDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
Expand Down Expand Up @@ -1955,7 +1955,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.measure.SwiftUIDemo;
PRODUCT_BUNDLE_IDENTIFIER = sh.measure.SwiftUIDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
Expand Down Expand Up @@ -1985,7 +1985,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.measure.DemoApp;
PRODUCT_BUNDLE_IDENTIFIER = sh.measure.DemoApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "DemoApp/Controller/DemoApp-Bridging-Header.h";
Expand Down Expand Up @@ -2017,7 +2017,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.measure.DemoApp;
PRODUCT_BUNDLE_IDENTIFIER = sh.measure.DemoApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "DemoApp/Controller/DemoApp-Bridging-Header.h";
Expand Down
6 changes: 6 additions & 0 deletions ios/MeasureSDK/Attribute/Attribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ struct Attributes: Codable {
var appBuild: String = ""
var measureSdkVersion: String = ""
var appUniqueId: String = ""
var deviceThermalThrottlingEnabled: Bool?
var deviceLowPowerMode: Bool?
var osPageSize: UInt8?

enum CodingKeys: String, CodingKey {
case threadName = "thread_name"
Expand Down Expand Up @@ -81,5 +84,8 @@ struct Attributes: Codable {
case appBuild = "app_build"
case measureSdkVersion = "measure_sdk_version"
case appUniqueId = "app_unique_id"
case osPageSize = "os_page_size"
case deviceThermalThrottlingEnabled = "device_thermal_throttling_enabled"
case deviceLowPowerMode = "device_low_power_mode"
}
}
3 changes: 2 additions & 1 deletion ios/MeasureSDK/Events/EventProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ final class BaseEventProcessor: EventProcessor {
attachments: [Attachment]?,
sessionId: String?
) {
let threadName = ((Thread.current.name?.isEmpty) != nil) ? "unknown" : Thread.current.name
let threadName = OperationQueue.current?.underlyingQueue?.label ?? "unknown"
let event = createEvent(
data: data,
timestamp: timestamp,
Expand All @@ -85,6 +85,7 @@ final class BaseEventProcessor: EventProcessor {
sessionId: sessionId
)
event.attributes?.threadName = threadName
event.attributes?.deviceLowPowerMode = ProcessInfo.processInfo.isLowPowerModeEnabled
event.appendAttributes(self.attributeProcessors)
if let attributes = event.attributes {
self.crashDataPersistence.attribute = attributes
Expand Down
57 changes: 29 additions & 28 deletions ios/MeasureSDK/Exporter/EventSerializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ struct EventSerializer {
var result = "{"
result += "\"handled\":\(exceptionData.handled),"
result += "\"exceptions\":[\(exceptionsSerialized)],"
result += "\"foreground\":\(exceptionData.foreground.map { "\($0)" } ?? "null"),"
result += "\"foreground\":\(exceptionData.foreground.map { "\($0)" } ?? ""),"
result += "\"threads\":[\(threadsSerialized)]"
result += "}"
return result
Expand All @@ -156,7 +156,7 @@ struct EventSerializer {
result += "\"type\":\"\(escapeString(exceptionDetail.type))\","
result += "\"message\":\"\(escapeString(exceptionDetail.message))\","
result += "\"frames\":[\(framesSerialized)],"
result += "\"signal\":\"\(exceptionDetail.signal ?? "null")\","
result += "\"signal\":\"\(exceptionDetail.signal ?? "")\","
result += "\"thread_name\":\"\(escapeString(exceptionDetail.threadName))\","
result += "\"thread_sequence\":\(exceptionDetail.threadSequence),"
result += "\"os_build_number\":\"\(escapeString(exceptionDetail.osBuildNumber))\""
Expand Down Expand Up @@ -197,8 +197,8 @@ struct EventSerializer {

private func serialiseClickData(_ clickData: ClickData) -> String? {
var result = "{"
result += "\"target\":\"\(clickData.target ?? "null")\","
result += "\"target_id\":\"\(clickData.targetId ?? "null")\","
result += "\"target\":\"\(clickData.target ?? "")\","
result += "\"target_id\":\"\(clickData.targetId ?? "")\","
result += "\"width\":\(clickData.width ?? 0),"
result += "\"height\":\(clickData.height ?? 0),"
result += "\"x\":\(clickData.x),"
Expand All @@ -211,8 +211,8 @@ struct EventSerializer {

private func serialiseLongClickData(_ longClickData: LongClickData) -> String? {
var result = "{"
result += "\"target\":\"\(longClickData.target ?? "null")\","
result += "\"target_id\":\"\(longClickData.targetId ?? "null")\","
result += "\"target\":\"\(longClickData.target ?? "")\","
result += "\"target_id\":\"\(longClickData.targetId ?? "")\","
result += "\"width\":\(longClickData.width ?? 0),"
result += "\"height\":\(longClickData.height ?? 0),"
result += "\"x\":\(longClickData.x),"
Expand All @@ -225,8 +225,8 @@ struct EventSerializer {

private func serialiseScrollData(_ scrollData: ScrollData) -> String {
var result = "{"
result += "\"target\":\"\(scrollData.target ?? "null")\","
result += "\"target_id\":\"\(scrollData.targetId ?? "null")\","
result += "\"target\":\"\(scrollData.target ?? "")\","
result += "\"target_id\":\"\(scrollData.targetId ?? "")\","
result += "\"x\":\(scrollData.x),"
result += "\"y\":\(scrollData.y),"
result += "\"end_x\":\(scrollData.endX),"
Expand Down Expand Up @@ -256,7 +256,7 @@ struct EventSerializer {
private func serialiseSwiftUILifecycleData(_ swiftUILifecycleData: SwiftUILifecycleData) -> String {
var result = "{"
result += "\"type\":\"\(swiftUILifecycleData.type.rawValue)\","
result += "\"view_name\":\"\(swiftUILifecycleData.viewName)\""
result += "\"class_name\":\"\(swiftUILifecycleData.className)\""
result += "}"
return result
}
Expand Down Expand Up @@ -327,31 +327,32 @@ struct EventSerializer {
do {
decodedAttributes = try JSONDecoder().decode(Attributes.self, from: attributeData)
var result = "{"
result += "\"thread_name\":\"\(decodedAttributes?.threadName ?? "null")\","
result += "\"device_name\":\"\(decodedAttributes?.deviceName ?? "null")\","
result += "\"device_model\":\"\(decodedAttributes?.deviceModel ?? "null")\","
result += "\"device_manufacturer\":\"\(decodedAttributes?.deviceManufacturer ?? "null")\","
result += "\"device_type\":\"\(decodedAttributes?.deviceType?.rawValue ?? "null")\","
result += "\"thread_name\":\"\(decodedAttributes?.threadName ?? "")\","
result += "\"device_name\":\"\(decodedAttributes?.deviceName ?? "")\","
result += "\"device_model\":\"\(decodedAttributes?.deviceModel ?? "")\","
result += "\"device_manufacturer\":\"\(decodedAttributes?.deviceManufacturer ?? "")\","
result += "\"device_type\":\"\(decodedAttributes?.deviceType?.rawValue ?? "")\","
result += "\"device_is_foldable\":\(decodedAttributes?.deviceIsFoldable ?? false),"
result += "\"device_is_physical\":\(decodedAttributes?.deviceIsPhysical ?? true),"
result += "\"device_density_dpi\":\(decodedAttributes?.deviceDensityDpi ?? 0),"
result += "\"device_width_px\":\(decodedAttributes?.deviceWidthPx ?? 0),"
result += "\"device_height_px\":\(decodedAttributes?.deviceHeightPx ?? 0),"
result += "\"device_density\":\(decodedAttributes?.deviceDensity ?? 0),"
result += "\"device_locale\":\"\(decodedAttributes?.deviceLocale ?? "null")\","
result += "\"os_name\":\"\(decodedAttributes?.osName ?? "null")\","
result += "\"os_version\":\"\(decodedAttributes?.osVersion ?? "null")\","
result += "\"platform\":\"\(decodedAttributes?.platform ?? "null")\","
result += "\"network_type\":\"\(decodedAttributes?.networkType?.rawValue ?? "null")\","
result += "\"network_generation\":\"\(decodedAttributes?.networkGeneration?.rawValue ?? "null")\","
result += "\"network_provider\":\"\(decodedAttributes?.networkProvider ?? "null")\","
result += "\"installation_id\":\"\(decodedAttributes?.installationId ?? "null")\","
result += "\"user_id\":\"\(decodedAttributes?.userId ?? "null")\","
result += "\"device_cpu_arch\":\"\(decodedAttributes?.deviceCpuArch ?? "null")\","
result += "\"app_version\":\"\(decodedAttributes?.appVersion ?? "null")\","
result += "\"app_build\":\"\(decodedAttributes?.appBuild ?? "null")\","
result += "\"measure_sdk_version\":\"\(decodedAttributes?.measureSdkVersion ?? "null")\","
result += "\"app_unique_id\":\"\(decodedAttributes?.appUniqueId ?? "null")\""
result += "\"device_locale\":\"\(decodedAttributes?.deviceLocale ?? "")\","
result += "\"os_name\":\"\(decodedAttributes?.osName ?? "")\","
result += "\"os_version\":\"\(decodedAttributes?.osVersion ?? "")\","
result += "\"platform\":\"\(decodedAttributes?.platform ?? "")\","
result += "\"network_type\":\"\(decodedAttributes?.networkType?.rawValue ?? "")\","
result += "\"network_generation\":\"\(decodedAttributes?.networkGeneration?.rawValue ?? "")\","
result += "\"network_provider\":\"\(decodedAttributes?.networkProvider ?? "")\","
result += "\"installation_id\":\"\(decodedAttributes?.installationId ?? "")\","
result += "\"user_id\":\"\(decodedAttributes?.userId ?? "")\","
result += "\"device_cpu_arch\":\"\(decodedAttributes?.deviceCpuArch ?? "")\","
result += "\"app_version\":\"\(decodedAttributes?.appVersion ?? "")\","
result += "\"app_build\":\"\(decodedAttributes?.appBuild ?? "")\","
result += "\"measure_sdk_version\":\"\(decodedAttributes?.measureSdkVersion ?? "")\","
result += "\"device_low_power_mode\":\"\(decodedAttributes?.deviceLowPowerMode ?? false)\","
result += "\"app_unique_id\":\"\(decodedAttributes?.appUniqueId ?? "")\""
result += "}"
return result
} catch {
Expand Down
32 changes: 24 additions & 8 deletions ios/MeasureSDK/Lifecycle/LifecycleCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,32 @@ class BaseLifecycleCollector: LifecycleCollector {
func processControllerLifecycleEvent(_ vcLifecycleType: VCLifecycleEventType, for viewController: UIViewController) {
let className = String(describing: type(of: viewController))

eventProcessor.track(data: VCLifecycleData(type: vcLifecycleType.stringValue, className: className),
timestamp: timeProvider.now(),
type: .lifecycleViewController,
attributes: nil,
sessionId: nil,
attachments: nil)
// Define the list of excluded class names
let excludedClassNames = [
"UIHostingController",
"UIKitNavigationController",
"NavigationStackHostingController",
"NotifyingMulticolumnSplitViewController",
"StyleContextSplitViewNavigationController"
]

// Check if the class name contains any of the excluded substrings
let shouldTrackEvent = !excludedClassNames.contains { className.contains($0) }

if shouldTrackEvent {
eventProcessor.track(
data: VCLifecycleData(type: vcLifecycleType.stringValue, className: className),
timestamp: timeProvider.now(),
type: .lifecycleViewController,
attributes: nil,
sessionId: nil,
attachments: nil
)
}
}

func processSwiftUILifecycleEvent(_ swiftUILifecycleType: SwiftUILifecycleType, for viewName: String) {
eventProcessor.track(data: SwiftUILifecycleData(type: swiftUILifecycleType, viewName: viewName),
func processSwiftUILifecycleEvent(_ swiftUILifecycleType: SwiftUILifecycleType, for className: String) {
eventProcessor.track(data: SwiftUILifecycleData(type: swiftUILifecycleType, className: className),
timestamp: timeProvider.now(),
type: .lifecycleSwiftUI,
attributes: nil,
Expand Down
12 changes: 11 additions & 1 deletion ios/MeasureSDK/Lifecycle/LifecycleEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ struct ApplicationLifecycleData: Codable {
struct VCLifecycleData: Codable {
let type: String
let className: String

enum CodingKeys: String, CodingKey {
case type
case className = "class_name"
}
}

enum SwiftUILifecycleType: String, Codable {
Expand All @@ -56,5 +61,10 @@ enum SwiftUILifecycleType: String, Codable {

struct SwiftUILifecycleData: Codable {
let type: SwiftUILifecycleType
let viewName: String
let className: String

enum CodingKeys: String, CodingKey {
case type
case className = "class_name"
}
}
Loading

0 comments on commit 92f1f03

Please sign in to comment.