Skip to content

Commit

Permalink
Add launch time pixels (#3621)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/0/1208832732122368/f

**Description**:
We want to measure our app’s launch speed to establish a baseline for
future improvements.

**Steps to test this PR**:
1. Launch the app and check if three m.debug.app-did-* pixels fired.
2. Launch the app and quickly go into background - the pixel related to
showing the UI likely shouldn’t be triggered.
  • Loading branch information
jaceklyp authored Nov 26, 2024
1 parent e8b8322 commit 6eaa17e
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Core/Pixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ public struct PixelParameters {
// Persistent pixel
public static let originalPixelTimestamp = "originalPixelTimestamp"
public static let retriedPixel = "retriedPixel"

public static let time = "time"
}

public struct PixelValues {
Expand Down
11 changes: 11 additions & 0 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,12 @@ extension Pixel {
case duckPlayerYouTubeOverlayNavigationOutsideYoutube
case duckPlayerYouTubeOverlayNavigationClosed
case duckPlayerYouTubeNavigationIdle30

// MARK: Launch time
case appDidFinishLaunchingTime(time: BucketAggregation)
case appDidShowUITime(time: BucketAggregation)
case appDidBecomeActiveTime(time: BucketAggregation)

}

}
Expand Down Expand Up @@ -1734,6 +1740,11 @@ extension Pixel.Event {
case .duckPlayerYouTubeOverlayNavigationClosed: return "duckplayer.youtube.overlay.navigation.closed"
case .duckPlayerYouTubeNavigationIdle30: return "duckplayer.youtube.overlay.idle-30"

// MARK: Launch time
case .appDidFinishLaunchingTime(let time): return "m_debug_app-did-finish-launching-time-\(time)"
case .appDidShowUITime(let time): return "m_debug_app-did-show-ui-time-\(time)"
case .appDidBecomeActiveTime(let time): return "m_debug_app-did-become-active-time-\(time)"

}
}
}
Expand Down
31 changes: 30 additions & 1 deletion DuckDuckGo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ import os.log
private let voiceSearchHelper = VoiceSearchHelper()

private let marketplaceAdPostbackManager = MarketplaceAdPostbackManager()

private var didFinishLaunchingStartTime: CFAbsoluteTime?

override init() {
super.init()

Expand All @@ -125,8 +128,19 @@ import os.log
}

// swiftlint:disable:next function_body_length
// swiftlint:disable:next cyclomatic_complexity
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

didFinishLaunchingStartTime = CFAbsoluteTimeGetCurrent()
defer {
if let didFinishLaunchingStartTime {
let launchTime = CFAbsoluteTimeGetCurrent() - didFinishLaunchingStartTime
Pixel.fire(pixel: .appDidFinishLaunchingTime(time: Pixel.Event.BucketAggregation(number: launchTime)),
withAdditionalParameters: [PixelParameters.time: String(launchTime)])
}
}


#if targetEnvironment(simulator)
if ProcessInfo.processInfo.environment["UITESTING"] == "true" {
// Disable hardware keyboards.
Expand Down Expand Up @@ -358,7 +372,8 @@ import os.log
voiceSearchHelper: voiceSearchHelper,
featureFlagger: AppDependencyProvider.shared.featureFlagger,
subscriptionCookieManager: subscriptionCookieManager,
textZoomCoordinator: makeTextZoomCoordinator())
textZoomCoordinator: makeTextZoomCoordinator(),
appDidFinishLaunchingStartTime: didFinishLaunchingStartTime)

main.loadViewIfNeeded()
syncErrorHandler.alertPresenter = main
Expand Down Expand Up @@ -560,6 +575,14 @@ import os.log
func applicationDidBecomeActive(_ application: UIApplication) {
guard !testing else { return }

defer {
if let didFinishLaunchingStartTime {
let launchTime = CFAbsoluteTimeGetCurrent() - didFinishLaunchingStartTime
Pixel.fire(pixel: .appDidBecomeActiveTime(time: Pixel.Event.BucketAggregation(number: launchTime)),
withAdditionalParameters: [PixelParameters.time: String(launchTime)])
}
}

StorageInconsistencyMonitor().didBecomeActive(isProtectedDataAvailable: application.isProtectedDataAvailable)
syncService.initializeIfNeeded()
syncDataProviders.setUpDatabaseCleanersIfNeeded(syncService: syncService)
Expand Down Expand Up @@ -754,6 +777,12 @@ import os.log
suspendSync()
syncDataProviders.bookmarksAdapter.cancelFaviconsFetching(application)
privacyProDataReporter.saveApplicationLastSessionEnded()
resetAppStartTime()
}

