diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c18f438d7..06e0205f1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Removes unused SentryLogLevel (#5591) - Removes deprecated `setExtraValue` from SentrySpan (#5864) - Removes deprecated getStoreEndpoint (#5591) +- Remove legacy profiling, the only supported profiling is now what was known as continuous V2 (#6386) - Removes deprecated useSpan function (#5591) - Removes deprecated user feedback API, this is replaced with the new feedback API (#5591) - Removes `enablePerformanceV2` option and makes this the default. The app start duration will now finish when the first frame is drawn instead of when the OS posts the UIWindowDidBecomeVisibleNotification. (#6008) diff --git a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift index a17b884035..1b241a3acb 100644 --- a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift +++ b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift @@ -159,10 +159,6 @@ public enum SentrySDKOverrides: String, CaseIterable { case tracing = "Tracing" public enum Profiling: String, SentrySDKOverride { - #if !SDK_V9 - case sampleRate = "--io.sentry.profiling.profilesSampleRate" - case samplerValue = "--io.sentry.profiling.profilesSamplerValue" - #endif // !SDK_V9 case disableAppStartProfiling = "--io.sentry.profiling.disable-app-start-profiling" case manualLifecycle = "--io.sentry.profiling.profile-lifecycle-manual" case sessionSampleRate = "--io.sentry.profiling.profile-session-sample-rate" @@ -266,11 +262,7 @@ private extension SentrySDKOverride { extension SentrySDKOverrides.Profiling { public var overrideType: OverrideType { switch self { - #if SDK_V9 case .sessionSampleRate: return .float - #else - case .sampleRate, .samplerValue, .sessionSampleRate: return .float - #endif // !SDK_V9 case .disableAppStartProfiling, .manualLifecycle, .disableUIProfiling, .slowLoadMethod, .immediateStop: return .boolean } } @@ -363,11 +355,7 @@ extension SentrySDKOverrides.Special { extension SentrySDKOverrides.Profiling { public var ignoresDisableEverything: Bool { switch self { - #if SDK_V9 case .sessionSampleRate, .manualLifecycle, .slowLoadMethod, .immediateStop: return true - #else - case .sampleRate, .samplerValue, .sessionSampleRate, .manualLifecycle, .slowLoadMethod, .immediateStop: return true - #endif // SDK_V9 case .disableAppStartProfiling, .disableUIProfiling: return false } } diff --git a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift index de938f1fa7..86bd929f51 100644 --- a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift +++ b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift @@ -469,17 +469,6 @@ extension SentrySDKWrapper { #if !os(tvOS) && !os(watchOS) && !os(visionOS) extension SentrySDKWrapper { func configureProfiling(_ options: Options) { - #if !SDK_V9 - if let sampleRate = SentrySDKOverrides.Profiling.sampleRate.floatValue { - options.profilesSampleRate = NSNumber(value: sampleRate) - } - if let samplerValue = SentrySDKOverrides.Profiling.samplerValue.floatValue { - options.profilesSampler = { _ in - return NSNumber(value: samplerValue) - } - } - #endif // !SDK_V9 - if !SentrySDKOverrides.Profiling.disableUIProfiling.boolValue { options.configureProfiling = { $0.lifecycle = SentrySDKOverrides.Profiling.manualLifecycle.boolValue ? .manual : .trace diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m index 5a0f8057a2..c6d1ea03e5 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m @@ -51,27 +51,6 @@ - (BOOL)application:(UIApplication *)application }; } -#if !SDK_V9 - if (env[@"--io.sentry.profiling.profilesSampleRate"] != nil) { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - options.profilesSampleRate = - @([env[@"--io.sentry.profiling.profilesSampleRate"] floatValue]); -# pragma clang diagnostic pop - } - - if (env[@"--io.sentry.profilesSamplerValue"] != nil) { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - options.profilesSampler - = ^NSNumber *_Nullable(SentrySamplingContext *_Nonnull samplingContext) - { - return @([env[@"--io.sentry.profilesSamplerValue"] floatValue]); - }; -# pragma clang diagnostic pop - } -#endif // !SDK_V9 - SentryHttpStatusCodeRange *httpStatusCodeRange = [[SentryHttpStatusCodeRange alloc] initWithMin:400 max:599]; options.failedRequestStatusCodes = @[ httpStatusCodeRange ]; diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift index 1c72308e58..f59c20cd01 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift @@ -22,45 +22,6 @@ class ProfilingUITests: BaseUITest { try performTest(lifecycle: .manual) } - - /** - * We had a bug where we forgot to install the frames tracker into the profiler, so weren't sending any GPU frame information with profiles. Since it's not possible to enforce such installation via the compiler, we test for the results we expect here, by starting a transaction, triggering an ANR which will cause degraded frame rendering, stop the transaction, and inspect the profile payload. - */ - func testProfilingGPUInfo() throws { - if #available(iOS 16, *) { - app.launchArguments.append(contentsOf: [ - SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue, - - // we're only interested in the manual transaction, the automatic stuff messes up how we try to retrieve the target profile info - SentrySDKOverrides.Other.disableSwizzling.rawValue, - - SentrySDKOverrides.Profiling.disableAppStartProfiling.rawValue - ]) - app.launchEnvironment[SentrySDKOverrides.Profiling.sampleRate.rawValue] = "1.0" - launchApp() - - goToTransactions() - startTransaction() - - app.buttons["appHangFullyBlockingThreadSleeping"].afterWaitingForExistence("Couldn't find button to trigger fully blocking AppHang.").tap() - stopTransaction() - - goToProfiling() - retrieveLastProfileData() - let profileDict = try marshalJSONDictionaryFromApp() - - let metrics = try XCTUnwrap(profileDict["measurements"] as? [String: Any]) - // We can only be sure about frozen frames when triggering an ANR. - // It could be that there is no slow frame for the captured transaction. - let frozenFrames = try XCTUnwrap(metrics["frozen_frame_renders"] as? [String: Any]) - let frozenFrameValues = try XCTUnwrap(frozenFrames["values"] as? [[String: Any]]) - XCTAssertFalse(frozenFrameValues.isEmpty, "The test triggered an ANR while the transaction is running. There must be at least one frozen frame, but there was none.") - - let frameRates = try XCTUnwrap(metrics["screen_frame_rates"] as? [String: Any]) - let frameRateValues = try XCTUnwrap(frameRates["values"] as? [[String: Any]]) - XCTAssertFalse(frameRateValues.isEmpty) - } - } } extension ProfilingUITests { diff --git a/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift b/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift index 443ff30f02..aaa959eb40 100644 --- a/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift +++ b/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift @@ -59,10 +59,6 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate { } @IBAction func sampleRateEdited(_ sender: UITextField) { - #if !SDK_V9 - var sampleRate = SentrySDKOverrides.Profiling.sampleRate - sampleRate.floatValue = getSampleRateOverride(field: sender) - #endif // !SDK_V9 } @IBAction func tracesSampleRateEdited(_ sender: UITextField) { @@ -77,11 +73,6 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate { @IBAction func defineProfilesSampleRateToggled(_ sender: UISwitch) { sampleRateField.isEnabled = sender.isOn - - #if !SDK_V9 - var sampleRate = SentrySDKOverrides.Profiling.sampleRate - sampleRate.floatValue = getSampleRateOverride(field: sampleRateField) - #endif // !SDK_V9 } @IBAction func defineTracesSampleRateToggled(_ sender: UISwitch) { @@ -169,18 +160,6 @@ private extension ProfilingViewController { func optionsConfiguration() { guard let options = SentrySDKInternal.currentHub().getClient()?.options else { return } - #if !SDK_V9 - if let sampleRate = options.profilesSampleRate { - sampleRateField.text = String(format: "%.2f", sampleRate.floatValue) - sampleRateField.isEnabled = true - profilesSampleRateSwitch.isOn = true - } else { - sampleRateField.isEnabled = false - sampleRateField.text = "nil" - profilesSampleRateSwitch.isOn = false - } - #endif // !SDK_V9 - if let sampleRate = options.tracesSampleRate { tracesSampleRateField.text = String(format: "%.2f", sampleRate.floatValue) tracesSampleRateField.isEnabled = true diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 0166c545b2..faa23f5258 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -582,7 +582,6 @@ 8431EFD329B27B1100D8DC56 /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 630C01951EC341D600C52CEF /* Resources */; }; 8431EFDC29B27B5300D8DC56 /* SentryProfilerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */; }; 8431EFDD29B27B5300D8DC56 /* SentrySamplingProfilerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 035E73CB27D575B3005EEB11 /* SentrySamplingProfilerTests.mm */; }; - 8431EFDE29B27B5300D8DC56 /* SentryTraceProfilerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8419C0C328C1889D001C8259 /* SentryTraceProfilerTests.swift */; }; 8431EFDF29B27B5300D8DC56 /* SentryThreadHandleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 035E73C927D57398005EEB11 /* SentryThreadHandleTests.mm */; }; 8431EFE029B27B5300D8DC56 /* SentryBacktraceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 035E73C727D56757005EEB11 /* SentryBacktraceTests.mm */; }; 8431EFE129B27B5300D8DC56 /* SentryThreadMetadataCacheTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 035E73CD27D5790A005EEB11 /* SentryThreadMetadataCacheTests.mm */; }; @@ -1898,7 +1897,6 @@ 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 = ""; }; 841325DE2BFED0510029228F /* TestFramesTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestFramesTracker.swift; sourceTree = ""; }; - 8419C0C328C1889D001C8259 /* SentryTraceProfilerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTraceProfilerTests.swift; sourceTree = ""; }; 84281C422A578E5600EE88F2 /* SentryProfilerState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfilerState.mm; sourceTree = ""; }; 84281C442A57905700EE88F2 /* SentrySample.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySample.h; path = ../include/SentrySample.h; sourceTree = ""; }; 84281C452A57905700EE88F2 /* SentrySample.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySample.m; sourceTree = ""; }; @@ -4018,7 +4016,6 @@ 845CEB162D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift */, 84A898CD2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift */, 845CEAEE2D83F79500B6B325 /* SentryProfilingPublicAPITests.swift */, - 8419C0C328C1889D001C8259 /* SentryTraceProfilerTests.swift */, 8446F5182BE172290040D57E /* SentryContinuousProfilerTests.swift */, 8431D4522BE1741E009EAEC1 /* SentryProfileTestFixture.swift */, ); @@ -6449,7 +6446,6 @@ 84F2A1CE2E06001300A94524 /* (null) in Sources */, 845CEB172D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift in Sources */, 8431EFE529B27BAD00D8DC56 /* SentryNSProcessInfoWrapperTests.swift in Sources */, - 8431EFDE29B27B5300D8DC56 /* SentryTraceProfilerTests.swift in Sources */, 84A898CE2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Sources/Sentry/Profiling/SentryLaunchProfiling.m b/Sources/Sentry/Profiling/SentryLaunchProfiling.m index 7732a41ab9..ae92688f25 100644 --- a/Sources/Sentry/Profiling/SentryLaunchProfiling.m +++ b/Sources/Sentry/Profiling/SentryLaunchProfiling.m @@ -28,9 +28,6 @@ NSString *const kSentryLaunchProfileConfigKeyTracesSampleRand = @"traces.sample_rand"; NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRate = @"profiles"; NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRand = @"profiles.sample_rand"; -# if !SDK_V9 -NSString *const kSentryLaunchProfileConfigKeyContinuousProfiling = @"continuous-profiling"; -# endif // !SDK_V9 NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2 = @"continuous-profiling-v2-enabled"; NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle @@ -83,15 +80,6 @@ profileOptions:profileOptions]; } -void -_sentry_continuousProfilingV1_startLaunchProfile(BOOL shouldWaitForFullDisplay) -{ - sentry_profileConfiguration = - [[SentryProfileConfiguration alloc] initWaitingForFullDisplay:shouldWaitForFullDisplay - continuousV1:YES]; - [SentryContinuousProfiler start]; -} - /** * Hydrate any relevant launch profiling options persisted from the previous launch and start a * trace that will automatically start a manual lifecycle continuous profile (v2) @@ -162,7 +150,7 @@ } SentryLaunchProfileDecision -sentry_launchShouldHaveContinuousProfilingV2(SentryOptions *options) +sentry_launchShouldHaveContinuousProfiling(SentryOptions *options) { if (!options.profiling.profileAppStarts) { SENTRY_LOG_DEBUG(@"Continuous profiling v2 enabled but disabled app start profiling, " @@ -219,8 +207,8 @@ SentryLaunchProfileDecision sentry_shouldProfileNextLaunch(SentryOptions *options) { - if ([options isContinuousProfilingV2Enabled]) { - return sentry_launchShouldHaveContinuousProfilingV2(options); + if ([options isContinuousProfilingEnabled]) { + return sentry_launchShouldHaveContinuousProfiling(options); } return (SentryLaunchProfileDecision) { NO, nil, nil }; } @@ -269,22 +257,10 @@ BOOL isContinuousV2 = [persistedLaunchConfigOptionsDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2] boolValue]; -# if !SDK_V9 - BOOL isContinuousV1 = - [persistedLaunchConfigOptionsDict[kSentryLaunchProfileConfigKeyContinuousProfiling] - boolValue]; - if (isContinuousV1 && isContinuousV2) { - SENTRY_LOG_WARN(@"Launch profile misconfiguration detected."); - _sentry_cleanUpConfigFile(); - return; - } -# else - BOOL isContinuousV1 = false; -# endif // !SDK_V9 SentrySamplerDecision *decision = _sentry_profileSampleDecision(persistedLaunchConfigOptionsDict); - if (!isContinuousV1 && nil == decision) { + if (nil == decision) { SENTRY_LOG_DEBUG(@"Couldn't hydrate the persisted sample decision."); _sentry_cleanUpConfigFile(); return; @@ -302,13 +278,6 @@ BOOL shouldWaitForFullDisplay = shouldWaitForFullDisplayValue.boolValue; - if (isContinuousV1) { - SENTRY_LOG_DEBUG(@"Starting continuous launch profile v1."); - _sentry_continuousProfilingV1_startLaunchProfile(shouldWaitForFullDisplay); - _sentry_cleanUpConfigFile(); - return; - } - SentryProfileOptions *profileOptions = nil; if (isContinuousV2) { SENTRY_LOG_DEBUG(@"Starting continuous launch profile v2."); @@ -336,8 +305,7 @@ SentryProfileLifecycleTrace, shouldWaitForFullDisplay); } else { sentry_profileConfiguration = - [[SentryProfileConfiguration alloc] initWaitingForFullDisplay:shouldWaitForFullDisplay - continuousV1:NO]; + [[SentryProfileConfiguration alloc] initWaitingForFullDisplay:shouldWaitForFullDisplay]; } // trace lifecycle UI profiling (continuous profiling v2) and trace-based profiling both join @@ -365,43 +333,22 @@ [NSMutableDictionary dictionary]; configDict[kSentryLaunchProfileConfigKeyWaitForFullDisplay] = @(options.enableTimeToFullDisplayTracing); -# if !SDK_V9 if ([options isContinuousProfilingEnabled]) { -# endif // !SDK_V9 - if ([options isContinuousProfilingV2Enabled]) { - SENTRY_LOG_DEBUG(@"Configuring continuous launch profile v2."); - configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2] = @YES; - configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle] = - @(options.profiling.lifecycle); - if (options.profiling.lifecycle == SentryProfileLifecycleTrace) { - configDict[kSentryLaunchProfileConfigKeyTracesSampleRate] - = config.tracesDecision.sampleRate; - configDict[kSentryLaunchProfileConfigKeyTracesSampleRand] - = config.tracesDecision.sampleRand; - } - configDict[kSentryLaunchProfileConfigKeyProfilesSampleRate] - = config.profilesDecision.sampleRate; - configDict[kSentryLaunchProfileConfigKeyProfilesSampleRand] - = config.profilesDecision.sampleRand; - } else { -# if !SDK_V9 - SENTRY_LOG_DEBUG(@"Configuring continuous launch profile."); - configDict[kSentryLaunchProfileConfigKeyContinuousProfiling] = @YES; -# endif // !SDK_V9 + SENTRY_LOG_DEBUG(@"Configuring continuous launch profile v2."); + configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2] = @YES; + configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle] = + @(options.profiling.lifecycle); + if (options.profiling.lifecycle == SentryProfileLifecycleTrace) { + configDict[kSentryLaunchProfileConfigKeyTracesSampleRate] + = config.tracesDecision.sampleRate; + configDict[kSentryLaunchProfileConfigKeyTracesSampleRand] + = config.tracesDecision.sampleRand; } -# if !SDK_V9 - } else { - SENTRY_LOG_DEBUG(@"Configuring trace launch profile."); - configDict[kSentryLaunchProfileConfigKeyTracesSampleRate] - = config.tracesDecision.sampleRate; - configDict[kSentryLaunchProfileConfigKeyTracesSampleRand] - = config.tracesDecision.sampleRand; configDict[kSentryLaunchProfileConfigKeyProfilesSampleRate] = config.profilesDecision.sampleRate; configDict[kSentryLaunchProfileConfigKeyProfilesSampleRand] = config.profilesDecision.sampleRand; } -# endif // !SDK_V9 writeAppLaunchProfilingConfigFile(configDict); }]; } diff --git a/Sources/Sentry/Profiling/SentryProfileConfiguration.m b/Sources/Sentry/Profiling/SentryProfileConfiguration.m index 096fb26d31..8f03717df5 100644 --- a/Sources/Sentry/Profiling/SentryProfileConfiguration.m +++ b/Sources/Sentry/Profiling/SentryProfileConfiguration.m @@ -23,14 +23,12 @@ - (instancetype)initWithProfileOptions:(SentryProfileOptions *)options } - (instancetype)initWaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay - continuousV1:(BOOL)continuousV1 { if (!(self = [super init])) { return nil; } _waitForFullDisplay = shouldWaitForFullDisplay; - _isContinuousV1 = continuousV1; _isProfilingThisLaunch = YES; return self; } @@ -39,7 +37,7 @@ - (instancetype)initContinuousProfilingV2WaitingForFullDisplay:(BOOL)shouldWaitF samplerDecision:(SentrySamplerDecision *)decision profileOptions:(SentryProfileOptions *)options { - if (!(self = [self initWaitingForFullDisplay:shouldWaitForFullDisplay continuousV1:NO])) { + if (!(self = [self initWaitingForFullDisplay:shouldWaitForFullDisplay])) { return nil; } diff --git a/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm b/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm index 0f613bd6dc..e831ff9cfc 100644 --- a/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm +++ b/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm @@ -176,17 +176,6 @@ sentry_stringFromSentryID(internalTraceId)); _unsafe_cleanUpContinuousProfilerV2(); } else if (internalTraceId != nil) { -# if !SDK_V9 - SentryClient *_Nullable client = hub.getClient; - if (client == nil) { - SENTRY_LOG_ERROR(@"No client found, skipping cleanup."); - return; - } - if (sentry_isContinuousProfilingEnabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { - SENTRY_LOG_ERROR(@"Tracers are not tracked with continuous profiling V1."); - return; - } -# endif // !SDK_V9 if (_gTracersToProfilers == nil) { SENTRY_LOG_ERROR(@"Tracer to profiler should have already been initialized by the " @@ -269,7 +258,7 @@ SentryClient *_Nullable client = hub.getClient; if (isProfiling && client != nil - && sentry_isContinuousProfilingV2Enabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client)) + && sentry_isContinuousProfilingEnabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client)) && sentry_isProfilingCorrelatedToTraces(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { SENTRY_LOG_DEBUG(@"Stopping tracking root span tracer with profilerReferenceId %@", sentry_stringFromSentryID(transaction.trace.profilerReferenceID)); @@ -355,7 +344,7 @@ } SentryClient *_Nullable client = hub.getClient; if (client != nil - && sentry_isContinuousProfilingV2Enabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { + && sentry_isContinuousProfilingEnabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { // non launch profile if (sentry_getParentSpanID(transactionContext) != nil) { SENTRY_LOG_DEBUG(@"Not a root span, will not start automatically for trace lifecycle."); @@ -371,15 +360,8 @@ } BOOL profileShouldBeSampled = configuration.profilesSamplerDecision.decision == kSentrySampleDecisionYes; -# if !SDK_V9 - BOOL isContinuousProfiling = client != nil - && sentry_isContinuousProfilingEnabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client)); - BOOL shouldStartNormalTraceProfile = !isContinuousProfiling && profileShouldBeSampled; -# else - BOOL shouldStartNormalTraceProfile = profileShouldBeSampled; -# endif // !SDK_V9 - - if (sentry_isTracingAppLaunch || shouldStartNormalTraceProfile) { + + if (sentry_isTracingAppLaunch || profileShouldBeSampled) { SentryId *internalID = sentry_getSentryId(); if ([SentryTraceProfiler startWithTracer:internalID]) { SENTRY_LOG_DEBUG(@"Started profiler for trace %@ with internal id %@", diff --git a/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m b/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m index 8d54aa2a91..1eb7fdfc2e 100644 --- a/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m +++ b/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m @@ -7,19 +7,11 @@ # import "SentrySamplerDecision.h" # import "SentrySwift.h" -# if !SDK_V9 BOOL sentry_isContinuousProfilingEnabled(SentryClient *client) { return [client.options isContinuousProfilingEnabled]; } -# endif // !SDK_V9 - -BOOL -sentry_isContinuousProfilingV2Enabled(SentryClient *client) -{ - return [client.options isContinuousProfilingV2Enabled]; -} BOOL sentry_isProfilingCorrelatedToTraces(SentryClient *client) diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index a3ae913d5c..1dbfd97ca3 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -537,81 +537,6 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull */ @property (nullable, nonatomic, copy) SentryProfilingConfigurationBlock configureProfiling; -# if !SDK_V9 - -/** - * @note Profiling is not supported on watchOS or tvOS. - * Indicates the percentage profiles being sampled out of the sampled transactions. - * @note The value needs to be >= @c 0.0 and \<= @c 1.0. When setting a value out of range - * the SDK sets it to @c 0. When set to a valid nonnull value, this property is dependent on - * @c tracesSampleRate -- if @c tracesSampleRate is @c 0 (default), no profiles will be collected no - * matter what this property is set to. This property is used to undersample profiles *relative to* - * @c tracesSampleRate . - * @note Setting this value to @c nil enables an experimental new profiling mode, called continuous - * profiling. This allows you to start and stop a profiler any time with @c SentrySDK.startProfiler - * and @c SentrySDK.stopProfiler, which can run with no time limit, periodically uploading profiling - * data. You can also set @c SentryOptions.enableAppLaunchProfiling to have the profiler start on - * app launch; there is no automatic stop, you must stop it manually at some later time if you - * choose to do so. Sampling rates do not apply to continuous profiles, including those - * automatically started for app launches. If you wish to sample them, you must do so at the - * callsites where you use the API or configure launch profiling. Continuous profiling is not - * automatically started for performance transactions as was the previous version of profiling. - * @seealso https://docs.sentry.io/platforms/apple/profiling/ for more information about the - * different profiling modes. - * @note The default is @c nil (which implies continuous profiling mode). - * @warning The new continuous profiling mode is experimental and may still contain bugs. - * @note Profiling is automatically disabled if a thread sanitizer is attached. - * @warning This property is deprecated and will be removed in a future version of the SDK. See - * @c SentryProfileOptions.sessionSampleRate. - */ -@property (nullable, nonatomic, strong) NSNumber *profilesSampleRate DEPRECATED_MSG_ATTRIBUTE( - "This property is deprecated and will be removed in a future version of the SDK. See " - "SentryProfileOptions.sessionSampleRate"); - -/** - * @note Profiling is not supported on watchOS or tvOS. - * A callback to a user defined profiles sampler function. This is similar to setting - * @c profilesSampleRate but instead of a static value, the callback function will be called to - * determine the sample rate. - * @note If @c enableAppLaunchProfiling is @c YES , this function will be called during SDK start - * with @c SentrySamplingContext.forNextAppLaunch set to @c YES, and the result will be persisted to - * disk for use on the next app launch. - * @note Profiling is automatically disabled if a thread sanitizer is attached. - * @warning This property is deprecated and will be removed in a future version of the SDK. See - * @c SentryProfileOptions.sessionSampleRate . - */ -@property (nullable, nonatomic) - SentryTracesSamplerCallback profilesSampler NS_SWIFT_SENDABLE DEPRECATED_MSG_ATTRIBUTE( - "This property is deprecated and will be removed in a future version of the SDK. See " - "SentryProfileOptions.sessionSampleRate"); - -/** - * If profiling should be enabled or not. - * @note Profiling is not supported on watchOS or tvOS. - * @note This only returns whether or not trace-based profiling is enabled. If it is not, then - * continuous profiling is effectively enabled, and calling SentrySDK.startProfiler will - * successfully start a continuous profile. - * @returns @c YES if either @c profilesSampleRate > @c 0 and \<= @c 1 , or @c profilesSampler is - * set, otherwise @c NO. - * @note Profiling is automatically disabled if a thread sanitizer is attached. - * @warning This property is deprecated and will be removed in a future version of the SDK. - */ -@property (nonatomic, assign, readonly) BOOL isProfilingEnabled DEPRECATED_MSG_ATTRIBUTE( - "This property is deprecated and will be removed in a future version of the SDK"); - -/** - * @brief Whether to enable the sampling profiler. - * @note Profiling is not supported on watchOS or tvOS. - * @deprecated Use @c profilesSampleRate instead. Setting @c enableProfiling to @c YES is the - * equivalent of setting @c profilesSampleRate to @c 1.0 If @c profilesSampleRate is set, it will - * take precedence over this setting. - * @note Default is @c NO. - * @note Profiling is automatically disabled if a thread sanitizer is attached. - */ -@property (nonatomic, assign) BOOL enableProfiling DEPRECATED_MSG_ATTRIBUTE( - "Use profilesSampleRate or profilesSampler instead. This property will be removed in a future " - "version of the SDK"); -# endif // !SDK_V9 #endif // SENTRY_TARGET_PROFILING_SUPPORTED /** diff --git a/Sources/Sentry/SentryHub.m b/Sources/Sentry/SentryHub.m index e92c237a0b..50ede302c2 100644 --- a/Sources/Sentry/SentryHub.m +++ b/Sources/Sentry/SentryHub.m @@ -455,14 +455,6 @@ - (SentryTracer *)startTransactionWithContext:(SentryTransactionContext *)transa sampleRate:tracesSamplerDecision.sampleRate sampleRand:tracesSamplerDecision.sampleRand]; -#if SENTRY_TARGET_PROFILING_SUPPORTED && !SDK_V9 - if (![self.client.options isContinuousProfilingEnabled]) { - SentrySamplerDecision *profilesSamplerDecision = sentry_sampleTraceProfile( - samplingContext, tracesSamplerDecision, self.client.options); - configuration.profilesSamplerDecision = profilesSamplerDecision; - } -#endif // SENTRY_TARGET_PROFILING_SUPPORTED && !SDK_V9 - SentryTracer *tracer = [[SentryTracer alloc] initWithTransactionContext:transactionContext hub:self configuration:configuration]; diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index 48ebc47c3c..c9519f7d28 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -117,15 +117,6 @@ - (instancetype)init self.enableNetworkBreadcrumbs = YES; self.enableLogs = NO; self.tracesSampleRate = nil; -#if SENTRY_TARGET_PROFILING_SUPPORTED -# if !SDK_V9 - _enableProfiling = NO; -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - self.profilesSampleRate = SENTRY_INITIAL_PROFILES_SAMPLE_RATE; -# pragma clang diagnostic pop -# endif // !SDK_V9 -#endif // SENTRY_TARGET_PROFILING_SUPPORTED self.enableCoreDataTracing = YES; _enableSwizzling = YES; self.swizzleClassNameExcludes = [NSSet new]; @@ -290,73 +281,16 @@ - (BOOL)isTracingEnabled } #if SENTRY_TARGET_PROFILING_SUPPORTED -# if !SDK_V9 -- (void)setProfilesSampleRate:(NSNumber *)profilesSampleRate -{ - if (profilesSampleRate == nil) { - _profilesSampleRate = nil; - } else if (sentry_isValidSampleRate(profilesSampleRate)) { - _profilesSampleRate = profilesSampleRate; - } else { - _profilesSampleRate = SENTRY_DEFAULT_PROFILES_SAMPLE_RATE; - } -} - -- (BOOL)isProfilingEnabled -{ - return (_profilesSampleRate != nil && [_profilesSampleRate doubleValue] > 0) - || _profilesSampler != nil || _enableProfiling; -} - (BOOL)isContinuousProfilingEnabled { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - // this looks a little weird with the `!self.enableProfiling` but that actually is the - // deprecated way to say "enable trace-based profiling", which necessarily disables continuous - // profiling as they are mutually exclusive modes - return _profilesSampleRate == nil && _profilesSampler == nil && !self.enableProfiling; -# pragma clang diagnostic pop -} - -# endif // !SDK_V9 - -- (BOOL)isContinuousProfilingV2Enabled -{ -# if SDK_V9 return _profiling != nil; -# else - return [self isContinuousProfilingEnabled] && _profiling != nil; -# endif // SDK_V9 } - (BOOL)isProfilingCorrelatedToTraces { -# if SDK_V9 return _profiling != nil && _profiling.lifecycle == SentryProfileLifecycleTrace; -# else - return ![self isContinuousProfilingEnabled] - || (_profiling != nil && _profiling.lifecycle == SentryProfileLifecycleTrace); -# endif // SDK_V9 -} - -# if !SDK_V9 -- (void)setEnableProfiling_DEPRECATED_TEST_ONLY:(BOOL)enableProfiling_DEPRECATED_TEST_ONLY -{ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - self.enableProfiling = enableProfiling_DEPRECATED_TEST_ONLY; -# pragma clang diagnostic pop -} - -- (BOOL)enableProfiling_DEPRECATED_TEST_ONLY -{ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - return self.enableProfiling; -# pragma clang diagnostic pop } -# endif // !SDK_V9 #endif // SENTRY_TARGET_PROFILING_SUPPORTED #if SENTRY_UIKIT_AVAILABLE diff --git a/Sources/Sentry/SentryProfiler.mm b/Sources/Sentry/SentryProfiler.mm index 5906fae1e9..56c2054dee 100644 --- a/Sources/Sentry/SentryProfiler.mm +++ b/Sources/Sentry/SentryProfiler.mm @@ -55,7 +55,7 @@ SentryProfileOptions *_Nullable nullableOptions = sentry_profileConfiguration.profileOptions; if (nil == nullableOptions) { - return !sentry_profileConfiguration.isContinuousV1; + return YES; } SentryProfileOptions *_Nonnull options = SENTRY_UNWRAP_NULLABLE(SentryProfileOptions, nullableOptions); @@ -66,17 +66,6 @@ void sentry_configureContinuousProfiling(SentryOptions *options) { -# if !SDK_V9 - if (![options isContinuousProfilingEnabled]) { - if (options.configureProfiling != nil) { - SENTRY_LOG_WARN(@"In order to configure SentryProfileOptions you must remove " - @"configuration of the older SentryOptions.profilesSampleRate, " - @"SentryOptions.profilesSampler and/or SentryOptions.enableProfiling"); - } - return; - } -# endif // !SDK_V9 - if (options.configureProfiling == nil) { SENTRY_LOG_DEBUG(@"Continuous profiling V2 configuration not set by SDK consumer, nothing " @"to do here."); @@ -143,7 +132,7 @@ } # endif // SENTRY_HAS_UIKIT - if (configurationFromLaunch.isContinuousV1 || v2LifecycleIsManual) { + if (v2LifecycleIsManual) { SENTRY_LOG_DEBUG(@"Continuous manual launch profiles aren't stopped on calls to " @"SentrySDK.start, " @"not stopping profile."); diff --git a/Sources/Sentry/SentrySDKInternal.m b/Sources/Sentry/SentrySDKInternal.m index 17a0c9095a..2c61fdb5c6 100644 --- a/Sources/Sentry/SentrySDKInternal.m +++ b/Sources/Sentry/SentrySDKInternal.m @@ -696,18 +696,8 @@ + (void)crash + (void)startProfiler { SentryOptions *options = currentHub.client.options; -# if !SDK_V9 - if (![options isContinuousProfilingEnabled]) { - SENTRY_LOG_WARN( - @"You must disable trace profiling by setting SentryOptions.profilesSampleRate and " - @"SentryOptions.profilesSampler to nil (which is the default initial value for both " - @"properties, so you can also just remove those lines from your configuration " - @"altogether) before attempting to start a continuous profiling session. This behavior " - @"relies on deprecated options and will change in a future version."); -# else if (options == nil) { SENTRY_LOG_WARN(@"Cannot start profiling when options are nil."); -# endif return; } @@ -740,12 +730,6 @@ + (void)stopProfiler // check if we'd be stopping a launch profiler, because then we need to check the hydrated // configuration options, not the current ones if (sentry_profileConfiguration.isProfilingThisLaunch) { - if (sentry_profileConfiguration.isContinuousV1) { - SENTRY_LOG_DEBUG(@"Stopping continuous v1 launch profile."); - [SentryContinuousProfiler stop]; - return; - } - if (sentry_profileConfiguration.profileOptions == nil) { SENTRY_LOG_WARN( @"The current profiler was started on app launch and was configured as a " @@ -767,21 +751,10 @@ + (void)stopProfiler } SentryOptions *options = currentHub.client.options; -# if !SDK_V9 - if (![options isContinuousProfilingEnabled]) { - SENTRY_LOG_WARN( - @"You must disable trace profiling by setting SentryOptions.profilesSampleRate and " - @"SentryOptions.profilesSampler to nil (which is the default initial value for both " - @"properties, so you can also just remove those lines from your configuration " - @"altogether) before attempting to stop a continuous profiling session. This behavior " - @"relies on deprecated options and will change in a future version."); -# else if (options == nil) { SENTRY_LOG_WARN(@"Cannot stop profiling when options are nil."); -# endif return; } - if (options.profiling != nil && options.profiling.lifecycle == SentryProfileLifecycleTrace) { SENTRY_LOG_WARN( @"The profiling lifecycle is set to trace, so you cannot stop profile sessions " diff --git a/Sources/Sentry/SentrySampling.m b/Sources/Sentry/SentrySampling.m index e5645de02c..351fc05661 100644 --- a/Sources/Sentry/SentrySampling.m +++ b/Sources/Sentry/SentrySampling.m @@ -86,43 +86,6 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED -# if !SDK_V9 -SentrySamplerDecision * -sentry_sampleTraceProfile(SentrySamplingContext *context, - SentrySamplerDecision *tracesSamplerDecision, SentryOptions *options) -{ - // Profiles are always undersampled with respect to traces. If the trace is not sampled, - // the profile will not be either. If the trace is sampled, we can proceed to checking - // whether the associated profile should be sampled. - if (tracesSamplerDecision.decision != kSentrySampleDecisionYes) { - return [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionNo - forSampleRate:nil - withSampleRand:nil]; - } - - // Backward compatibility for clients that are still using the enableProfiling option. -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (options.enableProfiling) { - return [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes - forSampleRate:@1.0 - withSampleRand:@1.0]; - } - - NSNumber *callbackRate = _sentry_samplerCallbackRate( - options.profilesSampler, context, SENTRY_DEFAULT_PROFILES_SAMPLE_RATE); -# pragma clang diagnostic pop - if (callbackRate != nil) { - return _sentry_calcSample(callbackRate); - } - -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - return _sentry_calcSampleFromNumericalRate(options.profilesSampleRate); -# pragma clang diagnostic pop -} -# endif // !SDK_V9 - SentrySamplerDecision * sentry_sampleProfileSession(float sessionSampleRate) { diff --git a/Sources/Sentry/SentrySpan.m b/Sources/Sentry/SentrySpan.m index d16e08218c..3e17450c65 100644 --- a/Sources/Sentry/SentrySpan.m +++ b/Sources/Sentry/SentrySpan.m @@ -91,11 +91,7 @@ - (instancetype)initWithContext:(SentrySpanContext *)context _origin = context.origin; #if SENTRY_TARGET_PROFILING_SUPPORTED -# if !SDK_V9 - _isContinuousProfiling = [SentrySDKInternal.options isContinuousProfilingEnabled]; -# else _isContinuousProfiling = SentrySDKInternal.options != nil; -# endif if (_isContinuousProfiling) { _profileSessionID = SentryContinuousProfiler.currentProfilerID.sentryIdString; if (_profileSessionID == nil) { diff --git a/Sources/Sentry/SentyOptionsInternal.m b/Sources/Sentry/SentyOptionsInternal.m index e0eee4c097..d73d9fac1f 100644 --- a/Sources/Sentry/SentyOptionsInternal.m +++ b/Sources/Sentry/SentyOptionsInternal.m @@ -348,30 +348,6 @@ + (BOOL)validateOptions:(NSDictionary *)options [self setBool:options[@"enableCoreDataTracing"] block:^(BOOL value) { sentryOptions.enableCoreDataTracing = value; }]; -#if SENTRY_TARGET_PROFILING_SUPPORTED -# if !SDK_V9 - if ([options[@"profilesSampleRate"] isKindOfClass:[NSNumber class]]) { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - sentryOptions.profilesSampleRate = options[@"profilesSampleRate"]; -# pragma clang diagnostic pop - } - -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - if ([self isBlock:options[@"profilesSampler"]]) { - sentryOptions.profilesSampler = options[@"profilesSampler"]; - } -# pragma clang diagnostic pop - -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self setBool:options[@"enableProfiling"] - block:^(BOOL value) { sentryOptions.enableProfiling = value; }]; -# pragma clang diagnostic pop -# endif // !SDK_V9 -#endif // SENTRY_TARGET_PROFILING_SUPPORTED - [self setBool:options[@"sendClientReports"] block:^(BOOL value) { sentryOptions.sendClientReports = value; }]; diff --git a/Sources/Sentry/include/SentryLaunchProfiling.h b/Sources/Sentry/include/SentryLaunchProfiling.h index 99b73a173b..35de6a3d7f 100644 --- a/Sources/Sentry/include/SentryLaunchProfiling.h +++ b/Sources/Sentry/include/SentryLaunchProfiling.h @@ -18,9 +18,6 @@ SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyTracesSampleRate; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyTracesSampleRand; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRate; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRand; -# if !SDK_V9 -SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfiling; -# endif // !SDK_V9 SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyWaitForFullDisplay; diff --git a/Sources/Sentry/include/SentryOptions+Private.h b/Sources/Sentry/include/SentryOptions+Private.h index fae56bbbcd..d9dd3bbd4f 100644 --- a/Sources/Sentry/include/SentryOptions+Private.h +++ b/Sources/Sentry/include/SentryOptions+Private.h @@ -12,19 +12,11 @@ FOUNDATION_EXPORT NSString *const kSentryDefaultEnvironment; #if SENTRY_TARGET_PROFILING_SUPPORTED @property (nonatomic, assign) BOOL enableProfiling_DEPRECATED_TEST_ONLY; -# if !SDK_V9 -/** - * If continuous profiling mode v1 ("beta") is enabled. - * @note Not for use with launch profiles. See functions in @c SentryLaunchProfiling . - */ -- (BOOL)isContinuousProfilingEnabled; -# endif // !SDK_V9 - /** * If UI profiling mode ("continuous v2") is enabled. * @note Not for use with launch profiles. See functions in @c SentryLaunchProfiling . */ -- (BOOL)isContinuousProfilingV2Enabled; +- (BOOL)isContinuousProfilingEnabled; /** * Whether or not the SDK was configured with a profile mode that automatically starts and tracks diff --git a/Sources/Sentry/include/SentryProfileConfiguration.h b/Sources/Sentry/include/SentryProfileConfiguration.h index e2eb75b60e..102aead628 100644 --- a/Sources/Sentry/include/SentryProfileConfiguration.h +++ b/Sources/Sentry/include/SentryProfileConfiguration.h @@ -21,7 +21,6 @@ NS_ASSUME_NONNULL_BEGIN SENTRY_NO_INIT -@property (assign, nonatomic, readonly) BOOL isContinuousV1; @property (assign, nonatomic, readonly) BOOL waitForFullDisplay; @property (assign, nonatomic, readonly) BOOL isProfilingThisLaunch; @@ -42,8 +41,7 @@ SENTRY_NO_INIT /** * Initializer for both trace-based and continuous V1 (aka continuous beta) launch profiles. */ -- (instancetype)initWaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay - continuousV1:(BOOL)continuousV1; +- (instancetype)initWaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay; /** Initializer for launch UI profiles (aka continuous V2). */ - (instancetype)initContinuousProfilingV2WaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay diff --git a/Sources/Sentry/include/SentryProfilingSwiftHelpers.h b/Sources/Sentry/include/SentryProfilingSwiftHelpers.h index e5896e492b..50e5d5555b 100644 --- a/Sources/Sentry/include/SentryProfilingSwiftHelpers.h +++ b/Sources/Sentry/include/SentryProfilingSwiftHelpers.h @@ -19,10 +19,7 @@ NS_ASSUME_NONNULL_BEGIN extern "C" { #endif -#if !SDK_V9 BOOL sentry_isContinuousProfilingEnabled(SentryClient *client); -#endif // !SDK_V9 -BOOL sentry_isContinuousProfilingV2Enabled(SentryClient *client); BOOL sentry_isProfilingCorrelatedToTraces(SentryClient *client); SentryProfileOptions *_Nullable sentry_getProfiling(SentryClient *client); NSString *sentry_stringFromSentryID(SentryId *sentryID); diff --git a/Sources/Sentry/include/SentrySampling.h b/Sources/Sentry/include/SentrySampling.h index 97742fe8e8..2811752c24 100644 --- a/Sources/Sentry/include/SentrySampling.h +++ b/Sources/Sentry/include/SentrySampling.h @@ -14,16 +14,6 @@ SENTRY_EXTERN SentrySamplerDecision *sentry_sampleTrace( SentrySamplingContext *context, SentryOptions *options); #if SENTRY_TARGET_PROFILING_SUPPORTED -/** - * Determines whether a profile should be sampled based on the context, options, and - * whether the trace corresponding to the profile was sampled, to decide whether to configure the - * next launch to start a trace profile. - */ -# if !SDK_V9 -SENTRY_EXTERN SentrySamplerDecision *sentry_sampleTraceProfile(SentrySamplingContext *context, - SentrySamplerDecision *tracesSamplerDecision, SentryOptions *options); -# endif // !SDK_V9 - SENTRY_EXTERN SentrySamplerDecision *sentry_sampleProfileSession(float sessionSampleRate); #endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift b/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift index 66cb989df4..3a51d2ebf7 100644 --- a/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift +++ b/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift @@ -23,7 +23,6 @@ extension SentryAppLaunchProfilingTests { func testContinuousLaunchProfileV2TraceLifecycleConfiguration() throws { // Arrange let options = Options() - options.profilesSampleRate = nil options.tracesSampleRate = 1 options.configureProfiling = { $0.lifecycle = .trace @@ -57,7 +56,6 @@ extension SentryAppLaunchProfilingTests { func testContinuousLaunchProfileV2ManualLifecycleConfiguration() throws { // Arrange let options = Options() - options.profilesSampleRate = nil options.configureProfiling = { $0.lifecycle = .manual $0.sessionSampleRate = 1 @@ -95,7 +93,6 @@ extension SentryAppLaunchProfilingTests { func testLaunchContinuousProfileV2TraceLifecycleNotStoppedOnFullyDisplayed() throws { // Arrange fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = nil fixture.options.configureProfiling = { $0.profileAppStarts = true $0.sessionSampleRate = 1 @@ -127,7 +124,6 @@ extension SentryAppLaunchProfilingTests { func testLaunchContinuousProfileV2ManualLifecycleNotStoppedOnFullyDisplayed() throws { // Arrange - fixture.options.profilesSampleRate = nil fixture.options.configureProfiling = { $0.profileAppStarts = true $0.sessionSampleRate = 1 @@ -160,7 +156,6 @@ extension SentryAppLaunchProfilingTests { func testLaunchContinuousProfileV2TraceLifecycleNotStoppedOnInitialDisplayWithoutWaitingForFullDisplay() throws { // Arrange fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = nil fixture.options.configureProfiling = { $0.profileAppStarts = true $0.sessionSampleRate = 1 @@ -191,7 +186,6 @@ extension SentryAppLaunchProfilingTests { func testLaunchContinuousProfileV2ManualLifecycleNotStoppedOnInitialDisplayWithoutWaitingForFullDisplay() throws { // Arrange - fixture.options.profilesSampleRate = nil fixture.options.configureProfiling = { $0.profileAppStarts = true $0.sessionSampleRate = 1 diff --git a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift index cebbfe432e..7af348c79c 100644 --- a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift +++ b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift @@ -20,1166 +20,19 @@ final class SentryAppStartProfilingConfigurationChangeTests: XCTestCase { } } -// MARK: configuration changes between launches (no TTFD combinations, see iOS-only tests) -@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") -extension SentryAppStartProfilingConfigurationChangeTests { - func test_lastLaunch_traceBased_currentLaunch_continuousV1() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = nil - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_currentLaunch_continuousV2_traceLifecycle() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_currentLaunch_continuousV2_manualLifecycle() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_currentLaunch_continuousV2_traceLifecycle() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_currentLaunch_continuousV2_manualLifecycle() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_currentLaunch_traceBased() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_traceLifecycle_currentLaunch_continuousV1() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_manualLifecycle_currentLaunch_continuousV1() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_traceLifecycle_currentLaunch_traceBased() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_manualLifecycle_currentLaunch_traceBased() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } -} - -#if !os(macOS) -// MARK: configuring launch profiling with TTFD disabled, then launching with it enabled (iOS-only) -@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") -extension SentryAppStartProfilingConfigurationChangeTests { - // MARK: starting with trace-based no TTFD - func test_lastLaunch_traceBased_noTTFD_currentLaunch_continuousV1_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_noTTFD_currentLaunch_traceBased_withTTFD() throws { - - } - - // MARK: starting with continuous v1 no TTFD - func test_lastLaunch_continuousV1_noTTFD_currentLaunch_continuousV1_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_noTTFD_currentLaunch_traceBased_withTTFD() throws { - - } - - // MARK: starting with continuous v2 manual lifecycle no TTFD - func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV1_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_traceBased_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - // MARK: starting with continuous v2 trace lifecycle no TTFD - func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV1_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_traceBased_withTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: false - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } -} - -// MARK: configuring launch profiling with TTFD enabled, then launching with it disabled (iOS-only) -@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") -extension SentryAppStartProfilingConfigurationChangeTests { - // MARK: starting with trace-based with TTFD - func test_lastLaunch_traceBased_withTTFD_currentLaunch_continuousV1_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration (continuous V1) - fixture.options.profilesSampleRate = nil // Enables continuous profiling V1 - fixture.options.enableTimeToFullDisplayTracing = true - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started (trace-based from launch config) - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler not stopped initially (waiting for TTFD due to launch config) - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate TTFD using launch tracer (not a new transaction) - // Since the launch profiler is trace-based, we use the existing launch tracer - let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) - - // Use the launch tracer for TTFD simulation - let launchTracer = try XCTUnwrap(sentry_launchTracer) - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: launchTracer) - ttd.reportInitialDisplay() - ttd.reportFullyDisplayed() - fixture.displayLinkWrapper.call() - - // Assert profile stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .trace - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.tracesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = false - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler not stopped (waiting for TTFD) - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate TTFD - let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) - - // Use the launch tracer for TTFD simulation - let launchTracer = try XCTUnwrap(sentry_launchTracer) - - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: launchTracer) - ttd.reportInitialDisplay() - ttd.reportFullyDisplayed() - fixture.displayLinkWrapper.call() - - // Assert profile stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_withTTFD_currentLaunch_continuousV2_manualLifecycle_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.configureProfiling = { - $0.lifecycle = .manual - $0.sessionSampleRate = 1 - $0.profileAppStarts = true - } - fixture.options.enableTimeToFullDisplayTracing = false - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler not stopped (waiting for TTFD) - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate TTFD - let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) - let launchTracer = try XCTUnwrap(sentry_launchTracer) - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: launchTracer) - ttd.reportInitialDisplay() - ttd.reportFullyDisplayed() - fixture.displayLinkWrapper.call() - - // Assert profile stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_traceBased_withTTFD_currentLaunch_traceBased_noTTFD() throws { +#if !os(macOS) +// MARK: configuring launch profiling with TTFD disabled, then launching with it enabled (iOS-only) +@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") +extension SentryAppStartProfilingConfigurationChangeTests { + func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { // Arrange // persisted configuration simulating previous launch let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyTracesSampleRate: 1, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = false - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Assert profiler not stopped (waiting for TTFD) - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate TTFD - let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) - let launchTracer = try XCTUnwrap(sentry_launchTracer) - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: launchTracer) - ttd.reportInitialDisplay() - ttd.reportFullyDisplayed() - fixture.displayLinkWrapper.call() - - // Assert profile stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - // MARK: starting with continuous v1 with TTFD - func test_lastLaunch_continuousV1_withTTFD_currentLaunch_continuousV1_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = false - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler not stopped initially, continuous profiler doesn't wait for TTFD - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func test_lastLaunch_continuousV1_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false ] let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) @@ -1191,7 +44,7 @@ extension SentryAppStartProfilingConfigurationChangeTests { $0.profileAppStarts = true } fixture.options.tracesSampleRate = 1 - fixture.options.enableTimeToFullDisplayTracing = false + fixture.options.enableTimeToFullDisplayTracing = true // Act: simulate app launch _sentry_nondeduplicated_startLaunchProfile() @@ -1213,12 +66,15 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } - func test_lastLaunch_continuousV1_withTTFD_currentLaunch_continuousV2_manualLifecycle_noTTFD() throws { + func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { // Arrange // persisted configuration simulating previous launch let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false ] let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) @@ -1229,7 +85,7 @@ extension SentryAppStartProfilingConfigurationChangeTests { $0.sessionSampleRate = 1 $0.profileAppStarts = true } - fixture.options.enableTimeToFullDisplayTracing = false + fixture.options.enableTimeToFullDisplayTracing = true // Act: simulate app launch _sentry_nondeduplicated_startLaunchProfile() @@ -1251,32 +107,42 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } - func test_lastLaunch_continuousV1_withTTFD_currentLaunch_traceBased() throws { + // MARK: starting with continuous v2 trace lifecycle no TTFD + func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { // Arrange // persisted configuration simulating previous launch let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfiling: true, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false ] let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true // Act: simulate app launch _sentry_nondeduplicated_startLaunchProfile() // Assert correct type of profile started - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) // Act: simulate SDK start sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - // Act: simulate stopping the continuous profiler - SentrySDK.stopProfiler() + // Act: simulate elapsed time to finish UI profile chunk fixture.currentDateProvider.advance(by: 60) try fixture.timeoutTimerFactory.check() @@ -1285,23 +151,28 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } - // MARK: starting with continuous v2 manual lifecycle with TTFD - func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_continuousV1_noTTFD() throws { + func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { // Arrange // persisted configuration simulating previous launch let configDict: [String: Any] = [ kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false ] let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = false + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = true // Act: simulate app launch _sentry_nondeduplicated_startLaunchProfile() @@ -1311,10 +182,9 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) // Act: simulate elapsed time to finish UI profile chunk - SentrySDK.stopProfiler() fixture.currentDateProvider.advance(by: 60) try fixture.timeoutTimerFactory.check() @@ -1322,7 +192,12 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } +} +// MARK: configuring launch profiling with TTFD enabled, then launching with it disabled (iOS-only) +@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") +extension SentryAppStartProfilingConfigurationChangeTests { + // MARK: starting with continuous v2 manual lifecycle with TTFD func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { // Arrange // persisted configuration simulating previous launch @@ -1406,88 +281,7 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } - func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_traceBased_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate elapsed time to finish UI profile chunk - SentrySDK.stopProfiler() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - // MARK: starting with continuous v2 trace lifecycle with TTFD - func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_continuousV1_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.profilesSampleRate = nil - fixture.options.enableTimeToFullDisplayTracing = false - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate TTFD stoppage - let launchTracer = try XCTUnwrap(sentry_launchTracer) - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: launchTracer) - ttd.reportInitialDisplay() - ttd.reportFullyDisplayed() - fixture.displayLinkWrapper.call() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { // Arrange // persisted configuration simulating previous launch @@ -1584,50 +378,6 @@ extension SentryAppStartProfilingConfigurationChangeTests { XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } - - func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_traceBased_noTTFD() throws { - // Arrange - // persisted configuration simulating previous launch - let configDict: [String: Any] = [ - kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, - kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, - kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, - kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, - kSentryLaunchProfileConfigKeyWaitForFullDisplay: true - ] - let configURL = try XCTUnwrap(launchProfileConfigFileURL()) - try (configDict as NSDictionary).write(to: configURL) - - // new options simulating current launch configuration - fixture.options.tracesSampleRate = 1 - fixture.options.profilesSampleRate = 1 - - // Act: simulate app launch - _sentry_nondeduplicated_startLaunchProfile() - - // Assert correct type of profile started - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // Act: simulate SDK start - sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) - - // Act: simulate TTFD stoppage - let launchTracer = try XCTUnwrap(sentry_launchTracer) - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: launchTracer) - ttd.reportInitialDisplay() - ttd.reportFullyDisplayed() - fixture.displayLinkWrapper.call() - fixture.currentDateProvider.advance(by: 60) - try fixture.timeoutTimerFactory.check() - - // Assert profiler stopped - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } } #endif // !os(macOS) diff --git a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift index 58fa57ac54..48eb3b9981 100644 --- a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift +++ b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift @@ -4,16 +4,10 @@ import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) -/// Test how combinations of the following options interact to ultimately decide whether or not to start the profiler on the next app launch. -/// - `enableLaunchProfiling` (v1 of launch profiling; deprecated) -/// -/// Trace sample rates (tracing v2) affect both transaction-based profiling (deprecated) and continuous profiling v2 +/// Trace sample rates (tracing v2) affects continuous profiling v2 /// - `tracesSampleRate` /// -/// If profile sampling rate (deprecated) is set to nil, we're testing continuous profiling v1 if the v2 options aren't configured, or v2 if they are -/// - `profilesSampleRate` -/// -/// The following three options are for continuous profiling v2; all nil means we're testing continuous profiling v1, if any are defined, we're testing v2 +/// The following three options are for continuous profiling v2; if any are defined, we're testing v2 /// - `SentryProfileOptions.lifecycle` /// - `SentryProfileOptions.sessionSampleRate` /// - `SentryProfileOptions.profileAppStarts` @@ -29,7 +23,6 @@ final class SentryAppStartProfilingConfigurationTests: XCTestCase { } } -@available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") extension SentryAppStartProfilingConfigurationTests { func testValidCombinations() { for config in SentryAppStartProfilingConfigurationTests.validConfigurations { @@ -37,24 +30,6 @@ extension SentryAppStartProfilingConfigurationTests { } } - func testInvalidTransactionProfilingConfigurations() { - for config in SentryAppStartProfilingConfigurationTests.invalidTransactionProfilingConfigurations { - performTest(expectedOptions: config, shouldProfileLaunch: false) - } - } - - func testInvalidContinuousProfilingV1Configurations() { - for config in SentryAppStartProfilingConfigurationTests.invalidContinuousProfilingV1Configurations { - performTest(expectedOptions: config, shouldProfileLaunch: false) - } - } - - func testInvalidTransactionProfilingWithV2OptionsConfigurations() { - for config in SentryAppStartProfilingConfigurationTests.invalidTransactionProfilingWithV2OptionsConfigurations { - performTest(expectedOptions: config, shouldProfileLaunch: false) - } - } - func testInvalidContinuousProfilingV2Configurations() { for config in SentryAppStartProfilingConfigurationTests.invalidContinuousProfilingV2Configurations { performTest(expectedOptions: config, shouldProfileLaunch: false) @@ -63,22 +38,10 @@ extension SentryAppStartProfilingConfigurationTests { } private extension SentryAppStartProfilingConfigurationTests { - @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func performTest(expectedOptions: LaunchProfileOptions, shouldProfileLaunch: Bool) { let actualOptions = Options() - if let tracesSampleRate = expectedOptions.tracesSampleRate { - actualOptions.tracesSampleRate = NSNumber(value: tracesSampleRate) - } else { - actualOptions.tracesSampleRate = nil - } - - if let profilesSampleRate = expectedOptions.profilesSampleRate { - actualOptions.profilesSampleRate = NSNumber(value: profilesSampleRate) - } else { - actualOptions.profilesSampleRate = nil - } - + actualOptions.tracesSampleRate = expectedOptions.tracesSampleRate.map { NSNumber(value: $0) } if let continuousProfileV2Options = expectedOptions.continuousProfileV2Options { actualOptions.configureProfiling = { $0.lifecycle = continuousProfileV2Options.lifecycle @@ -103,122 +66,39 @@ private extension SentryAppStartProfilingConfigurationTests { // MARK: Configuration combination lists // MARK: - private extension SentryAppStartProfilingConfigurationTests { - static let invalidTransactionProfilingConfigurations = [ - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1) - ] - - static let invalidContinuousProfilingV1Configurations = [ - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil) - ] - - static let invalidTransactionProfilingWithV2OptionsConfigurations = [ - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)) - ] - static let invalidContinuousProfilingV2Configurations = [ - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), - - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)) + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), + + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), + + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 0, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 0, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: false)), + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)) ] static let validConfigurations = [ - // - // configurations with continuous profiling v2 options set that are not short circuited to either transaction profiling or continuous v1 - // - // continuous profiling v2 trace lifecycle configurations - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .trace, sessionSampleRate: 1, profileAppStarts: true)), // continuous profiling v2 manual lifecycle configurations - LaunchProfileOptions(tracesSampleRate: 0, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: 1, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), - LaunchProfileOptions(tracesSampleRate: nil, profilesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)) + LaunchProfileOptions(tracesSampleRate: 0, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: 1, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)), + LaunchProfileOptions(tracesSampleRate: nil, continuousProfileV2Options: .init(lifecycle: .manual, sessionSampleRate: 1, profileAppStarts: true)) ] } @@ -230,9 +110,6 @@ struct LaunchProfileOptions: Equatable { /// to test transaction based profiling and continuous v2 trace lifecycle let tracesSampleRate: Float? - /// nonnil to test transaction profiling, nil to test continuous v1 and v2 - let profilesSampleRate: Float? - struct ContinuousProfileV2Options: Equatable { let lifecycle: SentryProfileOptions.SentryProfileLifecycle let sessionSampleRate: Float @@ -249,7 +126,6 @@ extension LaunchProfileOptions: CustomStringConvertible { var description: String { return "LaunchProfileOptions(\n" + "\ttracesSampleRate: \(String(describing: tracesSampleRate)),\n" - + "\tprofilesSampleRate: \(String(describing: profilesSampleRate)),\n" + "\tcontinuousProfileV2Options: \(String(describing: continuousProfileV2Options))\n" + ")" } diff --git a/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift b/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift index b1c3e40ccb..3ccf776224 100644 --- a/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift +++ b/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift @@ -17,7 +17,6 @@ final class SentryContinuousProfilerTests: XCTestCase { override func setUp() { super.setUp() fixture = SentryProfileTestFixture() - fixture.options.profilesSampleRate = nil } override func tearDown() { @@ -68,16 +67,6 @@ final class SentryContinuousProfilerTests: XCTestCase { try performContinuousProfilingTest(expectedEnvironment: expectedEnvironment) } - func testStartingContinuousProfilerWithSampleRateOne() throws { - fixture.options.profilesSampleRate = 1 - try performContinuousProfilingTest() - } - - func testStartingContinuousProfilerWithZeroSampleRate() throws { - fixture.options.profilesSampleRate = 0 - try performContinuousProfilingTest() - } - #if !os(macOS) func testDoesNotStopFramesTracker_WhenAppHangsV2Enabled() throws { diff --git a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift index 720099cd18..11dc26d4a2 100644 --- a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift +++ b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift @@ -85,7 +85,6 @@ class SentryProfileTestFixture { hub.bindClient(client) SentrySDKInternal.setCurrentHub(hub) - options.profilesSampleRate = 1.0 options.tracesSampleRate = 1.0 dispatchFactory.vendedSourceHandler = { eventHandler in diff --git a/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift b/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift index e0a0af10e7..39cec65ed3 100644 --- a/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift +++ b/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift @@ -71,212 +71,36 @@ class SentryProfilingPublicAPITests: XCTestCase { } } -// MARK: transaction profiling -@available(*, deprecated, message: "Transaction profiling is deprecated") -extension SentryProfilingPublicAPITests { - func testSentryOptionsReportsProfilingCorrelatedToTraces_NonnilSampleRate() { - // Arrange - let options = Options() - options.profilesSampleRate = 1 - options.profilesSampler = nil - options.configureProfiling = { - $0.lifecycle = .trace - } - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertTrue(options.isProfilingCorrelatedToTraces()) - } - - func testSentryOptionsReportsProfilingCorrelatedToTraces_NonnilSampler() { - // Arrange - let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = { _ in 1 } - options.configureProfiling = { - $0.lifecycle = .trace - } - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertTrue(options.isProfilingCorrelatedToTraces()) - } -} - -// MARK: continuous profiling v1 -@available(*, deprecated, message: "Continuous profiling v1 is deprecated") -extension SentryProfilingPublicAPITests { - func testSentryOptionsReportsContinuousProfilingEnabled() { - // Arrange - let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = nil - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertTrue(options.isContinuousProfilingEnabled()) - } - - func testSentryOptionsReportsContinuousProfilingDisabledWithNonnilSampleRate() { - // Arrange - let options = Options() - options.profilesSampleRate = 1 - options.profilesSampler = nil - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertFalse(options.isContinuousProfilingEnabled()) - } - - func testSentryOptionsReportsContinuousProfilingDisabledWithNonnilSampler() { - // Arrange - let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = { _ in 1 } - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertFalse(options.isContinuousProfilingEnabled()) - } - - func testStartingContinuousProfilerV1WithSampleRateZero() throws { - givenSdkWithHub() - - fixture.options.profilesSampleRate = 0 - XCTAssertEqual(try XCTUnwrap(fixture.options.profilesSampleRate).doubleValue, 0) - - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - SentrySDK.startProfiler() - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func testStartingContinuousProfilerV1WithSampleRateNil() throws { - givenSdkWithHub() - - // nil is the default initial value for profilesSampleRate, so we don't have to explicitly set it on the fixture - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - SentrySDK.startProfiler() - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - // clean up - try stopProfiler() - } - - func testNotStartingContinuousProfilerV1WithSampleRateBlock() throws { - givenSdkWithHub() - - fixture.options.profilesSampler = { _ in 0 } - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - SentrySDK.startProfiler() - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func testNotStartingContinuousProfilerV1WithSampleRateNonZero() throws { - givenSdkWithHub() - - fixture.options.profilesSampleRate = 1 - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - SentrySDK.startProfiler() - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func testStartingAndStoppingContinuousProfilerV1() throws { - givenSdkWithHub() - SentrySDK.startProfiler() - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - - try stopProfiler() - - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func testStartingContinuousProfilerV1BeforeStartingSDK() { - SentrySDK.startProfiler() - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - - func testStartingContinuousProfilerV1AfterStoppingSDK() { - givenSdkWithHub() - SentrySDK.close() - SentrySDK.startProfiler() - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } -} - // MARK: continuous profiling v2 @available(*, deprecated, message: "This is only deprecated because profilesSampleRate is deprecated. Once that is removed this attribute can be removed.") extension SentryProfilingPublicAPITests { func testSentryOptionsReportsContinuousProfilingV2Enabled() { // Arrange let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = nil - options.configureProfiling = { _ in } - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertTrue(options.isContinuousProfilingV2Enabled()) - } - - func testSentryOptionsReportsContinuousProfilingV2Disabled_NonnilSampleRate() { - // Arrange - let options = Options() - options.profilesSampleRate = 1 - options.profilesSampler = nil options.configureProfiling = { _ in } // Act sentry_configureContinuousProfiling(options) // Assert - XCTAssertFalse(options.isContinuousProfilingV2Enabled()) - } - - func testSentryOptionsReportsContinuousProfilingV2Disabled_NonnilSampler() { - // Arrange - let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = { _ in 1 } - options.configureProfiling = { _ in } - - // Act - sentry_configureContinuousProfiling(options) - - // Assert - XCTAssertFalse(options.isContinuousProfilingV2Enabled()) + XCTAssertTrue(options.isContinuousProfilingEnabled()) } func testSentryOptionsReportsContinuousProfilingV2Disabled_NilConfiguration() { // Arrange let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = nil options.configureProfiling = nil // Act sentry_configureContinuousProfiling(options) // Assert - XCTAssertFalse(options.isContinuousProfilingV2Enabled()) + XCTAssertFalse(options.isContinuousProfilingEnabled()) } func testSentryOptionsReportsProfilingCorrelatedToTraces() { // Arrange let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = nil options.configureProfiling = { $0.lifecycle = .trace } @@ -291,8 +115,6 @@ extension SentryProfilingPublicAPITests { func testSentryOptionsReportsProfilingNotCorrelatedToTraces_ManualLifecycle() { // Arrange let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = nil options.configureProfiling = { $0.lifecycle = .manual // this is the default value, but made explicit here for clarity } @@ -307,8 +129,6 @@ extension SentryProfilingPublicAPITests { func testSentryOptionsReportsProfilingNotCorrelatedToTraces_NilConfiguration() { // Arrange let options = Options() - options.profilesSampleRate = nil - options.profilesSampler = nil options.configureProfiling = nil // Act @@ -374,18 +194,6 @@ extension SentryProfilingPublicAPITests { XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) } - func testStartingContinuousProfilerV2WithoutContinuousProfilingEnabledDoesNotStartProfiler() { - // Arrange - fixture.options.profilesSampleRate = 1 - givenSdkWithHub() - - // Act - SentrySDK.startProfiler() - - // Assert - XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) - } - func testStartingContinuousProfilerV2WithTraceLifeCycleDoesNotStartProfiler() { // Arrange fixture.options.configureProfiling = { diff --git a/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m b/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m index 4ebc8180af..1a93ecd770 100644 --- a/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m +++ b/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m @@ -15,21 +15,12 @@ - (void)testIsContinuousProfilingEnabled { SentryOptions *options = [[SentryOptions alloc] init]; options.dsn = @"https://username:password@app.getsentry.com/12345"; + options.profiling = [[SentryProfileOptions alloc] init]; SentryClient *client = [[SentryClient alloc] initWithOptions:options]; XCTAssertEqual( [client.options isContinuousProfilingEnabled], sentry_isContinuousProfilingEnabled(client)); } -- (void)testIsContinuousProfilingV2Enabled -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.dsn = @"https://username:password@app.getsentry.com/12345"; - options.profiling = [[SentryProfileOptions alloc] init]; - SentryClient *client = [[SentryClient alloc] initWithOptions:options]; - XCTAssertEqual([client.options isContinuousProfilingV2Enabled], - sentry_isContinuousProfilingV2Enabled(client)); -} - - (void)testIsProfilingCorrelatedToTraces { SentryOptions *options = [[SentryOptions alloc] init]; diff --git a/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift b/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift deleted file mode 100644 index 66a02b8411..0000000000 --- a/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift +++ /dev/null @@ -1,686 +0,0 @@ -import _SentryPrivate -@_spi(Private) @testable import Sentry -@_spi(Private) import SentryTestUtils -import XCTest - -#if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) -@available(*, deprecated, message: "This is only marked deprecated because SentryProfileTestFixture is marked as deprecated.") -class SentryTraceProfilerTests: XCTestCase { - - private var fixture: SentryProfileTestFixture! - - override class func setUp() { - super.setUp() - SentrySDKLogSupport.configure(true, diagnosticLevel: .debug) - } - - override func setUp() { - super.setUp() - fixture = SentryProfileTestFixture() - } - - override func tearDown() { - super.tearDown() - clearTestState() - } - - func testSentryProfilerTimoutInterval() { - XCTAssertEqual(30, kSentryProfilerTimeoutInterval) - } - - func testMetricProfiler() throws { - let span = try fixture.newTransaction() - try addMockSamples() - try fixture.gatherMockedTraceProfileMetrics() - self.fixture.currentDateProvider.advanceBy(nanoseconds: 1.toNanoSeconds()) - span.finish() - try self.assertMetricsPayload() - } - - func testCaptureTransactionWithProfile_StopsProfileOnCallingThread() throws { - let span = try fixture.newTransaction() - try addMockSamples() - try fixture.gatherMockedTraceProfileMetrics() - - self.fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false - let currentProfiler = try XCTUnwrap(SentryTraceProfiler.getCurrentProfiler()) - - XCTAssertTrue(currentProfiler.isRunning()) - - span.finish() - - XCTAssertFalse(currentProfiler.isRunning(), "Profiler must be stopped on the calling thread.") - XCTAssertEqual(SentryProfilerTruncationReason.normal, currentProfiler.truncationReason) - - self.fixture.currentDateProvider.advanceBy(nanoseconds: 1.toNanoSeconds()) - self.fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = true - self.fixture.dispatchQueueWrapper.invokeLastDispatchAsync() - - try self.assertMetricsPayload() - try self.assertValidTraceProfileData() - } - - func testTransactionWithMutatedTracerID() throws { - let span = try fixture.newTransaction() - try addMockSamples() - self.fixture.currentDateProvider.advanceBy(nanoseconds: 1.toNanoSeconds()) - span.traceId = SentryId() - span.finish() - try self.assertValidTraceProfileData() - } - - func testConcurrentProfilingTransactions() throws { - let numberOfTransactions = 10 - var spans = [Span]() - - func createConcurrentSpansWithMetrics() throws { - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - - for i in 0 ..< numberOfTransactions { - print("creating new concurrent transaction for test") - let span = try fixture.newTransaction() - - // because energy readings are computed as the difference between sequential cumulative readings, we must increment the mock value by the expected result each iteration - fixture.systemWrapper.overrides.cpuEnergyUsage = NSNumber(value: try XCTUnwrap(fixture.systemWrapper.overrides.cpuEnergyUsage).intValue + fixture.mockMetrics.cpuEnergyUsage.intValue) - - XCTAssertTrue(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(i + 1)) - spans.append(span) - fixture.currentDateProvider.advanceBy(nanoseconds: 100) - } - - let threadMetadata = SentryProfileTestFixture.ThreadMetadata(id: 1, priority: 2, name: "test-thread") - try addMockSamples(threadMetadata: threadMetadata) - - for (i, span) in spans.enumerated() { - try fixture.gatherMockedTraceProfileMetrics() - - XCTAssertTrue(SentryTraceProfiler.isCurrentlyProfiling()) - span.finish() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(numberOfTransactions - (i + 1))) - - try self.assertValidTraceProfileData(expectedThreadMetadata: [threadMetadata]) - - // this is a complicated number to come up with, see the explanation for each part... - let expectedUsageReadings = fixture.mockMetrics.readingsPerBatch * (i + 1) // since we fire mock metrics readings for each concurrent span, - // we need to accumulate across the number of spans each iteration - + numberOfTransactions // and then, add the number of spans that were created to account for the start reading for each span - + 1 // and the end reading for this span - try self.assertMetricsPayload(oneLessEnergyReading: i == 0, expectedMetricsReadingsPerBatchOverride: expectedUsageReadings) - } - - XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - } - - try createConcurrentSpansWithMetrics() - - // do everything again to make sure that stopping and starting the profiler over again works - spans.removeAll() -#if !os(macOS) - fixture.resetProfileGPUExpectations() -#endif // !os(macOS) - - try createConcurrentSpansWithMetrics() - } - - /// Test a situation where a long-running span starts the profiler, which winds up timing out, and then another span starts that begins a new profile, then finishes, and then the long-running span finishes; both profiles should be separately captured in envelopes. - /// ``` - /// time-> - /// transaction A |---------------------------------------------------| - /// profiler A |---------------------------x <- timeout - /// transaction B |-------| - /// profiler B |-------| <- normal finish - /// ``` - func testConcurrentSpansWithTimeout() throws { - // start span A and mock profile data for it - let spanA = try fixture.newTransaction() - fixture.currentDateProvider.advanceBy(nanoseconds: 1.toNanoSeconds()) - let expectedAddressesA: [NSNumber] = [0x1, 0x2, 0x3] - let expectedThreadMetadataA = SentryProfileTestFixture.ThreadMetadata(id: 1, priority: 2, name: "test-thread1") - try addMockSamples(threadMetadata: expectedThreadMetadataA, addresses: expectedAddressesA) - - // time out profiler for span A - fixture.currentDateProvider.advanceBy(nanoseconds: 30.toNanoSeconds()) - try fixture.timeoutTimerFactory.fire() - - fixture.currentDateProvider.advanceBy(nanoseconds: 0.5.toNanoSeconds()) - - // start span B and mock profile data for it - let spanB = try fixture.newTransaction() - fixture.currentDateProvider.advanceBy(nanoseconds: 0.5.toNanoSeconds()) - let expectedAddressesB: [NSNumber] = [0x7, 0x8, 0x9] - let expectedThreadMetadataB = SentryProfileTestFixture.ThreadMetadata(id: 4, priority: 5, name: "test-thread2") - try addMockSamples(threadMetadata: expectedThreadMetadataB, addresses: expectedAddressesB) - - // finish span B and check profile data - spanB.finish() - try self.assertValidTraceProfileData(expectedAddresses: expectedAddressesB, expectedThreadMetadata: [expectedThreadMetadataB]) - - // finish span A and check profile data - spanA.finish() - try self.assertValidTraceProfileData(expectedAddresses: expectedAddressesA, expectedThreadMetadata: [expectedThreadMetadataA]) - } - - func testProfileTimeoutTimer() throws { - try performTraceProfilingTest(shouldTimeOut: true) - } - - func testStartTransaction_ProfilingDataIsValid() throws { - try performTraceProfilingTest() - } - - func testProfilingDataContainsEnvironmentSetFromOptions() throws { - let expectedEnvironment = "test-environment" - fixture.options.environment = expectedEnvironment - try performTraceProfilingTest(transactionEnvironment: expectedEnvironment) - } - -#if !os(macOS) - func testProfileWithTransactionContainingStartupSpansForColdStart() throws { - try performTraceProfilingTest(uikitParameters: UIKitParameters(launchType: .cold, prewarmed: false)) - } - - func testProfileWithTransactionContainingStartupSpansForWarmStart() throws { - try performTraceProfilingTest(uikitParameters: UIKitParameters(launchType: .warm, prewarmed: false)) - } - - func testProfileWithTransactionContainingStartupSpansForPrewarmedStart() throws { - try performTraceProfilingTest(uikitParameters: UIKitParameters(launchType: .warm, prewarmed: true)) - } -#endif // !os(macOS) - - func testProfilingDataContainsEnvironmentSetFromConfigureScope() throws { - let expectedEnvironment = "test-environment" - fixture.hub.configureScope { scope in - scope.setEnvironment(expectedEnvironment) - } - try performTraceProfilingTest(transactionEnvironment: expectedEnvironment) - } - - func testStartTransaction_NotSamplingProfileUsingEnableProfiling() throws { - try assertProfilesSampler(expectedDecision: .no) { options in - options.enableProfiling_DEPRECATED_TEST_ONLY = false - } - } - - func testStartTransaction_SamplingProfileUsingEnableProfiling() throws { - try assertProfilesSampler(expectedDecision: .yes) { options in - options.enableProfiling_DEPRECATED_TEST_ONLY = true - } - } - - func testStartTransaction_NotSamplingProfileUsingSampleRate() throws { - try assertProfilesSampler(expectedDecision: .no) { options in - options.profilesSampleRate = 0.49 - } - } - - func testStartTransaction_SamplingProfileUsingSampleRate() throws { - try assertProfilesSampler(expectedDecision: .yes) { options in - options.profilesSampleRate = 0.5 - } - } - - func testStartTransaction_SamplingProfileUsingProfilesSampler() throws { - try assertProfilesSampler(expectedDecision: .yes) { options in - options.profilesSampler = { _ in return 0.51 } - } - } - - func testStartTransaction_WhenProfilesSampleRateAndProfilesSamplerNil() throws { - try assertProfilesSampler(expectedDecision: .no) { options in - options.profilesSampleRate = 0 - options.profilesSampler = { _ in return nil } - } - } - - func testStartTransaction_WhenProfilesSamplerOutOfRange_TooBig() throws { - try assertProfilesSampler(expectedDecision: .no) { options in - options.profilesSampler = { _ in return 1.01 } - } - } - - func testStartTransaction_WhenProfilesSamplersOutOfRange_TooSmall() throws { - try assertProfilesSampler(expectedDecision: .no) { options in - options.profilesSampler = { _ in return -0.01 } - } - } - - /// based on ``SentryTracerTests.testFinish_WithoutHub_DoesntCaptureTransaction`` - func testProfilerCleanedUpAfterTransactionDiscarded_NoHub() throws { - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - func performTransaction() { - let sut = SentryTracer(transactionContext: TransactionContext(name: fixture.transactionName, operation: fixture.transactionOperation), hub: nil) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - sut.finish() - } - performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - - /// based on ``SentryTracerTests.testFinish_WaitForAllChildren_ExceedsMaxDuration_NoTransactionCaptured`` - func testProfilerCleanedUpAfterTransactionDiscarded_ExceedsMaxDuration() throws { - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - func performTransaction() throws { - let sut = try fixture.newTransaction(automaticTransaction: true) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(1)) - fixture.currentDateProvider.advance(by: 500) - sut.finish() - } - try performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - - func testProfilerCleanedUpAfterInFlightTransactionDeallocated() throws { - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - func performTransaction() throws { - let sut = try fixture.newTransaction(automaticTransaction: true) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(1)) - XCTAssertFalse(sut.isFinished) - } - try performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - - /// based on ``SentryTracerTests.testFinish_IdleTimeout_ExceedsMaxDuration_NoTransactionCaptured`` - func testProfilerCleanedUpAfterTransactionDiscarded_IdleTimeout_ExceedsMaxDuration() throws { - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - func performTransaction() throws { - let sut = try fixture.newTransaction(automaticTransaction: true, idleTimeout: 1) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(1)) - fixture.currentDateProvider.advance(by: 500) - sut.finish() - } - try performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - - /// based on ``SentryTracerTests.testIdleTimeout_NoChildren_TransactionNotCaptured`` - func testProfilerCleanedUpAfterTransactionDiscarded_IdleTimeout_NoChildren() throws { - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - func performTransaction() throws { - let span = try fixture.newTransaction(automaticTransaction: true, idleTimeout: 1) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(1)) - fixture.currentDateProvider.advance(by: 500) - fixture.dispatchQueueWrapper.invokeLastDispatchAfter() - XCTAssert(span.isFinished) - } - try performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - - /// based on ``SentryTracerTests.testIdleTransaction_CreatingDispatchBlockFails_NoTransactionCaptured`` - func testProfilerCleanedUpAfterTransactionDiscarded_IdleTransaction_CreatingDispatchBlockFails() throws { - fixture.dispatchQueueWrapper.createDispatchBlockReturnsNULL = true - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - func performTransaction() throws { - let span = try fixture.newTransaction(automaticTransaction: true, idleTimeout: 1) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(1)) - fixture.currentDateProvider.advance(by: 500) - span.finish() - } - try performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - -#if !os(macOS) - /// based on ``SentryTracerTests.testFinish_WaitForAllChildren_StartTimeModified_NoTransactionCaptured`` - func testProfilerCleanedUpAfterTransactionDiscarded_WaitForAllChildren_StartTimeModified() throws { - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) - fixture.currentDateProvider.advance(by: 1) - func performTransaction() throws { - let sut = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(1)) - fixture.currentDateProvider.advance(by: 499) - sut.finish() - } - try performTransaction() - XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) - XCTAssertEqual(self.fixture.client?.captureEventWithScopeInvocations.count, 0) - } - - // test that receiving a backgrounding notification stops the profiler - func testTraceProfilerStopsOnBackgrounding() throws { - let span = try fixture.newTransaction() - XCTAssert(try XCTUnwrap(SentryTraceProfiler.getCurrentProfiler()).isRunning()) - fixture.currentDateProvider.advance(by: 1) - fixture.notificationCenter.post(Notification(name: UIApplication.willResignActiveNotification, object: nil)) - XCTAssertFalse(try XCTUnwrap(SentryTraceProfiler.getCurrentProfiler()).isRunning()) - span.finish() // this isn't germane to the test, but we need the span to be retained throughout the test, and this satisfies the unused variable check - } -#endif // !os(macOS) -} - -@available(*, deprecated, message: "This is only marked deprecated because SentryProfileTestFixture is marked as deprecated.") -private extension SentryTraceProfilerTests { - func getLatestProfileData() throws -> Data { - let envelope = try XCTUnwrap(self.fixture.client?.captureEventWithScopeInvocations.last) - - XCTAssertEqual(1, envelope.additionalEnvelopeItems.count) - let profileItem = try XCTUnwrap(envelope.additionalEnvelopeItems.first) - - XCTAssertEqual("profile", profileItem.header.type) - return try XCTUnwrap(profileItem.data) - } - - func getLatestTransaction() throws -> Transaction { - let envelope = try XCTUnwrap(self.fixture.client?.captureEventWithScopeInvocations.last) - return try XCTUnwrap(envelope.event as? Transaction) - } - - func addMockSamples(threadMetadata: SentryProfileTestFixture.ThreadMetadata = SentryProfileTestFixture.ThreadMetadata(id: 1, priority: 2, name: "main"), addresses: [NSNumber] = [0x3, 0x4, 0x5]) throws { - let state = try XCTUnwrap(SentryTraceProfiler.getCurrentProfiler()).state - fixture.currentDateProvider.advanceBy(nanoseconds: 1) - SentryProfilerMocksSwiftCompatible.appendMockBacktrace(to: state, threadID: threadMetadata.id, threadPriority: threadMetadata.priority, threadName: threadMetadata.name, addresses: addresses) - fixture.currentDateProvider.advanceBy(nanoseconds: 1) - SentryProfilerMocksSwiftCompatible.appendMockBacktrace(to: state, threadID: threadMetadata.id, threadPriority: threadMetadata.priority, threadName: threadMetadata.name, addresses: addresses) - fixture.currentDateProvider.advanceBy(nanoseconds: 1) - SentryProfilerMocksSwiftCompatible.appendMockBacktrace(to: state, threadID: threadMetadata.id, threadPriority: threadMetadata.priority, threadName: threadMetadata.name, addresses: addresses) - } - - struct UIKitParameters { -#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - var launchType: SentryAppStartType - var prewarmed: Bool -#endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - } - - func performTraceProfilingTest(transactionEnvironment: String = kSentryDefaultEnvironment, shouldTimeOut: Bool = false, uikitParameters: UIKitParameters? = nil) throws { - var testingAppLaunchSpans = false - -#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - if let uikitParameters = uikitParameters { - testingAppLaunchSpans = true - let appStartMeasurement = fixture.getAppStartMeasurement(type: uikitParameters.launchType, preWarmed: uikitParameters.prewarmed) - SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) - } -#endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - - let span = try fixture.newTransaction(testingAppLaunchSpans: testingAppLaunchSpans) - - try addMockSamples() - fixture.currentDateProvider.advance(by: 31) - if shouldTimeOut { - try self.fixture.timeoutTimerFactory.fire() - } - - let exp = expectation(description: "finished span") - DispatchQueue.main.async { - span.finish() - exp.fulfill() - } - - waitForExpectations(timeout: 1) - - try self.assertValidTraceProfileData(transactionEnvironment: transactionEnvironment, shouldTimeout: shouldTimeOut, appStartProfile: testingAppLaunchSpans) - } - - func assertMetricsPayload(oneLessEnergyReading: Bool = true, expectedMetricsReadingsPerBatchOverride: Int? = nil) throws { - let profileData = try self.getLatestProfileData() - let transaction = try getLatestTransaction() - let profile = try XCTUnwrap(JSONSerialization.jsonObject(with: profileData) as? [String: Any]) - let measurements = try XCTUnwrap(profile["measurements"] as? [String: Any]) - let expectedUsageReadings = expectedMetricsReadingsPerBatchOverride ?? fixture.mockMetrics.readingsPerBatch + 2 // including one sample at the start and the end - - try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUUsage, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockMetrics.cpuUsage, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitPercentage) - - try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyMemoryFootprint, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockMetrics.memoryFootprint, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitBytes) - - #if arch(arm) || arch(arm64) - // we wind up with one less energy reading for the first concurrent span's metric sample. since we must use the difference between readings to get actual values, the first one is only the baseline reading. - let expectedEnergyReadings = oneLessEnergyReading ? expectedUsageReadings - 1 : expectedUsageReadings - try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUEnergyUsage, numberOfReadings: expectedEnergyReadings, expectedValue: fixture.mockMetrics.cpuEnergyUsage, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitNanoJoules) - #endif // arch(arm) || arch(arm64) - -#if !os(macOS) - try assertMetricEntries(measurements: measurements, key: kSentryProfilerSerializationKeySlowFrameRenders, expectedEntries: fixture.expectedTraceProfileSlowFrames, transaction: transaction) - try assertMetricEntries(measurements: measurements, key: kSentryProfilerSerializationKeyFrozenFrameRenders, expectedEntries: fixture.expectedTraceProfileFrozenFrames, transaction: transaction) - try assertMetricEntries(measurements: measurements, key: kSentryProfilerSerializationKeyFrameRates, expectedEntries: fixture.expectedTraceProfileFrameRateChanges, transaction: transaction) -#endif // !os(macOS) - } - - func sortedByTimestamps(_ entries: [[String: Any]]) throws -> [[String: Any]] { - try entries.sorted { a, b in - let aValue = try XCTUnwrap(a["elapsed_since_start_ns"] as? String) - let aIntValue = try XCTUnwrap(UInt64(aValue)) - let bValue = try XCTUnwrap(b["elapsed_since_start_ns"] as? String) - let bIntValue = try XCTUnwrap(UInt64(bValue)) - return aIntValue < bIntValue - } - } - - func printTimestamps(entries: [[String: Any]]) -> [NSString] { - entries.compactMap({ $0["elapsed_since_start_ns"] as? NSString }) - } - - func assertMetricEntries(measurements: [String: Any], key: String, expectedEntries: [[String: Any]], transaction: Transaction) throws { - let metricContainer = try XCTUnwrap(measurements[key] as? [String: Any]) - let actualEntries = try XCTUnwrap(metricContainer["values"] as? [[String: Any]]) - let sortedActualEntries = try sortedByTimestamps(actualEntries) - let sortedExpectedEntries = try sortedByTimestamps(expectedEntries) - - guard actualEntries.count == expectedEntries.count else { - XCTFail("Wrong number of values under \(key). expected: \(printTimestamps(entries: sortedExpectedEntries)); actual: \(printTimestamps(entries: sortedActualEntries)); transaction start time: \(transaction.startSystemTime)") - return - } - - for i in 0..(measurements: [String: Any], key: String, numberOfReadings: Int, expectedValue: T? = nil, transaction: Transaction, expectedUnits: String) throws { - let metricContainer = try XCTUnwrap(measurements[key] as? [String: Any]) - let values = try XCTUnwrap(metricContainer["values"] as? [[String: Any]]) - XCTAssertEqual(values.count, numberOfReadings, "Wrong number of values under \(key)") - - if let expectedValue = expectedValue { - let actualValue = try XCTUnwrap(values.element(at: 1)?["value"] as? T) - XCTAssertEqual(actualValue, expectedValue, "Wrong value for \(key)") - - let timestamp = try XCTUnwrap(values.first?["elapsed_since_start_ns"] as? NSString) - try assertTimestampOccursWithinTransaction(timestamp: timestamp, transaction: transaction) - - let actualUnits = try XCTUnwrap(metricContainer["unit"] as? String) - XCTAssertEqual(actualUnits, expectedUnits) - } - } - - /// Assert that the relative timestamp actually falls within the transaction's duration, so it should be between 0 and the transaction duration. The string that holds an elapsed time actually holds an unsigned long long value (due to us using unsigned 64 bit integers, which are not officially supported by JSON), but there is no Cocoa API to get that back out of a string. So, we'll just convert them to signed 64 bit integers, for which there is an API. This likely won't cause a problem because signed 64 bit ints still support large positive values that are likely to be larger than any amount of nanoseconds of a machine's uptime. We can revisit if this actually fails in practice. - func assertTimestampOccursWithinTransaction(timestamp: NSString, transaction: Transaction) throws { - let transactionDuration = Int64(getDurationNs(transaction.startSystemTime, transaction.endSystemTime)) - let timestampNumericValue = timestamp.longLongValue - XCTAssertGreaterThanOrEqual(timestampNumericValue, 0) - XCTAssertLessThanOrEqual(timestampNumericValue, transactionDuration) - } - - enum SentryProfilerSwiftTestError: Error { - case notEnoughAppStartSpans - } - - func assertValidTraceProfileData(transactionEnvironment: String = kSentryDefaultEnvironment, shouldTimeout: Bool = false, expectedAddresses: [NSNumber]? = nil, expectedThreadMetadata: [SentryProfileTestFixture.ThreadMetadata]? = nil, appStartProfile: Bool = false) throws { - let data = try getLatestProfileData() - let profile = try XCTUnwrap(try JSONSerialization.jsonObject(with: data) as? [String: Any]) - - XCTAssertEqual(try XCTUnwrap(profile["version"] as? String), "1") - - let device = try XCTUnwrap(profile["device"] as? [String: Any?]) - XCTAssertNotNil(device) - XCTAssertEqual("Apple", try XCTUnwrap(device["manufacturer"] as? String)) - XCTAssertEqual(try XCTUnwrap(device["locale"] as? String), (NSLocale.current as NSLocale).localeIdentifier) - XCTAssertFalse(try XCTUnwrap(device["model"] as? String).isEmpty) -#if targetEnvironment(simulator) - XCTAssertTrue(try XCTUnwrap(device["is_emulator"] as? Bool)) -#else - XCTAssertFalse(try XCTUnwrap(device["is_emulator"] as? Bool)) -#endif // targetEnvironment(simulator) - - let os = try XCTUnwrap(profile["os"] as? [String: Any?]) - XCTAssertNotNil(os) - XCTAssertNotNil(try XCTUnwrap(os["name"] as? String)) - XCTAssertFalse(try XCTUnwrap(os["version"] as? String).isEmpty) - XCTAssertFalse(try XCTUnwrap(os["build_number"] as? String).isEmpty) - - let platform = try XCTUnwrap(profile["platform"] as? String) - XCTAssertEqual("cocoa", platform) - - XCTAssertEqual(transactionEnvironment, try XCTUnwrap(profile["environment"] as? String)) - - let bundleID = Bundle.main.object(forInfoDictionaryKey: kCFBundleIdentifierKey as String) ?? "(null)" - let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "(null)" - let build = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) ?? "(null)" - let expectedReleaseString = "\(bundleID)@\(version)+\(build)" - let actualReleaseString = try XCTUnwrap(profile["release"] as? String) - XCTAssertEqual(actualReleaseString, expectedReleaseString) - - XCTAssertNotEqual(SentryId.empty, SentryId(uuidString: try XCTUnwrap(profile["profile_id"] as? String))) - - let debugMeta = try XCTUnwrap(profile["debug_meta"] as? [String: Any]) - let images = try XCTUnwrap(debugMeta["images"] as? [[String: Any]]) - XCTAssertFalse(images.isEmpty) - let firstImage = try XCTUnwrap(images.first) - XCTAssertFalse(try XCTUnwrap(firstImage["code_file"] as? String).isEmpty) - XCTAssertFalse(try XCTUnwrap(firstImage["debug_id"] as? String).isEmpty) - XCTAssertFalse(try XCTUnwrap(firstImage["image_addr"] as? String).isEmpty) - XCTAssertGreaterThan(try XCTUnwrap(firstImage["image_size"] as? Int), 0) - XCTAssertEqual(try XCTUnwrap(firstImage["type"] as? String), "macho") - - let sampledProfile = try XCTUnwrap(profile["profile"] as? [String: Any]) - let threadMetadata = try XCTUnwrap(sampledProfile["thread_metadata"] as? [String: [String: Any]]) - XCTAssertFalse(threadMetadata.isEmpty) - if let expectedThreadMetadata = expectedThreadMetadata { - try expectedThreadMetadata.forEach { - let actualThreadMetadata = try XCTUnwrap(threadMetadata["\($0.id)"]) - let actualThreadPriority = try XCTUnwrap(actualThreadMetadata["priority"] as? Int32) - XCTAssertEqual(actualThreadPriority, $0.priority) - let actualThreadName = try XCTUnwrap(actualThreadMetadata["name"] as? String) - XCTAssertEqual(actualThreadName, $0.name) - } - } else { - XCTAssertFalse(try threadMetadata.values.compactMap { $0["priority"] }.filter { try XCTUnwrap($0 as? Int) > 0 }.isEmpty) - XCTAssertFalse(try threadMetadata.values.compactMap { $0["name"] }.filter { try XCTUnwrap($0 as? String) == "main" }.isEmpty) - } - - let samples = try XCTUnwrap(sampledProfile["samples"] as? [[String: Any]]) - XCTAssertFalse(samples.isEmpty) - - let frames = try XCTUnwrap(sampledProfile["frames"] as? [[String: Any]]) - XCTAssertFalse(frames.isEmpty) - XCTAssertFalse(try XCTUnwrap(frames.first?["instruction_addr"] as? String).isEmpty) - XCTAssertFalse(try XCTUnwrap(frames.first?["function"] as? String).isEmpty) - - let stacks = try XCTUnwrap(sampledProfile["stacks"] as? [[Int]]) - var foundAtLeastOneNonEmptySample = false - XCTAssertFalse(stacks.isEmpty) - for stack in stacks { - guard !stack.isEmpty else { continue } - foundAtLeastOneNonEmptySample = true - for frameIdx in stack { - XCTAssertNotNil(frames[frameIdx]) - } - } - XCTAssert(foundAtLeastOneNonEmptySample) - - let latestTransaction = try getLatestTransaction() - let linkedTransactionInfo = try XCTUnwrap(profile["transaction"] as? [String: Any]) - - let profileTimestampString = try XCTUnwrap(profile["timestamp"] as? String) - - let latestTransactionTimestamp = try XCTUnwrap(latestTransaction.startTimestamp) - var startTimestampString = sentry_toIso8601String(latestTransactionTimestamp) - #if !os(macOS) - if appStartProfile { - let runtimeInitTimestamp = try XCTUnwrap(SentrySDKInternal.getAppStartMeasurement()?.runtimeInitTimestamp) - startTimestampString = sentry_toIso8601String(runtimeInitTimestamp) - } - #endif // !os(macOS) - - XCTAssertEqual(profileTimestampString, startTimestampString) - - XCTAssertEqual(fixture.transactionName, latestTransaction.transaction) - XCTAssertEqual(fixture.transactionName, try XCTUnwrap(linkedTransactionInfo["name"] as? String)) - - let linkedTransactionId = SentryId(uuidString: try XCTUnwrap(linkedTransactionInfo["id"] as? String)) - XCTAssertEqual(latestTransaction.eventId, linkedTransactionId) - XCTAssertNotEqual(SentryId.empty, linkedTransactionId) - - let linkedTransactionTraceId = SentryId(uuidString: try XCTUnwrap(linkedTransactionInfo["trace_id"] as? String)) - XCTAssertEqual(latestTransaction.trace.traceId, linkedTransactionTraceId) - XCTAssertNotEqual(SentryId.empty, linkedTransactionTraceId) - - let activeThreadId = try XCTUnwrap(linkedTransactionInfo["active_thread_id"] as? NSNumber) - XCTAssertEqual(activeThreadId, latestTransaction.trace.transactionContext.sentry_threadInfo().threadId) - - for sample in samples { - let timestamp = try XCTUnwrap(sample["elapsed_since_start_ns"] as? NSString) - try assertTimestampOccursWithinTransaction(timestamp: timestamp, transaction: latestTransaction) - XCTAssertNotNil(sample["thread_id"]) - let stackIDEntry = try XCTUnwrap(sample["stack_id"]) - let stackID = try XCTUnwrap(stackIDEntry as? Int) - XCTAssertNotNil(stacks[stackID]) - } - - if shouldTimeout { - XCTAssertEqual(try XCTUnwrap(profile["truncation_reason"] as? String), sentry_profilerTruncationReasonName(SentryProfilerTruncationReason.timeout)) - } - } - - func assertProfilesSampler(expectedDecision: SentrySampleDecision, options: (Options) -> Void) throws { - let fixtureOptions = fixture.options - fixtureOptions.tracesSampleRate = 1.0 - fixtureOptions.profilesSampleRate = 0 - fixtureOptions.profilesSampler = { _ in - switch expectedDecision { - case .undecided, .no: - return NSNumber(value: 0) - case .yes: - return NSNumber(value: 1) - @unknown default: - XCTFail("Unexpected value for sample decision") - return NSNumber(value: 0) - } - } - options(fixtureOptions) - - let span = try fixture.newTransaction() - if expectedDecision == .yes { - try addMockSamples() - } - fixture.currentDateProvider.advance(by: 5) - span.finish() - - let client = try XCTUnwrap(self.fixture.client) - - switch expectedDecision { - case .undecided, .no: - let event = try XCTUnwrap(client.captureEventWithScopeInvocations.first) - XCTAssertEqual(0, event.additionalEnvelopeItems.count) - case .yes: - let event = try XCTUnwrap(client.captureEventWithScopeInvocations.first) - XCTAssertEqual(1, event.additionalEnvelopeItems.count) - @unknown default: - XCTFail("Unexpected value for sample decision") - } - } -} -#endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) diff --git a/Tests/SentryTests/SentryOptionsTest.m b/Tests/SentryTests/SentryOptionsTest.m index 7ce07be3fa..870d70696c 100644 --- a/Tests/SentryTests/SentryOptionsTest.m +++ b/Tests/SentryTests/SentryOptionsTest.m @@ -774,16 +774,6 @@ - (void)assertDefaultValues:(SentryOptions *)options XCTAssertFalse(options.enableTimeToFullDisplayTracing); -#if SENTRY_TARGET_PROFILING_SUPPORTED -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - XCTAssertEqual(NO, options.enableProfiling); - XCTAssertNil(options.profilesSampleRate); - XCTAssertNil(options.profilesSampler); -# pragma clang diagnostic pop - XCTAssertTrue([options isContinuousProfilingEnabled]); -#endif // SENTRY_TARGET_PROFILING_SUPPORTED - XCTAssertTrue([options.spotlightUrl isEqualToString:@"http://localhost:8969/stream"]); } @@ -1113,207 +1103,6 @@ - (void)testIsTracingEnabled_TracesSamplerSet_IsEnabled XCTAssertTrue(options.isTracingEnabled); } -#if SENTRY_TARGET_PROFILING_SUPPORTED -- (void)testEnableProfiling -{ - [self testBooleanField:@"enableProfiling" defaultValue:NO]; -} - -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (void)testProfilesSampleRate -{ - SentryOptions *options = [self getValidOptions:@{ @"profilesSampleRate" : @0.1 }]; - XCTAssertEqual(options.profilesSampleRate.doubleValue, 0.1); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testDefaultProfilesSampleRate -{ - SentryOptions *options = [self getValidOptions:@{}]; - XCTAssertNil(options.profilesSampleRate); - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertFalse(options.isProfilingEnabled); - - XCTAssertTrue([options isContinuousProfilingEnabled]); -} - -- (void)testProfilesSampleRate_SetToNil -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.profilesSampleRate = nil; - XCTAssertNil(options.profilesSampleRate); - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertFalse(options.isProfilingEnabled); - - XCTAssert([options isContinuousProfilingEnabled]); -} - -- (void)testProfilesSampleRateLowerBound -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.profilesSampleRate = @0.5; - - NSNumber *lowerBound = @0; - options.profilesSampleRate = lowerBound; - XCTAssertEqual(lowerBound, options.profilesSampleRate); - - options.profilesSampleRate = @0.5; - - NSNumber *tooLow = @-0.01; - options.profilesSampleRate = tooLow; - XCTAssertEqual(options.profilesSampleRate.doubleValue, 0); - - // setting an invalid sample rate effectively now enables continuous profiling, since it can let - // the backing variable remain nil - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testProfilesSampleRateUpperBound -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.profilesSampleRate = @0.5; - - NSNumber *lowerBound = @1; - options.profilesSampleRate = lowerBound; - XCTAssertEqual(lowerBound, options.profilesSampleRate); - - options.profilesSampleRate = @0.5; - - NSNumber *tooLow = @1.01; - options.profilesSampleRate = tooLow; - XCTAssertEqual(options.profilesSampleRate.doubleValue, 0); - - // setting an invalid sample rate effectively now enables continuous profiling, since it can let - // the backing variable remain nil - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testIsProfilingEnabled_NothingSet_IsDisabled -{ - SentryOptions *options = [[SentryOptions alloc] init]; - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertFalse(options.isProfilingEnabled); - - XCTAssertNil(options.profilesSampleRate); - XCTAssertTrue([options isContinuousProfilingEnabled]); -} - -- (void)testIsProfilingEnabled_ProfilesSampleRateSetToZero_IsDisabled -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.profilesSampleRate = @0.00; - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertFalse(options.isProfilingEnabled); - - XCTAssertNotNil(options.profilesSampleRate); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testIsProfilingEnabled_ProfilesSampleRateSet_IsEnabled -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.profilesSampleRate = @0.01; - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertTrue(options.isProfilingEnabled); - - XCTAssertNotNil(options.profilesSampleRate); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testIsProfilingEnabled_ProfilesSamplerSet_IsEnabled -{ - SentryOptions *options = [[SentryOptions alloc] init]; - options.profilesSampler = ^(SentrySamplingContext *context) { - XCTAssertNotNil(context); - return @0.0; - }; - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertTrue(options.isProfilingEnabled); - - XCTAssertNil(options.profilesSampleRate); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testIsProfilingEnabled_EnableProfilingSet_IsEnabled -{ - SentryOptions *options = [[SentryOptions alloc] init]; -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - options.enableProfiling = YES; -# pragma clang diagnostic pop - - // This property now only refers to trace-based profiling, but renaming it would require a major - // rev - XCTAssertTrue(options.isProfilingEnabled); - - XCTAssertNil(options.profilesSampleRate); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testProfilesSampler -{ - SentryTracesSamplerCallback sampler = ^(SentrySamplingContext *context) { - XCTAssertNotNil(context); - return @1.0; - }; - - SentryOptions *options = [self getValidOptions:@{ @"profilesSampler" : sampler }]; - - SentrySamplingContext *context = [[SentrySamplingContext alloc] init]; - XCTAssertEqual(options.profilesSampler(context), @1.0); - XCTAssertNil(options.profilesSampleRate); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -// this is a tricky part of the API, because while a profilesSampleRate of nil enables continuous -// profiling, just having the profilesSampler set at all disables it, even if the sampler function -// would return nil -- (void)testProfilesSamplerReturnsNil_ContinuousProfilingNotEnabled -{ - SentryTracesSamplerCallback sampler = ^(SentrySamplingContext *context) { - XCTAssertNotNil(context); - NSNumber *result = nil; - return result; - }; - - SentryOptions *options = [self getValidOptions:@{ @"profilesSampler" : sampler }]; - - SentrySamplingContext *context = [[SentrySamplingContext alloc] init]; - XCTAssertNil(options.profilesSampler(context)); - XCTAssertNil(options.profilesSampleRate); - XCTAssertFalse([options isContinuousProfilingEnabled]); -} - -- (void)testDefaultProfilesSampler -{ - SentryOptions *options = [self getValidOptions:@{}]; - XCTAssertNil(options.profilesSampler); - XCTAssertTrue([options isContinuousProfilingEnabled]); -} - -- (void)testGarbageProfilesSampler_ReturnsNil -{ - SentryOptions *options = [self getValidOptions:@{ @"profilesSampler" : @"fault" }]; - XCTAssertNil(options.profilesSampler); - XCTAssertTrue([options isContinuousProfilingEnabled]); -} -# pragma clang diagnostic pop - -#endif // SENTRY_TARGET_PROFILING_SUPPORTED - - (void)testInAppIncludes { NSArray *expected = @[ @"iOS-Swift", @"BusinessLogic" ]; diff --git a/Tests/SentryTests/Transaction/SentrySpanTests.swift b/Tests/SentryTests/Transaction/SentrySpanTests.swift index 6a9fcd5d50..533eca4f80 100644 --- a/Tests/SentryTests/Transaction/SentrySpanTests.swift +++ b/Tests/SentryTests/Transaction/SentrySpanTests.swift @@ -67,23 +67,7 @@ class SentrySpanTests: XCTestCase { } #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) - func testSpanDoesNotIncludeTraceProfilerID() throws { - fixture.options.profilesSampleRate = 1 - SentrySDKInternal.setStart(with: fixture.options) - let span = fixture.getSut() - let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { - $0.name?.rawValue == kSentryNotificationContinuousProfileStarted - } - XCTAssertEqual(continuousProfileObservations.count, 0) - XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) - span.finish() - - let serialized = span.serialize() - XCTAssertNil(serialized["profile_id"]) - } - func testSpanDoesNotSubscribeToNotificationsIfAlreadyCapturedContinuousProfileID() { - fixture.options.profilesSampleRate = nil SentryContinuousProfiler.start() SentrySDKInternal.setStart(with: fixture.options) let _ = fixture.getSut() @@ -93,18 +77,7 @@ class SentrySpanTests: XCTestCase { XCTAssertEqual(continuousProfileObservations.count, 0) } - func testSpanDoesNotSubscribeToNotificationsIfContinuousProfilingDisabled() { - fixture.options.profilesSampleRate = 1 - SentrySDKInternal.setStart(with: fixture.options) - let _ = fixture.getSut() - let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { - $0.name?.rawValue == kSentryNotificationContinuousProfileStarted - } - XCTAssertEqual(continuousProfileObservations.count, 0) - } - func testSpanDoesSubscribeToNotificationsIfNotAlreadyCapturedContinuousProfileID() { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) let _ = fixture.getSut() let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { @@ -120,7 +93,6 @@ class SentrySpanTests: XCTestCase { /// +----profile----+ /// ``` func test_spanStart_profileStart_spanEnd_profileEnd_spanIncludesProfileID() throws { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() XCTAssertEqual(fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { @@ -142,7 +114,6 @@ class SentrySpanTests: XCTestCase { /// +----profile----+ /// ``` func test_spanStart_profileStart_profileEnd_spanEnd_spanIncludesProfileID() throws { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() SentryContinuousProfiler.start() @@ -162,7 +133,6 @@ class SentrySpanTests: XCTestCase { /// +-------span-------+ /// ``` func test_profileStart_spanStart_profileEnd_spanEnd_spanIncludesProfileID() throws { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) SentryContinuousProfiler.start() let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) @@ -182,7 +152,6 @@ class SentrySpanTests: XCTestCase { /// +-------span-------+ /// ``` func test_profileStart_spanStart_spanEnd_profileEnd_spanIncludesProfileID() throws { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) SentryContinuousProfiler.start() let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) @@ -201,7 +170,6 @@ class SentrySpanTests: XCTestCase { /// +--profile1--+ +--profile2--+ /// ``` func test_spanStart_profileStart_profileEnd_profileStart_profileEnd_spanEnd_spanIncludesSameProfileID() throws { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() SentryContinuousProfiler.start() @@ -224,7 +192,6 @@ class SentrySpanTests: XCTestCase { /// +----profile----+ /// ``` func test_spanStart_spanEnd_profileStart_profileEnd_spanDoesNotIncludeProfileID() { - fixture.options.profilesSampleRate = nil SentrySDKInternal.setStart(with: fixture.options) SentryContinuousProfiler.start() SentryContinuousProfiler.stop()