Skip to content

Commit

Permalink
feat(app launch profiling): add app launch profiling (#3529)
Browse files Browse the repository at this point in the history
  • Loading branch information
armcknight authored Feb 16, 2024
1 parent 6e1452d commit f8833c4
Show file tree
Hide file tree
Showing 51 changed files with 1,883 additions and 655 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Automatically profile app launches (#3529)

### Improvements

- Cache installationID async to avoid file IO on the main thread when starting the SDK (#3601)
Expand All @@ -10,6 +14,7 @@
### Fixes

- Finish TTID span when transaction finishes (#3610)
- Don't take screenshot and view hierarchy for app hanging (#3620)
- Dont take screenshot and view hierarchy for app hanging (#3620)
- Remove `free_storage` and `storage_size` from the device context (#3627), because Apple forbids sending
information retrieved via `NSFileSystemFreeSize` and `NSFileSystemSize` off a device; see
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
Expand Down Expand Up @@ -73,6 +73,26 @@
argument = "--disable-file-io-tracing"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--io.sentry.wipe-data"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "--io.sentry.slow-load-method"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "--disable-watchdog-tracking"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--disable-tracing"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--profile-app-launches"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "--disable-crash-handler"
isEnabled = "NO">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
Expand Down
17 changes: 11 additions & 6 deletions Samples/iOS-Swift/iOS-Swift/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
options.tracesSampleRate = tracesSampleRate

if let tracesSamplerValue = env["--io.sentry.tracersSamplerValue"] {
if let tracesSamplerValue = env["--io.sentry.tracesSamplerValue"] {
options.tracesSampler = { _ in
return NSNumber(value: (tracesSamplerValue as NSString).integerValue)
}
Expand All @@ -51,7 +51,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return NSNumber(value: (profilesSamplerValue as NSString).integerValue)
}
}


options.enableAppLaunchProfiling = args.contains("--profile-app-launches")

options.sessionTrackingIntervalMillis = 5_000
options.attachScreenshot = true
options.attachViewHierarchy = true
Expand Down Expand Up @@ -81,9 +83,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
options.enableNetworkBreadcrumbs = !args.contains("--disable-network-breadcrumbs")
options.enableSwizzling = !args.contains("--disable-swizzling")
options.enableCrashHandler = !args.contains("--disable-crash-handler")
options.enableTracing = !args.contains("--disable-tracing")

// because we run CPU for 15 seconds at full throttle, we trigger ANR issues being sent. disable such during benchmarks.
options.enableAppHangTracking = !isBenchmarking && !args.contains("--disable-anr-tracking")
options.enableWatchdogTerminationTracking = !isBenchmarking && !args.contains("--disable-watchdog-tracking")
options.appHangTimeoutInterval = 2
options.enableCaptureFailedRequests = true
let httpStatusCodeRange = HttpStatusCodeRange(min: 400, max: 599)
Expand All @@ -96,7 +100,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}

options.initialScope = { scope in
let processInfoEnvironment = ProcessInfo.processInfo.environment["io.sentry.sdk-environment"]
let processInfoEnvironment = env["io.sentry.sdk-environment"]

if processInfoEnvironment != nil {
scope.setEnvironment(processInfoEnvironment)
Expand Down Expand Up @@ -126,8 +130,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

print("[iOS-Swift] launch arguments: \(ProcessInfo.processInfo.arguments)")
print("[iOS-Swift] environment: \(ProcessInfo.processInfo.environment)")
print("[iOS-Swift] [debug] launch arguments: \(ProcessInfo.processInfo.arguments)")
print("[iOS-Swift] [debug] environment: \(ProcessInfo.processInfo.environment)")

maybeWipeData()
AppDelegate.startSentry()
Expand Down Expand Up @@ -161,9 +165,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}

private extension AppDelegate {
// previously tried putting this in an AppDelegate.load override in ObjC, but it wouldn't run until after a launch profiler would have an opportunity to run, since SentryProfiler.load would always run first due to being dynamically linked in a framework module. it is sufficient to do it before calling SentrySDK.startWithOptions to clear state for testProfiledAppLaunches because we don't make any assertions on a launch profile the first launch of the app in that test
func maybeWipeData() {
if ProcessInfo.processInfo.arguments.contains("--io.sentry.wipe-data") {
print("[iOS-Swift] removing app data")
print("[iOS-Swift] [debug] removing app data")
let appSupport = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!
let cache = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
for path in [appSupport, cache] {
Expand Down
62 changes: 57 additions & 5 deletions Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22154" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5CD-RQ-aBU">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5CD-RQ-aBU">
<device id="retina4_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22130"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
Expand Down Expand Up @@ -172,7 +172,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="jya-5z-xKN">
<rect key="frame" x="0.0" y="64" width="320" height="56"/>
<rect key="frame" x="0.0" y="64" width="320" height="190"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="DOu-47-e6X">
<rect key="frame" x="93" y="0.0" width="134" height="28"/>
Expand Down Expand Up @@ -223,16 +223,65 @@
</button>
</subviews>
</stackView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vwa-d9-1BM">
<rect key="frame" x="111.5" y="56" width="97" height="28"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="View last profile"/>
<connections>
<action selector="viewLastProfile:" destination="NZr-bH-g9o" eventType="touchUpInside" id="7Xd-19-rsP"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="keL-m5-7hv">
<rect key="frame" x="33.5" y="84" width="253" height="28"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Check launch profile marker file existence"/>
<connections>
<action selector="checkLaunchProfilingMarkerFile:" destination="NZr-bH-g9o" eventType="touchUpInside" id="IcT-D3-Oya"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="F1h-qu-BzX">
<rect key="frame" x="102.5" y="112" width="115" height="28"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="View launch profile"/>
<connections>
<action selector="viewLaunchProfile:" destination="NZr-bH-g9o" eventType="touchUpInside" id="DPn-8C-b7l"/>
</connections>
</button>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="LIr-jM-FSX">
<rect key="frame" x="19" y="140" width="282" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="UI test data marshalling:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Uhg-B3-Rao" userLabel="UI test data marshaling:">
<rect key="frame" x="0.0" y="15" width="184" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="5zI-Ix-rMJ">
<rect key="frame" x="192" y="8" width="32" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2LR-W8-mNE" userLabel="Profiling UI Test Data Marshaling status">
<rect key="frame" x="232" y="0.0" width="50" height="50"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<textField hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="uTM-T7-Gv6">
<rect key="frame" x="0.0" y="56" width="320" height="0.0"/>
<rect key="frame" x="0.0" y="190" width="320" height="0.0"/>
<accessibility key="accessibilityConfiguration" identifier="io.sentry.benchmark.value-marshaling-text-field"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="hFG-bX-qLp">
<rect key="frame" x="10" y="174" width="300" height="159.5"/>
<rect key="frame" x="10" y="308" width="300" height="159.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Work threads:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t2C-jL-6qO">
<rect key="frame" x="97" y="0.0" width="106.5" height="20.5"/>
Expand Down Expand Up @@ -342,10 +391,13 @@
</view>
<tabBarItem key="tabBarItem" title="Profiling" image="flame.fill" catalog="system" selectedImage="flame.fill" id="Wfx-IJ-h9f"/>
<connections>
<outlet property="launchProfilingMarkerFileCheckButton" destination="keL-m5-7hv" id="s2U-XE-Flv"/>
<outlet property="maxThreadsTextField" destination="COd-X5-alN" id="6Pn-Be-aUe"/>
<outlet property="maxWorkIntensityTextField" destination="rJh-QS-fAl" id="u9q-Sj-6SY"/>
<outlet property="minThreadsTextField" destination="sCM-tI-skI" id="D0Z-yT-LbU"/>
<outlet property="minWorkIntensityTextField" destination="CuN-wx-fvQ" id="Eik-Z2-7M7"/>
<outlet property="profilingUITestDataMarshalingStatus" destination="2LR-W8-mNE" id="S4k-Yg-EsB"/>
<outlet property="profilingUITestDataMarshalingTextField" destination="5zI-Ix-rMJ" id="2o6-Cc-NMl"/>
<outlet property="valueTextField" destination="uTM-T7-Gv6" id="M59-lx-juE"/>
<outlet property="workIntensityFactorLabel" destination="cAO-gr-3HC" id="BvB-NZ-TXI"/>
<outlet property="workIntervalSlider" destination="N8m-ny-upJ" id="3MU-ZK-5qD"/>
Expand Down
Loading

0 comments on commit f8833c4

Please sign in to comment.