Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(profiling): continuous profiling from launch #3938

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9a1edd7
feat: implement starting continuous profiling from launch
armcknight Apr 9, 2024
d46cc59
wip: test case description for all option combinations
armcknight Apr 9, 2024
3d9a8c6
WIP: bdd test all option combinations
armcknight Apr 10, 2024
b440e9e
WIP: writing app launch profiling option tests
armcknight May 5, 2024
4ad43d1
got tests working
armcknight May 5, 2024
4981b60
condense declarations
armcknight May 5, 2024
f893978
express the same app launch options combo test in another way
armcknight May 5, 2024
a7088fa
add combinations with profilesSampler
armcknight May 5, 2024
fec8ee7
clean up
armcknight May 5, 2024
a33651c
rewrite last old app launch objc test in the new swift class
armcknight May 5, 2024
197722b
dont sample anything related to continuous profiling
armcknight May 9, 2024
ac102a4
wip writing a test for launch profile configuration
armcknight May 14, 2024
39208f4
add more tests to cover launch profiling code
armcknight May 15, 2024
de2a193
fix a couple bugs in launch profiling state mgmt, and get all tests p…
armcknight May 15, 2024
544890d
fix tvos build
armcknight May 15, 2024
ccf77d8
fix build issue
armcknight May 15, 2024
8b6a180
pr feedback
armcknight May 15, 2024
33c28e0
fix build
armcknight May 15, 2024
12f0397
clean up launch profile state after each test
armcknight May 15, 2024
7eff3a3
add test to ensure trace profiler is nil after stopping launch profiler
armcknight May 15, 2024
86b8815
remove comment after fixing the test situation
armcknight May 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 11 additions & 9 deletions Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class ProfilingUITests: BaseUITest {
func testProfiledAppLaunches() throws {
if #available(iOS 16, *) {
app.launchArguments.append("--io.sentry.wipe-data")
setDefaultLaunchArgs()
launchApp()

// First launch enables in-app profiling by setting traces/profiles sample rates to 1 (which is the default configuration in the sample app), but not launch profiling; assert that we did not write a config to allow the next launch to be profiled.
Expand Down Expand Up @@ -162,6 +163,15 @@ extension ProfilingUITests {
})
XCTAssert(try XCTUnwrap(sample["thread_id"] as? String) == "259") // the main thread is always ID 259
}

/**
* These cause traces to run the profiler, which can overwrite the launch profile file we need to retrieve to make assertions in the UI test.
*/
func setDefaultLaunchArgs() {
app.launchArguments.append("--disable-swizzling")
app.launchArguments.append("--disable-auto-performance-tracing")
app.launchArguments.append("--disable-uiviewcontroller-tracing")
}