private func resetAppStartTime() {
didFinishLaunchingStartTime = nil
mainViewController?.appDidFinishLaunchingStartTime = nil
}

private func suspendSync() {
Expand Down
15 changes: 13 additions & 2 deletions DuckDuckGo/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class MainViewController: UIViewController {
var historyManager: HistoryManaging
var viewCoordinator: MainViewCoordinator!

var appDidFinishLaunchingStartTime: CFAbsoluteTime?

init(
bookmarksDatabase: CoreDataDatabase,
bookmarksDatabaseCleaner: BookmarkDatabaseCleaner,
Expand All @@ -206,7 +208,8 @@ class MainViewController: UIViewController {
featureFlagger: FeatureFlagger,
fireproofing: Fireproofing = UserDefaultsFireproofing.shared,
subscriptionCookieManager: SubscriptionCookieManaging,
textZoomCoordinator: TextZoomCoordinating
textZoomCoordinator: TextZoomCoordinating,
appDidFinishLaunchingStartTime: CFAbsoluteTime?
) {
self.bookmarksDatabase = bookmarksDatabase
self.bookmarksDatabaseCleaner = bookmarksDatabaseCleaner
Expand Down Expand Up @@ -246,6 +249,7 @@ class MainViewController: UIViewController {
self.fireproofing = fireproofing
self.subscriptionCookieManager = subscriptionCookieManager
self.textZoomCoordinator = textZoomCoordinator
self.appDidFinishLaunchingStartTime = appDidFinishLaunchingStartTime

super.init(nibName: nil, bundle: nil)

Expand Down Expand Up @@ -337,7 +341,14 @@ class MainViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

defer {
if let appDidFinishLaunchingStartTime {
let launchTime = CFAbsoluteTimeGetCurrent() - appDidFinishLaunchingStartTime
Pixel.fire(pixel: .appDidShowUITime(time: Pixel.Event.BucketAggregation(number: launchTime)),
withAdditionalParameters: [PixelParameters.time: String(launchTime)])
}
}

// Needs to be called here because sometimes the frames are not the expected size during didLoad
refreshViewsBasedOnAddressBarPosition(appSettings.currentAddressBarPosition)

Expand Down
3 changes: 2 additions & 1 deletion DuckDuckGoTests/OnboardingDaxFavouritesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ final class OnboardingDaxFavouritesTests: XCTestCase {
voiceSearchHelper: MockVoiceSearchHelper(isSpeechRecognizerAvailable: true, voiceSearchEnabled: true),
featureFlagger: MockFeatureFlagger(),
subscriptionCookieManager: SubscriptionCookieManagerMock(),
textZoomCoordinator: MockTextZoomCoordinator()
textZoomCoordinator: MockTextZoomCoordinator(),
appDidFinishLaunchingStartTime: nil
)
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIViewController()
Expand Down
3 changes: 2 additions & 1 deletion DuckDuckGoTests/OnboardingNavigationDelegateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ final class OnboardingNavigationDelegateTests: XCTestCase {
voiceSearchHelper: MockVoiceSearchHelper(isSpeechRecognizerAvailable: true, voiceSearchEnabled: true),
featureFlagger: MockFeatureFlagger(),
subscriptionCookieManager: SubscriptionCookieManagerMock(),
textZoomCoordinator: MockTextZoomCoordinator())
textZoomCoordinator: MockTextZoomCoordinator(),
appDidFinishLaunchingStartTime: nil)
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIViewController()
window.makeKeyAndVisible()
Expand Down

0 comments on commit 6eaa17e

Please sign in to comment.