Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

docs(ios): update feature documentation #1863

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@
All the features supported by the Measure SDK are listed below.

* [App launch](features/feature_app_launch.md)
* [Crash tracking](features/feature_crash_tracking.md)
* [Network monitoring](features/feature_network_monitoring.md)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Give a more detailed usage example to use NetworkInterceptor.
  • Consider renaming the NetworkInterceptor to MsrNetworkInterceptor.
  • Anything that requires manual setup must also be documented in the main README.md file.

* [Network changes](features/feature_network_changes.md)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the network changes documentation we should clearly mention that this is only available upto iOS 16.4.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also consider removing it if this will no longer be available in fufture and if there are no alternatives.

* [Gesture tracking](features/feature_gesture_tracking.md)
* [Layout Snapshots](features/feature_layout_snapshots.md)
* [Navigation & Lifecycle](features/feature_navigation_and_lifecycle.md)
* [CPU monitoring](features/feature_cpu_monitoring.md)
* [Memory monitoring](features/feature_memory_monitoring.md)
Empty file.
11 changes: 11 additions & 0 deletions docs/ios/features/feature_cpu_monitoring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Feature - CPU Monitoring

Measure SDK captures CPU usage periodically (defaults to 3 seconds) when the app is in the foreground.

## How it works

Measure SDK calculates CPU usage by retrieving task and thread information from the system. It uses `task_info` to gather overall task details and `task_threads` to obtain a list of active threads. Then, `thread_info` is used to extract CPU usage from each thread. The CPU usage of all threads is summed up and converted into a percentage of the total available CPU time.

Comment on lines +7 to +8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Links to documentation of task_info and task_threads would help understand this better. Also, some more details around the same in the doc will be useful:

What are task_info and task_thread, how is the percentage of total available CPU time calculated?

## Data collected

