Skip to content

Commit ea5408a

Browse files
authored
WaitingTimeTracker improvements (#15082)
2 parents 9068893 + 6de1ef0 commit ea5408a

File tree

4 files changed

+63
-22
lines changed

4 files changed

+63
-22
lines changed

WooCommerce/Classes/Analytics/AppStartupWaitingTimeTracker.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import protocol WooFoundation.Analytics
55
/// Tracks the waiting time for app startup, allowing to evaluate as analytics
66
/// how much time in seconds it took between the init and the final `end(action:)` function call.
77
///
8-
class AppStartupWaitingTimeTracker: WaitingTimeTracker {
8+
final class AppStartupWaitingTimeTracker: WaitingTimeTracker {
99

1010
/// All actions tracked in the app startup waiting time.
1111
///
@@ -21,8 +21,8 @@ class AppStartupWaitingTimeTracker: WaitingTimeTracker {
2121
private(set) var startupActionsPending = StartupAction.allCases
2222

2323
init(analyticsService: Analytics = ServiceLocator.analytics,
24-
currentTimeInMillis: @escaping () -> TimeInterval = { Date().timeIntervalSince1970 }) {
25-
super.init(trackScenario: .appStartup, analyticsService: analyticsService, currentTime: currentTimeInMillis)
24+
currentTimestampSeconds: @escaping () -> TimeInterval = { Date().timeIntervalSince1970 }) {
25+
super.init(trackScenario: .appStartup, analyticsService: analyticsService, currentTimestampSeconds: currentTimestampSeconds)
2626
}
2727

2828
/// Ends the waiting time for the provided startup action.

WooCommerce/Classes/Analytics/WaitingTimeTracker.swift

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,46 @@ import protocol WooFoundation.Analytics
77
///
88
class WaitingTimeTracker {
99
private let trackScenario: WooAnalyticsEvent.WaitingTime.Scenario
10-
private let currentTime: () -> TimeInterval
10+
private let currentTimestampSeconds: () -> TimeInterval
1111
private let analyticsService: Analytics
1212
private let waitingStartedTimestamp: TimeInterval
1313

14+
enum TrackingUnit {
15+
case seconds
16+
case milliseconds
17+
}
18+
1419
init(trackScenario: WooAnalyticsEvent.WaitingTime.Scenario,
1520
analyticsService: Analytics = ServiceLocator.analytics,
16-
currentTime: @escaping () -> TimeInterval = { Date().timeIntervalSince1970 }
21+
currentTimestampSeconds: @escaping () -> TimeInterval = { Date().timeIntervalSince1970 }
1722
) {
1823
self.trackScenario = trackScenario
1924
self.analyticsService = analyticsService
20-
self.currentTime = currentTime
21-
waitingStartedTimestamp = currentTime()
25+
self.currentTimestampSeconds = currentTimestampSeconds
26+
waitingStartedTimestamp = currentTimestampSeconds()
2227
}
2328

24-
/// End the waiting time by evaluating the elapsed time from the init,
25-
/// and sending it as an analytics event, in seconds.
29+
/// Default `end()` method to preserve interface compatibility. By default, tracks in `.seconds`
2630
///
2731
func end() {
28-
let elapsedTime = currentTime() - waitingStartedTimestamp
29-
let analyticsEvent = WooAnalyticsEvent.WaitingTime.waitingFinished(scenario: trackScenario, elapsedTime: elapsedTime)
30-
analyticsService.track(event: analyticsEvent)
32+
end(using: .seconds)
3133
}
3234

3335
/// End the waiting time by evaluating the elapsed time from the init,
34-
/// and sending it as an analytics event, in milliseconds
36+
/// and sending it as an analytics event.
3537
///
36-
func endInMilliseconds() {
37-
let elapsedTimeMs = (currentTime() - waitingStartedTimestamp) * 1000
38-
let analyticsEvent = WooAnalyticsEvent.WaitingTime.waitingFinished(scenario: trackScenario, elapsedTime: elapsedTimeMs)
38+
/// - Parameter trackingUnit: Defines whether the elapsed time should be tracked in `.seconds` or `.milliseconds` (default is `.seconds`).
39+
///
40+
func end(using trackingUnit: TrackingUnit = .seconds) {
41+
let elapsedTime = calculateElapsedTime(in: trackingUnit)
42+
let analyticsEvent = WooAnalyticsEvent.WaitingTime.waitingFinished(scenario: trackScenario, elapsedTime: elapsedTime)
3943
analyticsService.track(event: analyticsEvent)
4044
}
45+
46+
/// Calculates elapsed time in the specified tracking unit.
47+
///
48+
private func calculateElapsedTime(in trackingUnit: TrackingUnit) -> TimeInterval {
49+
let elapsedTime = currentTimestampSeconds() - waitingStartedTimestamp
50+
return trackingUnit == .milliseconds ? elapsedTime * 1000 : elapsedTime
51+
}
4152
}

WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleLoadingView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ private extension PointOfSaleLoadingView {
3131

3232
func trackElapsedTimeOnDisappear() {
3333
if let waitingTimeTracker = waitingTimeTracker {
34-
waitingTimeTracker.endInMilliseconds()
34+
waitingTimeTracker.end(using: .milliseconds)
3535
}
3636
}
3737
}

WooCommerce/WooCommerceTests/System/WaitingTimeTrackerTests.swift

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class WaitingTimeTrackerTests: XCTestCase {
2626

2727
func testOrderDetailsTrackScenarioTriggersExpectedAnalyticsStat() {
2828
// Given
29-
let waitingTracker = WaitingTimeTracker(trackScenario: .orderDetails, analyticsService: testAnalytics, currentTime: { 0 })
29+
let waitingTracker = WaitingTimeTracker(trackScenario: .orderDetails, analyticsService: testAnalytics, currentTimestampSeconds: { 0 })
3030

3131
// When
3232
waitingTracker.end()
@@ -39,7 +39,7 @@ class WaitingTimeTrackerTests: XCTestCase {
3939
// Given
4040
let waitingTracker = WaitingTimeTracker(trackScenario: .dashboardTopPerformers,
4141
analyticsService: testAnalytics,
42-
currentTime: { 0 }
42+
currentTimestampSeconds: { 0 }
4343
)
4444

4545
// When
@@ -53,7 +53,7 @@ class WaitingTimeTrackerTests: XCTestCase {
5353
// Given
5454
let waitingTracker = WaitingTimeTracker(trackScenario: .dashboardMainStats,
5555
analyticsService: testAnalytics,
56-
currentTime: { 0 }
56+
currentTimestampSeconds: { 0 }
5757
)
5858

5959
// When
@@ -67,7 +67,7 @@ class WaitingTimeTrackerTests: XCTestCase {
6767
// Given
6868
let waitingTracker = WaitingTimeTracker(trackScenario: .analyticsHub,
6969
analyticsService: testAnalytics,
70-
currentTime: { 0 }
70+
currentTimestampSeconds: { 0 }
7171
)
7272

7373
// When
@@ -81,7 +81,7 @@ class WaitingTimeTrackerTests: XCTestCase {
8181
// Given
8282
let waitingTracker = WaitingTimeTracker(trackScenario: .appStartup,
8383
analyticsService: testAnalytics,
84-
currentTime: { 0 }
84+
currentTimestampSeconds: { 0 }
8585
)
8686

8787
// When
@@ -91,6 +91,36 @@ class WaitingTimeTrackerTests: XCTestCase {
9191
XCTAssertEqual(testAnalytics.lastReceivedEventName, WooAnalyticsStat.applicationOpenedWaitingTimeLoaded.rawValue)
9292
}
9393

94+
func test_timeElapsed_evaluation_in_milliseconds_is_correct() {
95+
// Given
96+
var currentTimeCallCounter = 0.0
97+
let expectedReceivedWaitingTime = 10_000.0 // 10s * 1000 ms
98+
let waitingTracker = WaitingTimeTracker(trackScenario: .orderDetails,
99+
analyticsService: testAnalytics) {
100+
currentTimeCallCounter += 1
101+
return currentTimeCallCounter * 10
102+
}
103+
104+
// When
105+
waitingTracker.end(using: .milliseconds)
106+
107+
// Then
108+
XCTAssertEqual(testAnalytics.lastReceivedWaitingTime, expectedReceivedWaitingTime)
109+
}
110+
111+
func test_track_scenario_triggers_expected_analytics_stat_in_milliseconds() {
112+
// Given
113+
let waitingTracker = WaitingTimeTracker(trackScenario: .pointOfSaleLoaded,
114+
analyticsService: testAnalytics,
115+
currentTimestampSeconds: { 0 })
116+
117+
// When
118+
waitingTracker.end(using: .milliseconds)
119+
120+
// Then
121+
XCTAssertEqual(testAnalytics.lastReceivedEventName, WooAnalyticsStat.pointOfSaleLoaded.rawValue)
122+
}
123+
94124
class TestAnalytics: Analytics {
95125
var lastReceivedEventName: String? = nil
96126
var lastReceivedWaitingTime: TimeInterval? = nil

0 commit comments

Comments
 (0)