[No QA] Add Sentry performance spans to the networking pipeline#82731
[No QA] Add Sentry performance spans to the networking pipeline#82731roryabraham merged 25 commits intomainfrom
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
…tesQueue Co-authored-by: Cursor <cursoragent@cursor.com>
…R, and auto-wrap all middlewares
Introduces a three-level span hierarchy inside processWithMiddleware:
- processWithMiddleware (outermost, full pipeline)
- HttpUtils.xhr (network I/O)
- processMiddlewares (aggregate middleware cost)
- individual middleware spans (auto-wrapped via addMiddleware)
The addMiddleware function now accepts a name parameter used to
create per-middleware child spans under processMiddlewares.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Type catch block error as unknown and use instanceof Error - Add required name parameter to addMiddleware calls in MiddlewareTest.ts Co-authored-by: Cursor <cursoragent@cursor.com>
… value If a middleware doesn't return a promise (returns undefined), fall back to the previous promise in the chain. This prevents a TypeError when chaining .then() on the reduce result. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@codex review |
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
|
@youssef-lr Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
@heyjennahay no product considerations |
…rejection Co-authored-by: Cursor <cursoragent@cursor.com>
…span .finally() always set the span status to OK, masking errors. Now the span correctly reports failure status when flushQueue() rejects. Co-authored-by: Cursor <cursoragent@cursor.com>
Add MIDDLEWARE_* constants under CONST.TELEMETRY for all 10 production middlewares and replace plain string names in API/index.ts and MiddlewareTest.ts with the constants. Co-authored-by: Cursor <cursoragent@cursor.com>
- Convert makeXHR from .then() chain to flat async/await with try/catch - Replace middlewares.reduce() with a for...of loop building a currentResponsePromise variable iteratively - Replace final .then()/.catch() with try/catch around await - Rename variables: pipeline -> currentResponsePromise, tappedLast -> instrumentedMiddlewareInput Per-middleware .then() calls remain because the Middleware type contract requires receiving a promise, not an awaited value. All span logic is identical — no behavioral changes. Co-authored-by: Cursor <cursoragent@cursor.com>
With the async/await conversion, TypeScript can no longer infer the TKey generic parameter from the .then() chain's return type annotation. Passing <TKey> explicitly to HttpUtils.xhr resolves the type mismatch. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Updated and ready for review! |
Reviewer Checklist
|
|
🚧 @roryabraham has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.3.24-1 🚀
|
|
🚀 Deployed to production by https://github.com/puneetlath in version: 9.3.24-3 🚀
|
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.3.31-0 🚀
|
|
🚀 Deployed to production by https://github.com/blimpich in version: 9.3.31-12 🚀
|
Explanation of Change
Adds Sentry performance spans across the E/App networking pipeline to enable identification of performance bottlenecks and regressions in the request lifecycle. This instruments:
flush,process,flushOnyxUpdatesQueue) — measures full queue processing cycles and per-request timingprocessWithMiddleware,processMiddlewares,makeXHR) — three-level hierarchy separating network I/O from middleware processingaddMiddleware(middleware, name)so each middleware gets its own child span underprocessMiddlewaresapplyHTTPSOnyxUpdates,applyPusherOnyxUpdates,applyAirshipOnyxUpdates) — measures Onyx update application alongside existingPerformance.markStart/EndprepareRequest()— measures time to apply optimistic updates before network callsThe span hierarchy for a write request flush cycle looks like:
All spans follow the existing
Manual*naming convention and includecommandattributes for Sentry dashboard slicing.Fixed Issues
N/A — internal performance instrumentation, no linked issue.
Tests
ENABLE_SENTRY_ON_DEV=truein.env, runnpm run webManualSequentialQueueFlush,ManualSequentialQueueProcess,middleware.Logging, etc.) Sentry logs begin with[SENTRY]Offline tests
N/A — these spans are no-ops when Sentry is not initialized (offline, test environments). The SequentialQueue and middleware behavior is unchanged.
QA Steps
No QA — this PR adds observability instrumentation only. No user-facing behavior changes. Spans are no-ops when Sentry is not initialized.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos