[WOOMOB-2061] Add analytics tracking for file-based catalog sync#15288
[WOOMOB-2061] Add analytics tracking for file-based catalog sync#15288malinajirka wants to merge 15 commits intotrunkfrom
Conversation
Extend the sync_strategy analytics property to distinguish file-based local catalog sync from paginated sync. This allows filtering analytics by sync method to identify performance issues with file-based approach. - Add LOCAL_CATALOG_FILE to SyncStrategy enum - Inject WooPosLocalCatalogFileApproachEnabled to determine sync method - Update analytics mapping to include "local_catalog_file" value - Update exhaustive when expressions in search and identifier lookup
Extend Success class with optional generationDurationMs and pollAttempts for tracking server-side generation time and polling attempts. Extend CatalogGenerationTimeout with lastGenerationState and pollAttempts to track the last observed state before timeout for debugging.
Add site-specific methods to persist poll attempts across worker retries: - getFileBasedSyncPollAttempts: read accumulated attempts - setFileBasedSyncPollAttempts: store attempts count - clearFileBasedSyncPollAttempts: reset after successful sync This ensures poll_attempts continue accumulating when the worker retries after a timeout instead of resetting to 0.
Add calculateGenerationDuration method to compute server-side generation time from scheduledAt and completedAt timestamps. Returns the difference in milliseconds for tracking slow catalog generation.
- Read accumulated poll attempts from preferences at sync start - Track current run poll attempts and accumulate with previous retries - Track last generation state (scheduled/in_progress/completed) for timeouts - Calculate generation duration from API timestamps (completedAt - scheduledAt) - Pass poll attempts and generation duration to Success result - Pass last generation state and poll attempts to CatalogGenerationTimeout - Clear poll attempts on success, persist on timeout for next retry
Update LocalCatalogSyncCompleted event: - Add optional generationDurationMs for server-side generation time - Add optional pollAttempts for number of polling attempts Update LocalCatalogSyncFailed event: - Add optional lastGenerationState for timeout debugging - Add optional pollAttempts for tracking retry accumulation Properties are only included when non-null (file-based sync only).
Update trackSyncCompleted to include: - generationDurationMs from Success result - pollAttempts from Success result Update trackSyncFailed to include: - lastGenerationState from CatalogGenerationTimeout - pollAttempts from CatalogGenerationTimeout
Update checks that compared against LOCAL_CATALOG to use != REMOTE instead, so they work correctly for both LOCAL_CATALOG and LOCAL_CATALOG_FILE sync strategies.
📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
|
|
📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.
|
# Conflicts: # WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosPreferencesRepository.kt
…eferencesRepository
…ndling in `WooPosFileBasedSyncAction`
- Simplify poll attempt logic by removing `currentRunPollAttempts`. - Use `attemptIndex` consistently in logs and calculations. - Consolidate total poll attempts calculation for timeout handling.
There was a problem hiding this comment.
Pull request overview
Adds additional analytics metadata for the file-based local catalog sync to better diagnose “stuck” generation/polling scenarios, including generation duration, total poll attempts, and last-known generation state on timeout.
Changes:
- Extend local catalog sync result and analytics events to include
generation_duration_ms,poll_attempts, andlast_generation_state(timeout). - Persist poll attempt counts in DataStore and wire them into the file-based sync action + tests.
- Introduce/propagate a new
LOCAL_CATALOG_FILEsync strategy across UI/analytics decision points.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosFileBasedSyncAction.kt | Computes/passes poll attempts, tracks last generation state, stores attempts on timeout, computes generation duration. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosLocalCatalogSyncRepository.kt | Sends new optional analytics properties on completed/failed events (timeout-only for failure props). |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosSyncResult.kt | Extends success + timeout failure result types with new optional fields. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/analytics/WooPosAnalyticsEvent.kt | Adds optional properties for completed/failed local catalog sync analytics; adds mapping for LOCAL_CATALOG_FILE. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosPreferencesRepository.kt | Adds DataStore persistence helpers for file-based sync poll attempts. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosSyncTimestampManager.kt | Adds helper to compute generation duration from API timestamps. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt | Adds LOCAL_CATALOG_FILE sync strategy and determines it via feature flag. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/categories/WooPosSettingsCategoriesViewModel.kt | Shows Local Catalog settings category for any non-remote strategy (includes file-based). |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/search/WooPosItemsSearchViewModel.kt | Enables PTR for both local catalog strategies. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/data/searchbyidentifier/WooPosSearchByIdentifier.kt | Avoids remote fallback whenever using a non-remote sync strategy. |
| WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/data/searchbyidentifier/WooPosSearchByIdentifierLocal.kt | Treats LOCAL_CATALOG_FILE like LOCAL_CATALOG for local search behavior. |
| WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosFileBasedSyncActionTest.kt | Adds coverage for persisted poll attempts, generation duration, and timeout last-state propagation. |
| WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSourceTest.kt | Updates construction for the new feature-flag dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| val siteId = site.localId() | ||
| val accumulatedPollAttempts = preferencesRepository.getAndClearFileBasedSyncPollAttempts(siteId) | ||
| var lastGenerationState: WooPosGenerateCatalogState? = null |
There was a problem hiding this comment.
getAndClearFileBasedSyncPollAttempts() clears the persisted counter at the start of a run, but most non-timeout failure paths (e.g., consecutive network failures, download/parse/store failures, missing URL) return without re-persisting the updated count. This can drop previously accumulated attempts and defeats the “accumulated across app restarts” behavior. Consider reading without clearing, incrementing as you poll, and only clearing on successful completion (or re-saving the latest total on any early exit/failure).
| val timeoutResult = result as? PosLocalCatalogSyncResult.Failure.CatalogGenerationTimeout | ||
|
|
||
| analyticsTracker.track( | ||
| LocalCatalogSyncFailed( | ||
| syncType = syncType, | ||
| errorContext = "WooPosLocalCatalogSyncRepository", | ||
| errorType = errorType, | ||
| errorDescription = result.error | ||
| errorDescription = result.error, | ||
| lastGenerationState = timeoutResult?.lastGenerationState, | ||
| pollAttempts = timeoutResult?.pollAttempts |
There was a problem hiding this comment.
The new failure analytics properties (lastGenerationState, pollAttempts) are only populated when the failure is CatalogGenerationTimeout (via the cast). Other file-based sync failures will still emit local_catalog_sync_failed without these properties, which doesn’t match the PR description (“times out or fails”). Either propagate these properties for other failure types too (e.g., by carrying pollAttempts/last state in a shared failure type) or adjust the PR description to clarify it’s timeout-only.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## trunk #15288 +/- ##
=========================================
Coverage 38.85% 38.86%
- Complexity 10729 10730 +1
=========================================
Files 2214 2214
Lines 125980 126046 +66
Branches 17465 17479 +14
=========================================
+ Hits 48954 48984 +30
- Misses 72072 72098 +26
- Partials 4954 4964 +10 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
📓 This can wait for after the Bookings work. |
Fixes WOOMOB-2061
Description
Adds analytics tracking for the file-based local catalog sync to help diagnose "stuck" sync issues. When sync times out or fails, we now track additional properties to understand where the sync got stuck:
Poll attempts are accumulated across app restarts so we can see the total attempts when users repeatedly open/close the app during long syncs.
Based on pdfdoF-8GW-p2.
Test Steps
last_generation_stateandpoll_attempts(easiest way to force it is to update the code, however, I tested it by scheduling a job and before it started I cancelled it inWPAdmin -> WooCommerce -> Status -> Scheduled Actions -> Pending -> Search forfeed` -> cancel catalog generation action)Images/gif
N/A - Analytics changes only
RELEASE-NOTES.txtif necessary. Use the "[Internal]" label for non-user-facing changes.