UN-3444 [FEAT] Propagate frontend request ID and surface it on error notifications#1955
Conversation
…notifications - Add `X-Request-ID` request interceptor (uuidv4) on the global axios instance and on each `useAxiosPrivate` axios instance so every API call carries a client-generated correlation ID. Django/Flask backends already honor incoming `X-Request-ID`, so backend logs reuse the same value. - Extract the request ID in `useExceptionHandler` from response headers with a fallback to the outgoing request headers (covers network/cancel errors). - Thread `requestId` through the alert store and render it in the error notification with an antd `Typography.Text copyable` for a one-click copy.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Summary by CodeRabbit
WalkthroughAdds X-Request-ID support: a helper injects/generates request IDs on Axios requests and extracts them from errors; global and private Axios instances attach the interceptor; exception handler threads requestId into alerts; alert store holds requestId; notifications show a copyable Request ID for error alerts. ChangesRequest ID Tracking
Sequence DiagramsequenceDiagram
participant App
participant Axios
participant ReqInterceptor as Request Interceptor
participant Server
participant ErrHandler as Error Handler
participant AlertStore as Alert Store
participant Notification
App->>Axios: attachRequestIdInterceptor(axios)
Note over Axios: global interceptor installed
App->>Axios: send HTTP request
Axios->>ReqInterceptor: outgoing request
ReqInterceptor->>ReqInterceptor: ensure/generate X-Request-ID
ReqInterceptor->>Server: request + X-Request-ID
Server-->>Axios: error response (+ X-Request-ID header)
Axios->>ErrHandler: error caught
ErrHandler->>ErrHandler: getRequestIdFromError(err)
ErrHandler->>AlertStore: setAlertDetails(..., requestId)
AlertStore->>Notification: notify with requestId
Notification->>Notification: render error + Request ID block
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| Filename | Overview |
|---|---|
| frontend/src/helpers/requestId.js | New helper module exporting the request-ID header constant, interceptor factory, and error extractor; fallback chain correctly uses ?? and lowercase for response headers vs original case for config headers |
| frontend/src/App.jsx | Registers global axios interceptor at module scope and conditionally renders a copyable Request ID in error notifications; interceptor ID is exported but never ejected (only matters for HMR dev flow, already noted in prior review) |
| frontend/src/hooks/useAxiosPrivate.js | Correctly registers the request-ID interceptor inside the same useEffect as the response interceptor and ejects both on cleanup, matching the existing pattern |
| frontend/src/hooks/useExceptionHandler.jsx | Threads requestId through all buildAlert return paths; getRequestIdFromError is called before the !err guard but optional chaining makes this safe |
| frontend/src/store/alert-store.js | Adds requestId: null to the default alert shape; setAlertDetails spreads caller-supplied details so requestId flows through correctly |
| frontend/src/index.css | Adds BEM-style CSS for the request-ID notification row; straightforward layout rules with no issues |
Sequence Diagram
sequenceDiagram
participant Browser
participant AxiosInterceptor as Axios Request Interceptor
participant Backend
participant ExceptionHandler as useExceptionHandler
participant AlertStore as alert-store
participant AppUI as App.jsx Notification
Browser->>AxiosInterceptor: outgoing request (no X-Request-ID)
AxiosInterceptor->>AxiosInterceptor: inject X-Request-ID: uuidv4()
AxiosInterceptor->>Backend: request with X-Request-ID header
Backend-->>Browser: response
alt HTTP error
Backend-->>Browser: error response
Browser->>ExceptionHandler: handleException(err)
ExceptionHandler->>ExceptionHandler: getRequestIdFromError(err)
ExceptionHandler->>AlertStore: buildAlert(..., requestId)
AlertStore->>AppUI: alertDetails with requestId
AppUI-->>Browser: notification with copyable Request ID
else Network or Canceled error
Browser->>ExceptionHandler: handleException(err)
ExceptionHandler->>ExceptionHandler: fallback to err.config.headers
ExceptionHandler->>AlertStore: buildAlert(..., requestId)
AlertStore->>AppUI: alertDetails with requestId
AppUI-->>Browser: notification with copyable Request ID
end
Reviews (3): Last reviewed commit: "Merge branch 'main' into UN-3444-impleme..." | Re-trigger Greptile
- Use nullish coalescing in `getRequestIdFromError` so an empty-string backend-echoed header isn't silently shadowed by the request-side header. - Drop the redundant mixed-case response-header lookup; browser/axios response headers are always lower-cased. - Export the global axios interceptor ID so HMR-friendly cleanup is possible (and the chain doesn't leak across module re-evals).
…rom-frontend-to-backend
Frontend Lint Report (Biome)✅ All checks passed! No linting or formatting issues found. |
|



Summary
X-Request-ID: <uuidv4>on every outbound API call (both on the globalaxiosdefault instance and onuseAxiosPrivateinstances). Django + Flask backend middleware already honor an incomingX-Request-ID, so backend logs now share the same correlation ID the frontend generated.useExceptionHandlerpulls the request ID out oferr.response.headers['x-request-id']with a fallback toerr.config.headers['X-Request-ID'](coversERR_NETWORK/ERR_CANCELEDpaths where there is no response).requestId, and the notification description now renders aRequest ID: <id>line with antd'sTypography.Text copyable(built-in copy icon) whenever an error alert has a request ID.Why
Support and on-call needed an easy way for users to share the correlation ID that ties a UI error back to backend/worker logs. Backend already understood
X-Request-IDbut the frontend was neither sending one nor surfacing it.Files changed
frontend/src/helpers/requestId.js(new) —attachRequestIdInterceptor,getRequestIdFromError,REQUEST_ID_HEADERconstant.frontend/src/App.jsx— registers interceptor on globalaxios; renders the copyable request ID inline in error notifications.frontend/src/hooks/useAxiosPrivate.js— registers + ejects the interceptor on the private axios instance.frontend/src/hooks/useExceptionHandler.jsx— threadsrequestIdthrough everybuildAlertreturn path.frontend/src/store/alert-store.js— addsrequestIdto the default alert shape.frontend/src/index.css—.notification-request-idBEM styling.Notes
response.headers['x-request-id']won't be readable in the browser unless the backend setsCORS_EXPOSE_HEADERS = ["X-Request-ID"]. The fallback toerr.config.headerskeeps the feature working regardless because the backend reuses whatever ID we send. Adding the expose header is a small follow-up if desired.Test plan
X-Request-IDis present on the outgoing request in the Network tab.Request ID: <uuid>with a working copy icon.