Skip to content

Commit f8833c4

Browse files
authored
feat(app launch profiling): add app launch profiling (#3529)
1 parent 6e1452d commit f8833c4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1883
-655
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- Automatically profile app launches (#3529)
8+
59
### Improvements
610

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

1216
- Finish TTID span when transaction finishes (#3610)
17+
- Don't take screenshot and view hierarchy for app hanging (#3620)
1318
- Dont take screenshot and view hierarchy for app hanging (#3620)
1419
- Remove `free_storage` and `storage_size` from the device context (#3627), because Apple forbids sending
1520
information retrieved via `NSFileSystemFreeSize` and `NSFileSystemSize` off a device; see

Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
</BuildActionEntries>
2424
</BuildAction>
2525
<TestAction
26-
buildConfiguration = "Debug"
26+
buildConfiguration = "Test"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
2929
shouldUseLaunchSchemeArgsEnv = "YES">
@@ -73,6 +73,26 @@
7373
argument = "--disable-file-io-tracing"
7474
isEnabled = "NO">
7575
</CommandLineArgument>
76+
<CommandLineArgument
77+
argument = "--io.sentry.wipe-data"
78+
isEnabled = "YES">
79+
</CommandLineArgument>
80+
<CommandLineArgument
81+
argument = "--io.sentry.slow-load-method"
82+
isEnabled = "YES">
83+
</CommandLineArgument>
84+
<CommandLineArgument
85+
argument = "--disable-watchdog-tracking"
86+
isEnabled = "NO">
87+
</CommandLineArgument>
88+
<CommandLineArgument
89+
argument = "--disable-tracing"
90+
isEnabled = "NO">
91+
</CommandLineArgument>
92+
<CommandLineArgument
93+
argument = "--profile-app-launches"
94+
isEnabled = "YES">
95+
</CommandLineArgument>
7696
<CommandLineArgument
7797
argument = "--disable-crash-handler"
7898
isEnabled = "NO">

Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-SwiftUITests.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
</Testables>
2626
</TestAction>
2727
<LaunchAction
28-
buildConfiguration = "Debug"
28+
buildConfiguration = "Test"
2929
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
3030
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
3131
launchStyle = "0"

Samples/iOS-Swift/iOS-Swift/AppDelegate.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
3434
}
3535
options.tracesSampleRate = tracesSampleRate
3636

37-
if let tracesSamplerValue = env["--io.sentry.tracersSamplerValue"] {
37+
if let tracesSamplerValue = env["--io.sentry.tracesSamplerValue"] {
3838
options.tracesSampler = { _ in
3939
return NSNumber(value: (tracesSamplerValue as NSString).integerValue)
4040
}
@@ -51,7 +51,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
5151
return NSNumber(value: (profilesSamplerValue as NSString).integerValue)
5252
}
5353
}
54-
54+
55+
options.enableAppLaunchProfiling = args.contains("--profile-app-launches")
56+
5557
options.sessionTrackingIntervalMillis = 5_000
5658
options.attachScreenshot = true
5759
options.attachViewHierarchy = true
@@ -81,9 +83,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
8183
options.enableNetworkBreadcrumbs = !args.contains("--disable-network-breadcrumbs")
8284
options.enableSwizzling = !args.contains("--disable-swizzling")
8385
options.enableCrashHandler = !args.contains("--disable-crash-handler")
86+
options.enableTracing = !args.contains("--disable-tracing")
8487

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

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

101105
if processInfoEnvironment != nil {
102106
scope.setEnvironment(processInfoEnvironment)
@@ -126,8 +130,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
126130

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

129-
print("[iOS-Swift] launch arguments: \(ProcessInfo.processInfo.arguments)")
130-
print("[iOS-Swift] environment: \(ProcessInfo.processInfo.environment)")
133+
print("[iOS-Swift] [debug] launch arguments: \(ProcessInfo.processInfo.arguments)")
134+
print("[iOS-Swift] [debug] environment: \(ProcessInfo.processInfo.environment)")
131135

132136
maybeWipeData()
133137
AppDelegate.startSentry()
@@ -161,9 +165,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
161165
}
162166

163167
private extension AppDelegate {
168+
// 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
164169
func maybeWipeData() {
165170
if ProcessInfo.processInfo.arguments.contains("--io.sentry.wipe-data") {
166-
print("[iOS-Swift] removing app data")
171+
print("[iOS-Swift] [debug] removing app data")
167172
let appSupport = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!
168173
let cache = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
169174
for path in [appSupport, cache] {

Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<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">
2+
<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">
33
<device id="retina4_0" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22130"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
77
<capability name="Image references" minToolsVersion="12.0"/>
88
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
99
<capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -172,7 +172,7 @@
172172
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
173173
<subviews>
174174
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="jya-5z-xKN">
175-
<rect key="frame" x="0.0" y="64" width="320" height="56"/>
175+
<rect key="frame" x="0.0" y="64" width="320" height="190"/>
176176
<subviews>
177177
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="DOu-47-e6X">
178178
<rect key="frame" x="93" y="0.0" width="134" height="28"/>
@@ -223,16 +223,65 @@
223223
</button>
224224
</subviews>
225225
</stackView>
226+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vwa-d9-1BM">
227+
<rect key="frame" x="111.5" y="56" width="97" height="28"/>
228+
<fontDescription key="fontDescription" type="system" pointSize="13"/>
229+
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
230+
<state key="normal" title="View last profile"/>
231+
<connections>
232+
<action selector="viewLastProfile:" destination="NZr-bH-g9o" eventType="touchUpInside" id="7Xd-19-rsP"/>
233+
</connections>
234+
</button>
235+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="keL-m5-7hv">
236+
<rect key="frame" x="33.5" y="84" width="253" height="28"/>
237+
<fontDescription key="fontDescription" type="system" pointSize="13"/>
238+
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
239+
<state key="normal" title="Check launch profile marker file existence"/>
240+
<connections>
241+
<action selector="checkLaunchProfilingMarkerFile:" destination="NZr-bH-g9o" eventType="touchUpInside" id="IcT-D3-Oya"/>
242+
</connections>
243+
</button>
244+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="F1h-qu-BzX">
245+
<rect key="frame" x="102.5" y="112" width="115" height="28"/>
246+
<fontDescription key="fontDescription" type="system" pointSize="13"/>
247+
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
248+
<state key="normal" title="View launch profile"/>
249+
<connections>
250+
<action selector="viewLaunchProfile:" destination="NZr-bH-g9o" eventType="touchUpInside" id="DPn-8C-b7l"/>
251+
</connections>
252+
</button>
253+
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="LIr-jM-FSX">
254+
<rect key="frame" x="19" y="140" width="282" height="50"/>
255+
<subviews>
256+
<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:">
257+
<rect key="frame" x="0.0" y="15" width="184" height="20.5"/>
258+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
259+
<nil key="textColor"/>
260+
<nil key="highlightedColor"/>
261+
</label>
262+
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="5zI-Ix-rMJ">
263+
<rect key="frame" x="192" y="8" width="32" height="34"/>
264+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
265+
<textInputTraits key="textInputTraits"/>
266+
</textField>
267+
<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">
268+
<rect key="frame" x="232" y="0.0" width="50" height="50"/>
269+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
270+
<nil key="textColor"/>
271+
<nil key="highlightedColor"/>
272+
</label>
273+
</subviews>
274+
</stackView>
226275
<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">
227-
<rect key="frame" x="0.0" y="56" width="320" height="0.0"/>
276+
<rect key="frame" x="0.0" y="190" width="320" height="0.0"/>
228277
<accessibility key="accessibilityConfiguration" identifier="io.sentry.benchmark.value-marshaling-text-field"/>
229278
<fontDescription key="fontDescription" type="system" pointSize="14"/>
230279
<textInputTraits key="textInputTraits"/>
231280
</textField>
232281
</subviews>
233282
</stackView>
234283
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="hFG-bX-qLp">
235-
<rect key="frame" x="10" y="174" width="300" height="159.5"/>
284+
<rect key="frame" x="10" y="308" width="300" height="159.5"/>
236285
<subviews>
237286
<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">
238287
<rect key="frame" x="97" y="0.0" width="106.5" height="20.5"/>
@@ -342,10 +391,13 @@
342391
</view>
343392
<tabBarItem key="tabBarItem" title="Profiling" image="flame.fill" catalog="system" selectedImage="flame.fill" id="Wfx-IJ-h9f"/>
344393
<connections>
394+
<outlet property="launchProfilingMarkerFileCheckButton" destination="keL-m5-7hv" id="s2U-XE-Flv"/>
345395
<outlet property="maxThreadsTextField" destination="COd-X5-alN" id="6Pn-Be-aUe"/>
346396
<outlet property="maxWorkIntensityTextField" destination="rJh-QS-fAl" id="u9q-Sj-6SY"/>
347397
<outlet property="minThreadsTextField" destination="sCM-tI-skI" id="D0Z-yT-LbU"/>
348398
<outlet property="minWorkIntensityTextField" destination="CuN-wx-fvQ" id="Eik-Z2-7M7"/>
399+
<outlet property="profilingUITestDataMarshalingStatus" destination="2LR-W8-mNE" id="S4k-Yg-EsB"/>
400+
<outlet property="profilingUITestDataMarshalingTextField" destination="5zI-Ix-rMJ" id="2o6-Cc-NMl"/>
349401
<outlet property="valueTextField" destination="uTM-T7-Gv6" id="M59-lx-juE"/>
350402
<outlet property="workIntensityFactorLabel" destination="cAO-gr-3HC" id="BvB-NZ-TXI"/>
351403
<outlet property="workIntervalSlider" destination="N8m-ny-upJ" id="3MU-ZK-5qD"/>

0 commit comments

Comments
 (0)