From f8833c443d047f0c8dac5710e52b4c0624fc52ce Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Fri, 16 Feb 2024 21:10:26 +0800 Subject: [PATCH] feat(app launch profiling): add app launch profiling (#3529) --- CHANGELOG.md | 5 + .../xcshareddata/xcschemes/iOS-Swift.xcscheme | 22 +- .../xcschemes/iOS-SwiftUITests.xcscheme | 2 +- Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 17 +- .../iOS-Swift/Base.lproj/Main.storyboard | 62 +++- .../Profiling/ProfilingViewController.swift | 106 ++++-- .../TransactionsViewController.swift | 37 +- .../iOS-SwiftUITests/BaseUITest.swift | 32 +- .../iOS-SwiftUITests/ProfilingUITests.swift | 266 ++++++++++++-- .../iOS-SwiftUI.xcodeproj/project.pbxproj | 122 +++++++ Sentry.xcodeproj/project.pbxproj | 52 +-- .../SentryTestUtils-ObjC-BridgingHeader.h | 2 +- .../Sentry/Profiling/SentryLaunchProfiling.m | 169 +++++++++ .../Sentry/Profiling/SentryProfilerState.mm | 11 +- Sources/Sentry/Public/SentryOptions.h | 22 +- .../Sentry/Public/SentryTransactionContext.h | 9 + Sources/Sentry/SentryFileManager.m | 153 ++++++-- Sources/Sentry/SentryHub.m | 28 +- Sources/Sentry/SentryLog.m | 7 +- Sources/Sentry/SentryOptions.m | 50 +-- Sources/Sentry/SentryProfileTimeseries.mm | 2 + Sources/Sentry/SentryProfiler.mm | 88 ++++- Sources/Sentry/SentryProfilesSampler.m | 93 ----- Sources/Sentry/SentrySDK.m | 19 +- Sources/Sentry/SentrySamplerDecision.m | 15 + Sources/Sentry/SentrySampling.m | 117 ++++++ Sources/Sentry/SentryTracer.m | 45 ++- Sources/Sentry/SentryTracesSampler.m | 84 ----- Sources/Sentry/include/SentryFileManager.h | 39 ++ .../Sentry/include/SentryInternalDefines.h | 8 +- .../Sentry/include/SentryLaunchProfiling.h | 33 ++ .../Sentry/include/SentryOptions+Private.h | 12 +- .../Sentry/include/SentryProfilesSampler.h | 55 --- .../Sentry/include/SentrySamplerDecision.h | 17 + Sources/Sentry/include/SentrySampling.h | 24 ++ Sources/Sentry/include/SentryTraceOrigins.h | 1 + Sources/Sentry/include/SentryTracer.h | 13 +- .../include/SentryTracerConfiguration.h | 6 +- Sources/Sentry/include/SentryTracesSampler.h | 46 --- .../SentryAppLaunchProfilingTests.m | 151 ++++++++ .../SentryProfilerSwiftTests.swift | 58 ++- .../SentryProfilerTests.mm | 2 +- ...tProperties.h => SentryFileManager+Test.h} | 3 + .../Helper/SentryFileManagerTests.swift | 332 ++++++++++++------ Tests/SentryTests/SentryHubTests.swift | 19 +- .../SentryTests/SentryLaunchProfiling+Tests.h | 27 ++ Tests/SentryTests/SentryOptionsTest.m | 27 +- Tests/SentryTests/SentrySDK+Tests.h | 8 +- .../SentryTests/SentryTests-Bridging-Header.h | 3 +- .../Transaction/SentryTracerObjCTests.m | 1 - develop-docs/README.md | 16 + 51 files changed, 1883 insertions(+), 655 deletions(-) create mode 100644 Sources/Sentry/Profiling/SentryLaunchProfiling.m delete mode 100644 Sources/Sentry/SentryProfilesSampler.m create mode 100644 Sources/Sentry/SentrySamplerDecision.m create mode 100644 Sources/Sentry/SentrySampling.m delete mode 100644 Sources/Sentry/SentryTracesSampler.m create mode 100644 Sources/Sentry/include/SentryLaunchProfiling.h delete mode 100644 Sources/Sentry/include/SentryProfilesSampler.h create mode 100644 Sources/Sentry/include/SentrySamplerDecision.h create mode 100644 Sources/Sentry/include/SentrySampling.h delete mode 100644 Sources/Sentry/include/SentryTracesSampler.h create mode 100644 Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.m rename Tests/SentryTests/Helper/{SentryFileManager+TestProperties.h => SentryFileManager+Test.h} (72%) create mode 100644 Tests/SentryTests/SentryLaunchProfiling+Tests.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 842aff2a95d..09733f266e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Automatically profile app launches (#3529) + ### Improvements - Cache installationID async to avoid file IO on the main thread when starting the SDK (#3601) @@ -10,6 +14,7 @@ ### Fixes - Finish TTID span when transaction finishes (#3610) +- Don't take screenshot and view hierarchy for app hanging (#3620) - Dont take screenshot and view hierarchy for app hanging (#3620) - Remove `free_storage` and `storage_size` from the device context (#3627), because Apple forbids sending information retrieved via `NSFileSystemFreeSize` and `NSFileSystemSize` off a device; see diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme index fa07f21b626..dc3a836c25c 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme @@ -23,7 +23,7 @@ @@ -73,6 +73,26 @@ argument = "--disable-file-io-tracing" isEnabled = "NO"> + + + + + + + + + + diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-SwiftUITests.xcscheme b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-SwiftUITests.xcscheme index 55e1974867d..37a4ca1e81a 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-SwiftUITests.xcscheme +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-SwiftUITests.xcscheme @@ -25,7 +25,7 @@ Bool { - print("[iOS-Swift] launch arguments: \(ProcessInfo.processInfo.arguments)") - print("[iOS-Swift] environment: \(ProcessInfo.processInfo.environment)") + print("[iOS-Swift] [debug] launch arguments: \(ProcessInfo.processInfo.arguments)") + print("[iOS-Swift] [debug] environment: \(ProcessInfo.processInfo.environment)") maybeWipeData() AppDelegate.startSentry() @@ -161,9 +165,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } private extension AppDelegate { + // previously tried putting this in an AppDelegate.load override in ObjC, but it wouldn't run until after a launch profiler would have an opportunity to run, since SentryProfiler.load would always run first due to being dynamically linked in a framework module. it is sufficient to do it before calling SentrySDK.startWithOptions to clear state for testProfiledAppLaunches because we don't make any assertions on a launch profile the first launch of the app in that test func maybeWipeData() { if ProcessInfo.processInfo.arguments.contains("--io.sentry.wipe-data") { - print("[iOS-Swift] removing app data") + print("[iOS-Swift] [debug] removing app data") let appSupport = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first! let cache = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first! for path in [appSupport, cache] { diff --git a/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard b/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard index 094218d85bd..67696810cb6 100644 --- a/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard +++ b/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -172,7 +172,7 @@ - + @@ -223,8 +223,57 @@ + + + + + + + + + + + + + + + - +