expoUpdatesListenerIntegration listens to the expo-updates state machine and emits breadcrumbs for transitions (checking, downloading, update pending, errors, rollback, restart). However, it captures zero timestamps and zero durations — you can see that a download happened but not how long it took.
Implementation
Add a downloadSpan variable to the integration closure:
- Start a span (
startInactiveSpan({ name: 'expo.updates.download', op: 'expo.updates.download' })) when isDownloading transitions false→true.
- End the span when
isUpdatePending transitions false→true (download completed).
- End with error status if
downloadError transitions true.
- Clear the span reference on subscription cleanup.
Edge cases (already handled by existing logic)
- Download starts before SDK init:
latestContext seeds previousContext on setup. If isDownloading is already true, the falsy-to-truthy check won't fire — no phantom span.
- Download completes before SDK init: Same mechanism —
isUpdatePending already true means no spurious span end.
- Multiple sequential updates: Each new download cycle transitions
isDownloading false→true again, starting a new span.
- Download error (no pending): Span ends with error status on
downloadError. Clear the reference so retries start a new span.
- No active transaction:
startInactiveSpan works as a standalone span.
Scope
JS only. ~20-30 lines of code + tests.
expoUpdatesListenerIntegrationlistens to theexpo-updatesstate machine and emits breadcrumbs for transitions (checking, downloading, update pending, errors, rollback, restart). However, it captures zero timestamps and zero durations — you can see that a download happened but not how long it took.Implementation
Add a
downloadSpanvariable to the integration closure:startInactiveSpan({ name: 'expo.updates.download', op: 'expo.updates.download' })) whenisDownloadingtransitions false→true.isUpdatePendingtransitions false→true (download completed).downloadErrortransitions true.Edge cases (already handled by existing logic)
latestContextseedspreviousContexton setup. IfisDownloadingis already true, the falsy-to-truthy check won't fire — no phantom span.isUpdatePendingalready true means no spurious span end.isDownloadingfalse→true again, starting a new span.downloadError. Clear the reference so retries start a new span.startInactiveSpanworks as a standalone span.Scope
JS only. ~20-30 lines of code + tests.