/**
* Performs the various operations for the launch profiler test case:
Expand Down Expand Up @@ -216,16 +226,8 @@ extension ProfilingUITests {
if shouldDisableTracing {
app.launchArguments.append("--disable-tracing")
}
if shouldDisableSwizzling {
app.launchArguments.append("--disable-swizzling")
}
if shouldDisableAutoPerformanceTracking {
app.launchArguments.append("--disable-auto-performance-tracing")
}
if shouldDisableUIViewControllerTracing {
app.launchArguments.append("--disable-uiviewcontroller-tracing")
}

setDefaultLaunchArgs()
launchApp()

let sdkOptionsConfigurationAllowsLaunchProfiling = !(shouldDisableTracing || shouldDisableSwizzling || shouldDisableAutoPerformanceTracking || shouldDisableUIViewControllerTracing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate {

@IBAction func viewLaunchProfile(_ sender: Any) {
profilingUITestDataMarshalingTextField.text = "<fetching...>"
withProfile(fileName: "launchProfile") { file in
withProfile(fileName: "profile") { file in
handleContents(file: file)
}
}
Expand Down
16 changes: 10 additions & 6 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,8 @@
7DC8310A2398283C0043DD9A /* SentryCrashIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DC831082398283C0043DD9A /* SentryCrashIntegration.h */; };
7DC8310C2398283C0043DD9A /* SentryCrashIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC831092398283C0043DD9A /* SentryCrashIntegration.m */; };
840A11122B61E27500650D02 /* SentrySamplerDecision.m in Sources */ = {isa = PBXBuildFile; fileRef = 840A11102B61E27500650D02 /* SentrySamplerDecision.m */; };
840A11132B61FE5800650D02 /* SentryAppLaunchProfilingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 840A11092B5F47F700650D02 /* SentryAppLaunchProfilingTests.m */; };
841325BC2BF4184B0029228F /* TestHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B944FAD2469B43700A10721 /* TestHub.swift */; };
841325C52BF49EC40029228F /* SentryLaunchProfiling+Tests.h in Headers */ = {isa = PBXBuildFile; fileRef = 841325C42BF49EC40029228F /* SentryLaunchProfiling+Tests.h */; };
84281C432A578E5600EE88F2 /* SentryProfilerState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84281C422A578E5600EE88F2 /* SentryProfilerState.mm */; };
84281C462A57905700EE88F2 /* SentrySample.h in Headers */ = {isa = PBXBuildFile; fileRef = 84281C442A57905700EE88F2 /* SentrySample.h */; };
84281C472A57905700EE88F2 /* SentrySample.m in Sources */ = {isa = PBXBuildFile; fileRef = 84281C452A57905700EE88F2 /* SentrySample.m */; };
Expand Down Expand Up @@ -681,6 +681,7 @@
848A451D2BBF9504006AAAEC /* SentryProfilerTestHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 848A451C2BBF9504006AAAEC /* SentryProfilerTestHelpers.m */; };
848A451E2BBF9504006AAAEC /* SentryProfilerTestHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 848A451B2BBF9504006AAAEC /* SentryProfilerTestHelpers.h */; };
849AC40029E0C1FF00889C16 /* SentryFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849AC3FF29E0C1FF00889C16 /* SentryFormatterTests.swift */; };
84A305492BC7328400D84283 /* SentryAppLaunchProfilingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A305472BC72A0A00D84283 /* SentryAppLaunchProfilingTests.swift */; };
84A305572BC9EF8C00D84283 /* SentryLegacyProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 84A305552BC9EF8C00D84283 /* SentryLegacyProfiler.h */; };
84A305582BC9EF8C00D84283 /* SentryLegacyProfiler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84A305562BC9EF8C00D84283 /* SentryLegacyProfiler.mm */; };
84A5D75B29D5170700388BFA /* TimeInterval+Sentry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A5D75A29D5170700388BFA /* TimeInterval+Sentry.swift */; };
Expand Down Expand Up @@ -1644,16 +1645,15 @@
7DC27EC423997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAutoBreadcrumbTrackingIntegration.m; sourceTree = "<group>"; };
7DC831082398283C0043DD9A /* SentryCrashIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashIntegration.h; path = include/SentryCrashIntegration.h; sourceTree = "<group>"; };
7DC831092398283C0043DD9A /* SentryCrashIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashIntegration.m; sourceTree = "<group>"; };
840A11092B5F47F700650D02 /* SentryAppLaunchProfilingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAppLaunchProfilingTests.m; sourceTree = "<group>"; };
840A11102B61E27500650D02 /* SentrySamplerDecision.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySamplerDecision.m; sourceTree = "<group>"; };
840A11142B62041600650D02 /* SentryLaunchProfiling+Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryLaunchProfiling+Tests.h"; path = "../Tests/SentryTests/SentryLaunchProfiling+Tests.h"; sourceTree = "<group>"; };
840B7EEA2BBF2ABA008B8120 /* .slather.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .slather.yml; sourceTree = "<group>"; };
840B7EEC2BBF2AFE008B8120 /* .gitattributes */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitattributes; sourceTree = "<group>"; };
840B7EED2BBF2B16008B8120 /* .pre-commit-config.yaml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = ".pre-commit-config.yaml"; sourceTree = "<group>"; };
840B7EEE2BBF2B23008B8120 /* .ruby-version */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".ruby-version"; sourceTree = "<group>"; };
840B7EEF2BBF2B2B008B8120 /* .spi.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .spi.yml; sourceTree = "<group>"; };
840B7EF02BBF2B5F008B8120 /* MIGRATION.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = MIGRATION.md; sourceTree = "<group>"; };
840B7EF22BBF83DF008B8120 /* SentryProfiler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryProfiler+Private.h"; path = "Sources/Sentry/include/SentryProfiler+Private.h"; sourceTree = SOURCE_ROOT; };
841325C42BF49EC40029228F /* SentryLaunchProfiling+Tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SentryLaunchProfiling+Tests.h"; sourceTree = "<group>"; };
8419C0C328C1889D001C8259 /* SentryLegacyProfilerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLegacyProfilerTests.swift; sourceTree = "<group>"; };
84281C422A578E5600EE88F2 /* SentryProfilerState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfilerState.mm; sourceTree = "<group>"; };
84281C442A57905700EE88F2 /* SentrySample.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySample.h; path = ../include/SentrySample.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1721,6 +1721,7 @@
849472822971C2CD002603DE /* SentryNSProcessInfoWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSProcessInfoWrapperTests.swift; sourceTree = "<group>"; };
849472842971C41A002603DE /* SentryNSTimerFactoryTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSTimerFactoryTest.swift; sourceTree = "<group>"; };
849AC3FF29E0C1FF00889C16 /* SentryFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryFormatterTests.swift; sourceTree = "<group>"; };
84A305472BC72A0A00D84283 /* SentryAppLaunchProfilingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAppLaunchProfilingTests.swift; sourceTree = "<group>"; };
84A305552BC9EF8C00D84283 /* SentryLegacyProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryLegacyProfiler.h; path = ../include/SentryLegacyProfiler.h; sourceTree = "<group>"; };
84A305562BC9EF8C00D84283 /* SentryLegacyProfiler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryLegacyProfiler.mm; sourceTree = "<group>"; };
84A305592BC9FD1600D84283 /* SentryLegacyProfiler+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryLegacyProfiler+Test.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3404,7 +3405,7 @@
035E73CB27D575B3005EEB11 /* SentrySamplingProfilerTests.mm */,
035E73CD27D5790A005EEB11 /* SentryThreadMetadataCacheTests.mm */,
03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */,
840A11092B5F47F700650D02 /* SentryAppLaunchProfilingTests.m */,
84A305472BC72A0A00D84283 /* SentryAppLaunchProfilingTests.swift */,
8419C0C328C1889D001C8259 /* SentryLegacyProfilerTests.swift */,
8446F5182BE172290040D57E /* SentryContinuousProfilerTests.swift */,
8431D4522BE1741E009EAEC1 /* SentryProfileTestFixture.swift */,
Expand All @@ -3426,10 +3427,10 @@
8431F00B29B284F200D8DC56 /* SentryTestUtils */ = {
isa = PBXGroup;
children = (
841325C42BF49EC40029228F /* SentryLaunchProfiling+Tests.h */,
7B4C817124D1BC2B0076ACE4 /* SentryFileManager+Test.h */,
7B944FAD2469B43700A10721 /* TestHub.swift */,
7B7A30C924B48523005A4C6E /* SentryHub+Test.h */,
840A11142B62041600650D02 /* SentryLaunchProfiling+Tests.h */,
7BD47B4C268F0B080076A663 /* ClearTestState.swift */,
7B18DE4328D9F8F6004845C6 /* TestNSNotificationCenterWrapper.swift */,
84AC61D829F7643B009EEF61 /* TestDispatchFactory.swift */,
Expand Down Expand Up @@ -4150,6 +4151,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
841325C52BF49EC40029228F /* SentryLaunchProfiling+Tests.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -4228,6 +4230,8 @@
8431EED229B27B1100D8DC56 /* PBXTargetDependency */,
);
name = SentryProfilerTests;
packageProductDependencies = (
);
productName = "Tests-iOS";
productReference = 8431EFD929B27B1100D8DC56 /* SentryProfilerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
Expand Down Expand Up @@ -4959,8 +4963,8 @@
8431EFE129B27B5300D8DC56 /* SentryThreadMetadataCacheTests.mm in Sources */,
8431EFE029B27B5300D8DC56 /* SentryBacktraceTests.mm in Sources */,
8431EFDF29B27B5300D8DC56 /* SentryThreadHandleTests.mm in Sources */,
840A11132B61FE5800650D02 /* SentryAppLaunchProfilingTests.m in Sources */,
8431EFE829B27BAD00D8DC56 /* SentrySystemWrapperTests.swift in Sources */,
84A305492BC7328400D84283 /* SentryAppLaunchProfilingTests.swift in Sources */,
8431EFE529B27BAD00D8DC56 /* SentryNSProcessInfoWrapperTests.swift in Sources */,
8431EFDE29B27B5300D8DC56 /* SentryLegacyProfilerTests.swift in Sources */,
);
Expand Down
2 changes: 2 additions & 0 deletions SentryTestUtils/ClearTestState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class TestCleanup: NSObject {
SentryLegacyProfiler.getCurrentProfiler()?.stop(for: SentryProfilerTruncationReason.normal)
SentryLegacyProfiler.resetConcurrencyTracking()
SentryContinuousProfiler.stop()
removeAppLaunchProfilingConfigFile()
sentry_stopAndDiscardLaunchProfileTracer()
#endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst)

#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
Expand Down
46 changes: 46 additions & 0 deletions SentryTestUtils/SentryLaunchProfiling+Tests.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#import "SentryLaunchProfiling.h"

#if SENTRY_TARGET_PROFILING_SUPPORTED

# import "SentryDefines.h"

@class SentryOptions;
@class SentrySamplerDecision;
@class SentryTracer;

NS_ASSUME_NONNULL_BEGIN

typedef struct {
BOOL shouldProfile;
SentrySamplerDecision *_Nullable tracesDecision;
SentrySamplerDecision *_Nullable profilesDecision;
} SentryLaunchProfileConfig;

SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyTracesSampleRate;
SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRate;
SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfiling;

SENTRY_EXTERN SentryTracer *_Nullable sentry_launchTracer;

SentryLaunchProfileConfig sentry_shouldProfileNextLaunch(SentryOptions *options);

/**
* `sentry_shouldProfileNextLaunch` cannot be exposed to Swift tests because its return type is not
* expressible in Swift. This wraps it and only returns the `BOOL shouldProfile` value in the
* struct.
*/
BOOL sentry_willProfileNextLaunch(SentryOptions *options);

/**
* Contains the logic to start a launch profile. Exposed separately from @c
* sentry_startLaunchProfile, because that function wraps everything in a @c dispatch_once , and
* that path is taken once when @c SenryProfiler.load is called at the start of the test suite, and
* can't be executed again by calling that function.
*/
void _sentry_nondeduplicated_startLaunchProfile(void);

SentryTransactionContext *sentry_context(NSNumber *tracesRate);

NS_ASSUME_NONNULL_END

#endif // SENTRY_TARGET_PROFILING_SUPPORTED
1 change: 1 addition & 0 deletions SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#if SENTRY_TARGET_PROFILING_SUPPORTED
# import "SentryContinuousProfiler.h"
# import "SentryLaunchProfiling.h"
# import "SentryLegacyProfiler+Test.h"
# import "SentryProfiler+Private.h"
#endif // SENTRY_TARGET_PROFILING_SUPPORTED
Expand Down