Skip to content

Commit 8483dce

Browse files
Revert "impr(profiling): always remove launch profile config after starting (getsentry#5318)"
This reverts commit 2a36c3f.
1 parent 2d39d6c commit 8483dce

File tree

10 files changed

+249
-70
lines changed

10 files changed

+249
-70
lines changed

Samples/iOS-Swift/iOS-Swift-UITests/BaseUITest.swift

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class BaseUITest: XCTestCase {
88
//swiftlint:disable implicit_getter
99
var automaticallyLaunchAndTerminateApp: Bool { get { true } }
1010
//swiftlint:enable implicit_getter
11-
11+
1212
override func setUp() {
1313
super.setUp()
1414
continueAfterFailure = false
@@ -37,7 +37,7 @@ extension BaseUITest {
3737
return app
3838
}
3939

40-
func launchApp(args: [String] = [], env: [String: String] = [:], activateBeforeLaunch: Bool = true) {
40+
func launchApp(args: [String] = [], env: [String: String] = [:]) {
4141
app.launchArguments.append(contentsOf: args)
4242
for (k, v) in env {
4343
app.launchEnvironment[k] = v
@@ -46,17 +46,10 @@ extension BaseUITest {
4646
// Calling activate() and then launch() effectively launches the app twice, interfering with
4747
// local debugging. Only call activate if there isn't a debugger attached, which is a decent
4848
// proxy for whether this is running in CI.
49-
if !isDebugging() && activateBeforeLaunch {
50-
// activate() appears to drop launch args and environment variables, so save them beforehand and reset them before subsequent calls to launch()
51-
let launchArguments = app.launchArguments
52-
let launchEnvironment = app.launchEnvironment
53-
49+
if !isDebugging() {
5450
// App prewarming can sometimes cause simulators to get stuck in UI tests, activating them
5551
// before launching clears any prewarming state.
5652
app.activate()
57-
58-
app.launchArguments = launchArguments
59-
app.launchEnvironment = launchEnvironment
6053
}
6154

6255
app.launch()

Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,61 @@
1+
<<<<<<< HEAD
12
@testable import Sentry
23
import SentrySampleShared
4+
=======
5+
>>>>>>> parent of 2a36c3f8 (impr(profiling): always remove launch profile config after starting (#5318))
36
import XCTest
47

58
//swiftlint:disable function_body_length todo
69

710
class ProfilingUITests: BaseUITest {
811
override var automaticallyLaunchAndTerminateApp: Bool { false }
9-
12+
1013
func testAppLaunchesWithTraceProfiler() throws {
1114
guard #available(iOS 16, *) else {
1215
throw XCTSkip("Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs")
1316
}
1417

15-
try performTest(profileType: .trace)
18+
// by default, launch profiling is not enabled
19+
try launchAndConfigureSubsequentLaunches(shouldProfileThisLaunch: false)
20+
21+
// after configuring for launch profiling, check the marker file exists, and that the profile happens
22+
try launchAndConfigureSubsequentLaunches(terminatePriorSession: true, shouldProfileThisLaunch: true)
1623
}
1724

1825
func testAppLaunchesWithContinuousProfilerV1() throws {
1926
guard #available(iOS 16, *) else {
2027
throw XCTSkip("Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs")
2128
}
2229

23-
try performTest(profileType: .continuous)
30+
// by default, launch profiling is not enabled
31+
try launchAndConfigureSubsequentLaunches(shouldProfileThisLaunch: false, continuousProfiling: true)
32+
33+
// after configuring for launch profiling, check the marker file exists, and that the profile happens
34+
try launchAndConfigureSubsequentLaunches(terminatePriorSession: true, shouldProfileThisLaunch: true, continuousProfiling: true)
2435
}
2536

2637
func testAppLaunchesWithContinuousProfilerV2TraceLifecycle() throws {
2738
guard #available(iOS 16, *) else {
2839
throw XCTSkip("Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs")
2940
}
3041

31-
try performTest(profileType: .ui, lifecycle: .trace)
42+
// by default, launch profiling is not enabled
43+
try launchAndConfigureSubsequentLaunches(shouldProfileThisLaunch: false, continuousProfiling: true, v2TraceLifecycle: true)
44+
45+
// after configuring for launch profiling, check the marker file exists, and that the profile happens
46+
try launchAndConfigureSubsequentLaunches(terminatePriorSession: true, shouldProfileThisLaunch: true, continuousProfiling: true, v2TraceLifecycle: true)
3247
}
3348

3449
func testAppLaunchesWithContinuousProfilerV2ManualLifeCycle() throws {
3550
guard #available(iOS 16, *) else {
3651
throw XCTSkip("Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs")
3752
}
3853

39-
try performTest(profileType: .ui, lifecycle: .manual)
54+
// by default, launch profiling is not enabled
55+
try launchAndConfigureSubsequentLaunches(shouldProfileThisLaunch: false, continuousProfiling: true, v2ManualLifecycle: true)
56+
57+
// after configuring for launch profiling, check the marker file exists, and that the profile happens
58+
try launchAndConfigureSubsequentLaunches(terminatePriorSession: true, shouldProfileThisLaunch: true, continuousProfiling: true, v2ManualLifecycle: true)
4059
}
4160

4261
/**
@@ -130,6 +149,7 @@ extension ProfilingUITests {
130149
func stopContinuousProfiler() {
131150
app.buttons["io.sentry.ios-swift.ui-test.button.stop-continuous-profiler"].afterWaitingForExistence("Couldn't find button to stop continuous profiler").tap()
132151
}
152+
<<<<<<< HEAD
133153

134154
enum ProfilingType {
135155
case trace
@@ -180,56 +200,74 @@ extension ProfilingUITests {
180200
}
181201
}
182202

203+
=======
204+
205+
>>>>>>> parent of 2a36c3f8 (impr(profiling): always remove launch profile config after starting (#5318))
183206
/**
184207
* Performs the various operations for the launch profiler test case:
185208
* - terminates an existing app session
186-
* - starts a new app session
209+
* - creates a new one
187210
* - sets launch args and env vars to set the appropriate `SentryOption` values for the desired behavior
188-
* - launches the new configured app session, which will optionally start a launch profiler and then call SentrySDK.startWithOptions configured based on the launch args and env vars
211+
* - launches the new configured app session
189212
* - asserts the expected outcomes of the config file and launch profiler
190213
*/
191214
func launchAndConfigureSubsequentLaunches(
192215
terminatePriorSession: Bool = false,
193216
shouldProfileThisLaunch: Bool,
194-
shouldProfileNextLaunch: Bool,
195-
profileType: ProfilingType,
196-
lifecycle: SentryProfileOptions.SentryProfileLifecycle?
217+
continuousProfiling: Bool = false,
218+
v2TraceLifecycle: Bool = false,
219+
v2ManualLifecycle: Bool = false
197220
) throws {
198221
if terminatePriorSession {
199222
app.terminate()
200223
app = newAppSession()
201224
}
202225

203-
setAppLaunchParameters(profileType, lifecycle, shouldProfileNextLaunch)
226+
app.launchArguments.append(contentsOf: [
227+
// these help avoid other profiles that'd be taken automatically, that interfere with the checking we do for the assertions later in the tests
228+
"--disable-swizzling",
229+
"--disable-auto-performance-tracing",
230+
"--disable-uiviewcontroller-tracing",
204231

205-
launchApp(activateBeforeLaunch: false)
206-
goToProfiling()
232+
// sets a marker function to run in a load command that the launch profile should detect
233+
"--io.sentry.slow-load-method",
207234

208-
let configFileExists = try checkLaunchProfileMarkerFileExistence()
235+
// override full chunk completion before stoppage introduced in https://github.com/getsentry/sentry-cocoa/pull/4214
236+
"--io.sentry.continuous-profiler-immediate-stop"
237+
])
209238

210-
if shouldProfileNextLaunch {
211-
XCTAssert(configFileExists, "A launch profile config file should be present on disk if SentrySDK.startWithOptions configured launch profiling for the next launch.")
239+
if continuousProfiling {
240+
if v2TraceLifecycle {
241+
app.launchEnvironment["--io.sentry.profile-session-sample-rate"] = "1"
242+
} else if v2ManualLifecycle {
243+
app.launchArguments.append(contentsOf: [
244+
"--io.sentry.profile-lifecycle-manual"
245+
])
246+
app.launchEnvironment["--io.sentry.profile-session-sample-rate"] = "1"
247+
} else {
248+
app.launchArguments.append("--io.sentry.disable-ui-profiling")
249+
}
212250
} else {
213-
XCTAssertFalse(configFileExists, "Launch profile config files should be removed upon starting launch profiles. If SentrySDK.startWithOptions doesn't reconfigure launch profiling, the config file should not be present.")
251+
app.launchEnvironment["--io.sentry.profilesSampleRate"] = "1"
214252
}
215253

254+
launchApp()
255+
goToProfiling()
256+
XCTAssert(try checkLaunchProfileMarkerFileExistence())
257+
216258
guard shouldProfileThisLaunch else {
217259
return
218260
}
219-
220-
if profileType == .trace {
221-
retrieveLastProfileData()
222-
} else {
223-
if profileType == .continuous || (profileType == .ui && lifecycle == .manual) {
261+
262+
if continuousProfiling {
263+
if !v2TraceLifecycle {
224264
stopContinuousProfiler()
225265
}
226266
retrieveFirstProfileChunkData()
267+
} else {
268+
retrieveLastProfileData()
227269
}
228-
229-
try assertProfileContents()
230-
}
231-
232-
func assertProfileContents() throws {
270+
233271
let lastProfile = try marshalJSONDictionaryFromApp()
234272
let sampledProfile = try XCTUnwrap(lastProfile["profile"] as? [String: Any])
235273
let stacks = try XCTUnwrap(sampledProfile["stacks"] as? [[Int]])
@@ -239,7 +277,7 @@ extension ProfilingUITests {
239277
frames[stackFrame]["function"]
240278
}
241279
})
242-
280+
243281
// grab the first stack that contained frames from the fixture code that simulates a slow +[load] method
244282
var stackID: Int?
245283
let stack = try XCTUnwrap(stackFunctions.enumerated().first { nextStack in
@@ -258,12 +296,12 @@ extension ProfilingUITests {
258296
XCTFail("Didn't find the ID of the stack containing the target function")
259297
return
260298
}
261-
299+
262300
// ensure that the stack doesn't contain any calls to main functions; this ensures we actually captured pre-main stacks
263301
XCTAssertFalse(stack.contains("main"))
264302
XCTAssertFalse(stack.contains("UIApplicationMain"))
265303
XCTAssertFalse(stack.contains("-[UIApplication _run]"))
266-
304+
267305
// ensure that the stack happened on the main thread; this is a cross-check to make sure we didn't accidentally grab a stack from a different thread that wouldn't have had a call to main() anyways, thereby possibly missing the real stack that may have contained main() calls (but shouldn't for this test)
268306
let samples = try XCTUnwrap(sampledProfile["samples"] as? [[String: Any]])
269307
let sample = try XCTUnwrap(samples.first { nextSample in

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
77
var window: UIWindow?
88

99
var args: [String] {
10-
ProcessInfo.processInfo.arguments
11-
}
12-
13-
var env: [String: String] {
14-
ProcessInfo.processInfo.environment
10+
let args = ProcessInfo.processInfo.arguments
11+
print("[iOS-Swift] [debug] launch arguments: \(args)")
12+
return args
1513
}
1614

1715
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16+
<<<<<<< HEAD
1817
print("[iOS-Swift] [debug] launch arguments: \(args)")
1918
print("[iOS-Swift] [debug] launch environment: \(env)")
2019

2120
if args.contains(SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue) {
21+
=======
22+
if args.contains("--io.sentry.wipe-data") {
23+
>>>>>>> parent of 2a36c3f8 (impr(profiling): always remove launch profile config after starting (#5318))
2224
removeAppData()
2325
}
2426

Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,20 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate {
7777

7878
@IBAction func defineProfilesSampleRateToggled(_ sender: UISwitch) {
7979
sampleRateField.isEnabled = sender.isOn
80+
<<<<<<< HEAD
8081

8182
#if !SDK_V9
83+
=======
84+
85+
>>>>>>> parent of 2a36c3f8 (impr(profiling): always remove launch profile config after starting (#5318))
8286
var sampleRate = SentrySDKOverrides.Profiling.sampleRate
8387
sampleRate.floatValue = getSampleRateOverride(field: sampleRateField)
8488
#endif // !SDK_V9
8589
}
8690

8791
@IBAction func defineTracesSampleRateToggled(_ sender: UISwitch) {
8892
tracesSampleRateField.isEnabled = sender.isOn
89-
93+
9094
var sampleRate = SentrySDKOverrides.Tracing.sampleRate
9195
sampleRate.floatValue = getSampleRateOverride(field: tracesSampleRateField)
9296
}
@@ -113,16 +117,7 @@ private extension ProfilingViewController {
113117
let cachesDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
114118
let fm = FileManager.default
115119
let dir = "\(cachesDirectory)/io.sentry/" + (continuous ? "continuous-profiles" : "trace-profiles")
116-
117-
let count: Int
118-
do {
119-
count = try fm.contentsOfDirectory(atPath: dir).count
120-
} catch {
121-
print("[iOS-Swift] [debug] [ProfilingViewController] error reading directory \(dir): \(error)")
122-
profilingUITestDataMarshalingStatus.text = "<error>"
123-
return
124-
}
125-
120+
let count = try! fm.contentsOfDirectory(atPath: dir).count
126121
//swiftlint:disable empty_count
127122
guard continuous || count > 0 else {
128123
//swiftlint:enable empty_count
@@ -131,7 +126,7 @@ private extension ProfilingViewController {
131126
}
132127
let fileName = "profile\(continuous ? 0 : count - 1)"
133128
let fullPath = "\(dir)/\(fileName)"
134-
129+
135130
if fm.fileExists(atPath: fullPath) {
136131
let url = NSURL.fileURL(withPath: fullPath)
137132
block(url)
@@ -142,17 +137,17 @@ private extension ProfilingViewController {
142137
}
143138
return
144139
}
145-
140+
146141
block(nil)
147142
}
148-
143+
149144
func handleContents(file: URL?) {
150145
guard let file = file else {
151146
profilingUITestDataMarshalingTextField.text = "<missing>"
152147
profilingUITestDataMarshalingStatus.text = ""
153148
return
154149
}
155-
150+
156151
do {
157152
let data = try Data(contentsOf: file)
158153
let contents = data.base64EncodedString()

Sentry.xcodeproj/project.pbxproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,6 @@
743743
84E13B842CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E13B832CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift */; };
744744
84EB21942BF01C6C00EDDA28 /* TestNSNotificationCenterWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DE4328D9F8F6004845C6 /* TestNSNotificationCenterWrapper.swift */; };
745745
84EB21962BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */; };
746-
84F2A1CE2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2A1CD2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift */; };
747746
84F994E62A6894B500EC0190 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84F994E52A6894B500EC0190 /* CoreData.framework */; };
748747
84F994E82A6894BD00EC0190 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); };
749748
861265F92404EC1500C4AFDE /* SentryArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 861265F72404EC1500C4AFDE /* SentryArray.h */; };
@@ -2089,7 +2088,6 @@
20892088
84EACEBC2C33CA7A009B8753 /* SentryWithoutUIKit.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = SentryWithoutUIKit.modulemap; path = Sources/Resources/SentryWithoutUIKit.modulemap; sourceTree = SOURCE_ROOT; };
20902089
84EACEDF2C3DCAE2009B8753 /* DeploymentTargets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DeploymentTargets.xcconfig; sourceTree = "<group>"; };
20912090
84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashInstallationTests.swift; sourceTree = "<group>"; };
2092-
84F2A1CD2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryApplaunchProfilingMalformedConfigFileTests.swift; sourceTree = "<group>"; };
20932091
84F994E52A6894B500EC0190 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; };
20942092
84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; };
20952093
861265F72404EC1500C4AFDE /* SentryArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryArray.h; path = include/SentryArray.h; sourceTree = "<group>"; };
@@ -4051,7 +4049,6 @@
40514049
035E73CD27D5790A005EEB11 /* SentryThreadMetadataCacheTests.mm */,
40524050
03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */,
40534051
84A305472BC72A0A00D84283 /* SentryAppLaunchProfilingTests.swift */,
4054-
84F2A1CD2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift */,
40554052
845CEB162D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift */,
40564053
84A898CD2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift */,
40574054
845CEAEE2D83F79500B6B325 /* SentryProfilingPublicAPITests.swift */,
@@ -6369,8 +6366,11 @@
63696366
845CEAEF2D83F79500B6B325 /* SentryProfilingPublicAPITests.swift in Sources */,
63706367
8431EFE829B27BAD00D8DC56 /* SentrySystemWrapperTests.swift in Sources */,
63716368
84A305492BC7328400D84283 /* SentryAppLaunchProfilingTests.swift in Sources */,
6369+
<<<<<<< HEAD
63726370
D4DEE6592E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m in Sources */,
63736371
84F2A1CE2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift in Sources */,
6372+
=======
6373+
>>>>>>> parent of 2a36c3f8 (impr(profiling): always remove launch profile config after starting (#5318))
63746374
845CEB172D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift in Sources */,
63756375
8431EFE529B27BAD00D8DC56 /* SentryNSProcessInfoWrapperTests.swift in Sources */,
63766376
8431EFDE29B27B5300D8DC56 /* SentryTraceProfilerTests.swift in Sources */,

0 commit comments

Comments
 (0)