Check out the data collected by Measure in the [CPU Usage Event](../../api/sdk/README.md#cpu_usage) section.
12 changes: 12 additions & 0 deletions docs/ios/features/feature_crash_tracking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Feature - Crash Tracking

Measure tracks all crashes automatically, no additional code is required to enable this feature.

## How it works

We rely on [PLCrashReporter](https://github.com/microsoft/plcrashreporter) to detect crashes. Once a crash is detected, most recent [attribute](../../api/sdk/README.md#attributes) is saved with the crash report. On next launch, this crash report along with all the events in the previous session are exported to the server.

## Data collected

Checkout the data collected by Measure for each crash in
the [Exception Event](../../api/sdk/README.md#exception) section.
27 changes: 27 additions & 0 deletions docs/ios/features/feature_gesture_tracking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Feature - Gesture Tracking
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Measure SDK captures gestures such as click, long click, and scroll events automatically.

## How it works

Gesture tracking consists of two main components:

1. [Gesture detection](#gesture-detection)
2. [Gesture target detection](#gesture-target-detection)

### Gesture detection

Measure SDK detects touch events by swizzling `UIWindow`'s `sendEvent` method. It processes touch events to classify them into different gesture types:

- **Click**: A touch event that lasts for less than 500 ms.
- **Long Click**: A touch event that lasts for more than 500 ms.
- **Scroll**: A touch movement exceeding 3.5 points in any direction.

### Gesture target detection

Gesture target detection identifies the UI element interacted with during a gesture. It first determines the view at the touch location and then searches its subviews to find the most relevant target. For scroll detection, it checks if the interacted element is a scrollable view like `UIScrollView`, `UIDatePicker`, or `UIPickerView`.

#### Benchmark results

- On average, it takes **4 ms** to identify the clicked view in a view hierarchy with a depth of **1,500**.
- For more common scenarios, a view hierarchy with a depth of **20** takes approximately **0.2 ms**.
Comment on lines +26 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Links to the benchmark code (if any) would be useful here.

18 changes: 18 additions & 0 deletions docs/ios/features/feature_layout_snapshots.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Feature — Layout Snapshots

Layout snapshots provide a lightweight way to capture the structure of your UI at key user interactions.
They are automatically collected during click events (with throttling) and store the layout hierarchy as SVG rather than
full screenshots.
This approach gives valuable context about the UI state during user interactions while being significantly more
efficient to capture and store than traditional screenshots.

| Screenshot | Layout snapshot |
|-------------------------------------------------------|--------------------------------------------------|
| ![Screenshot](../../android/images/layoutSnapshotScreenshot.png) | ![Layout Snapshot](../../android/images/layoutSnapshot.png) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a layout snapshot example from an iOS device.


## How it works

Once a [gesture is detected](feature_gesture_tracking.md), the layout is parsed by going over every element, recording dimensions and size information.
The result is then converted into an SVG and tracked as an [attachment](../../api/sdk/README.md#attachments).

## Impact on Performance
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is empty, we could provide the names of traces added for this purpose if any.

11 changes: 11 additions & 0 deletions docs/ios/features/feature_memory_monitoring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Feature - Memory Monitoring

Measure SDK captures memory usage periodically (defaults to 2 seconds) when the app is in the foreground.

## How it works

Measure SDK calculates memory usage by retrieving task-level memory information using the `task_info` API with the `TASK_VM_INFO` flavor. It extracts the `phys_footprint` value, which represents the physical memory footprint of the app in kilobytes. If the footprint value is unavailable, it falls back to using `resident_size`, which represents the resident memory size allocated to the process.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are task_info, TASK_VM_INFO, phys_footprint and resident_size.

In what cases is the footprint value not available and how it impacts what is shown on the dashboard? (side question: how does someone know on the dashboard if we fall back to resident size?)

A bit more detail on the entire process of how memory usage is captured and calculated would make this more helpful.


## Data collected

Check out the data collected by Measure in the [Memory Usage Absolute](../../api/sdk/README.md#memory_usage_absolute) section.
58 changes: 58 additions & 0 deletions docs/ios/features/feature_navigation_and_lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Feature - Navigation & Lifecycle

Measure SDK captures lifecycle and navigation events automatically, this includes the following:

1. [Application lifecycle](#application-lifecycle)
2. [View Controller lifecycle](#view-controller-lifecycle)
3. [SwiftUI lifecycle](#swiftui-lifecycle)

## Application lifecycle

Measure automatically tracks the following Application lifecycle events:

1. Background
2. Foreground
3. Terminated

### How it works

Measure SDK listens for system notifications to track application lifecycle events. It uses `didEnterBackgroundNotification` to detect when the app moves to the background, `willEnterForegroundNotification` when the app returns to the foreground, and `willTerminateNotification` to capture when the app is about to be terminated. These notifications enable Measure to accurately record app state transitions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add documentation links to the callback functions.


### Data collected

Checkout all the data collected for App lifecycle in the [App Lifecycle Event](../../api/sdk/README.md#lifecycle_app) section.

## View Controller lifecycle

Measure automatically tracks the following View Controller lifecycle events:

1. viewDidLoad
2. viewWillAppear
3. viewDidAppear
4. viewWillDisappear
5. viewDidDisappear
6. didReceiveMemoryWarning
7. initWithNibName
8. initWithCoder

You can also track `loadView` and `deinit` by from `MeasureViewController` for swift and `MSRViewController` for ObjC.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a usage example to clearly show how to use this. Also, anything that requires manual setup must also be documented in the main README.md file.


### How it works

Measure SDK uses method swizzling to intercept View Controller lifecycle methods. This technique dynamically replaces method implementations at runtime, allowing Measure to capture lifecycle events without requiring manual integration.

### Data collected

Checkout all the data collected for View Controller lifecycle in the [View Controller Lifecycle Event](../../api/sdk/README.md#lifecycle_view_controller) section.

## SwiftUI lifecycle

Measure can track SwiftUI component's `onAppear` and `onDisappear` if you wrap your view with the `MsrMoniterView`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a usage example to clearly show how to use this. Also, anything that requires manual setup must also be documented in the main README.md file.


### How it works

Measure SDK provides `MsrMoniterView`, a wrapper view that listens for SwiftUI lifecycle events. The `MsrMoniterView` ensures that each appearance event is only triggered once per lifecycle instance. Additionally, you can use the `moniterWithMsr` extension to conveniently wrap any SwiftUI view.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a usage example to clearly show how to use moniterWithMsr. Also, anything that requires manual setup must also be documented in the main README.md file.


### Data collected

Checkout all the data collected for SwiftUI lifecycle in the [SwiftUI Lifecycle Event](../../api/sdk/README.md#lifecycle_swift_ui) section.
1 change: 1 addition & 0 deletions ios/MeasureSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,7 @@
52F377352CB41DDF006147E8 /* Frameworks */,
52F377362CB41DDF006147E8 /* Resources */,
52F377602CB41F5F006147E8 /* Embed Frameworks */,
52B7F0DD2D6D97DC001498BC /* ShellScript */,
);
buildRules = (
);
Expand Down
3 changes: 1 addition & 2 deletions ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,13 @@ Measure.shared.trackScreenView("Home")

# Features

* [App launch](../docs/ios/features/feature_app_launch.md)
* [Crash tracking](../docs/ios/features/feature_crash_tracking.md)
* [Network monitoring](../docs/ios/features/feature_network_monitoring.md)
* [Network changes](../docs/ios/features/feature_network_changes.md)
* [Gesture tracking](../docs/ios/features/feature_gesture_tracking.md)
* [Layout Snapshots](../docs/ios/features/feature_layout_snapshots.md)
* [Navigation & Lifecycle](../docs/ios/features/feature_navigation_and_lifecycle.md)
* [App Lifecycle](../docs/ios/features/feature_app_lifecycle.md)
* [App launch](../docs/ios/features/feature_app_launch.md)
* [CPU monitoring](../docs/ios/features/feature_cpu_monitoring.md)
* [Memory monitoring](../docs/ios/features/feature_memory_monitoring.md)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import XCTest
final class GestureTargetFinderTests: XCTestCase {
var targetFinder: BaseGestureTargetFinder!
var window: UIWindow!
let viewDepth = 1500
let viewDepth = 20

override func setUp() {
super.setUp()
Expand Down
Loading