Skip to content

Add loading indicator and Sentry metrics for page load#488

Merged
SvenVw merged 6 commits into
developmentfrom
fix-double-navigate-errors
Mar 3, 2026
Merged

Add loading indicator and Sentry metrics for page load#488
SvenVw merged 6 commits into
developmentfrom
fix-double-navigate-errors

Conversation

@SvenVw
Copy link
Copy Markdown
Collaborator

@SvenVw SvenVw commented Mar 3, 2026

Summary by CodeRabbit

  • New Features

    • Added a loading indicator with spinner and blur overlay that appears when page navigation exceeds 300ms.
    • Added telemetry to record when the indicator is shown and the duration of slow navigations.
  • Bug Fixes

    • Suppressed noisy error reports caused by aborted navigation streams in monitoring.

SvenVw added 2 commits March 3, 2026 09:51
…s this is caused by users navigating to another page while the page is still loading
@SvenVw SvenVw self-assigned this Mar 3, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Adds a navigation-progress UI that appears after 300ms of non-idle navigation, records Sentry metrics for show and duration, and adds Sentry ignore rules to suppress the "BodyStreamBuffer was aborted" error.

Changes

Cohort / File(s) Summary
Changesets
.changeset/heavy-steaks-mix.md, .changeset/shy-times-fly.md, .changeset/wide-animals-tan.md
Three changeset entries updating @nmi-agro/fdm-app (patch/minor); document the navigation progress behavior, logging, and error suppression.
Navigation Progress Component
fdm-app/app/components/custom/navigation-progress.tsx
New React component that starts a 300ms timer on navigation, shows a blurred backdrop + spinner when triggered, records show and duration metrics to Sentry, and uses framer-motion animations.
Layout Integration
fdm-app/app/root.tsx
Imports and mounts <NavigationProgress /> inside the app layout (after <Outlet />).
Sentry Initialization
fdm-app/app/entry.client.tsx, fdm-app/instrument.server.mjs
Adds ignoreErrors filter to Sentry init to suppress errors matching /BodyStreamBuffer was aborted/.

Sequence Diagram

sequenceDiagram
    actor User
    participant Router as Navigation Handler
    participant Progress as NavigationProgress
    participant Sentry as Sentry
    participant UI as Page UI

    User->>Router: start navigation
    Router->>Progress: navigation state != idle
    Progress->>Progress: start 300ms timer
    alt timer expires && still navigating
        Progress->>Sentry: increment navigation_progress.shown
        Progress->>UI: show blurred backdrop + spinner
    end
    Router->>Progress: navigation becomes idle
    Progress->>Progress: compute duration
    Progress->>Sentry: record navigation_progress.duration_ms
    Progress->>UI: hide backdrop + spinner
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

fdm-app, enhancement, bug, branch:development

Suggested reviewers

  • BoraIneviNMI

Poem

🐰 A hush as pages stretch and wait,
A spinner hums behind the gate,
Blur-soft veil and patient cheer,
Metrics whisper, "duration's here,"
Hop, click—back to the path we sate.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed Title check skipped as CodeRabbit has written the PR title.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-double-navigate-errors

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@SvenVw SvenVw mentioned this pull request Mar 3, 2026
@coderabbitai coderabbitai Bot changed the title @coderabbitai Add loading indicator and Sentry metrics for page load Mar 3, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.changeset/heavy-steaks-mix.md:
- Line 5: The release note sentence is a run-on and needs punctuation and a
slight reword for clarity; replace the current sentence with a concise version
such as: "If a page load takes longer than 300ms, log this to Sentry including
the total duration to help identify potential slow pages." Update the sentence
in the release note content to include the comma after the conditional and end
with a period.

In @.changeset/shy-times-fly.md:
- Line 5: Update the changelog sentence text to use hyphenation and clearer
phrasing: replace "In case a page load takes longer than 300ms show a loading
spinner and blur the page to prevent double clicking the navigation action" with
a polished version such as "If a page load takes longer than 300 ms, show a
loading spinner and blur the page to prevent double‑clicking navigation
actions." Ensure you add the comma after the time clause, use a non‑breaking
space or space before "ms" as your style guide prefers, and hyphenate
"double‑clicking" and pluralize "actions" for clarity.

In @.changeset/wide-animals-tan.md:
- Line 5: Update the release note entry that currently reads 'BodyStreambuffer
was aborted' to exactly match the runtime error string/casing used by the code
(inspect where the error is thrown or the error.name/message in the codebase and
copy it verbatim) so Sentry filters can correlate correctly; replace the typo in
the .changeset entry with that exact error text.

In `@fdm-app/app/components/custom/navigation-progress.tsx`:
- Around line 19-43: The effect currently sets startTimeRef inside the 300ms
timer and includes show in deps which lets the effect re-arm when show flips;
instead, on transition to non-idle set startTimeRef.current = Date.now()
immediately and only schedule the 300ms timer to call setShow(true) (store the
timer id and clear it on cleanup), and when state goes back to "idle" compute
duration from startTimeRef (if non-null), emit the Sentry metric, reset
startTimeRef to null and setShow(false); finally remove show from the effect
dependency array so the effect only reacts to state changes (update the
useEffect that references startTimeRef, setShow and timer accordingly).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50c1f90 and 16e64ad.

📒 Files selected for processing (7)
  • .changeset/heavy-steaks-mix.md
  • .changeset/shy-times-fly.md
  • .changeset/wide-animals-tan.md
  • fdm-app/app/components/custom/navigation-progress.tsx
  • fdm-app/app/entry.client.tsx
  • fdm-app/app/root.tsx
  • fdm-app/instrument.server.mjs

Comment thread .changeset/heavy-steaks-mix.md Outdated
Comment thread .changeset/shy-times-fly.md Outdated
Comment thread .changeset/wide-animals-tan.md Outdated
Comment thread fdm-app/app/components/custom/navigation-progress.tsx
@SvenVw SvenVw requested a review from BoraIneviNMI March 3, 2026 09:52
@SvenVw
Copy link
Copy Markdown
Collaborator Author

SvenVw commented Mar 3, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
fdm-app/app/components/custom/navigation-progress.tsx (1)

19-45: ⚠️ Potential issue | 🟠 Major

Prevent duplicate navigation_progress.shown metrics during a single navigation.

On Line 45, show in the dependency array causes the effect to re-run after setShow(true), which can arm another timer and emit an extra navigation_progress.shown while still non-idle.

🛠️ Proposed fix
 export function NavigationProgress() {
     const { state } = useNavigation()
     const [show, setShow] = useState(false)
     const startTimeRef = useRef<number | null>(null)
+    const shownRef = useRef(false)

     // Show after 300ms — emit a count metric when it appears
     useEffect(() => {
         if (state !== "idle") {
             if (startTimeRef.current === null) {
                 startTimeRef.current = Date.now()
             }
+            if (shownRef.current) {
+                return
+            }
             const timer = setTimeout(() => {
+                shownRef.current = true
                 setShow(true)
                 if (clientConfig.analytics.sentry) {
                     Sentry.metrics.count("navigation_progress.shown", 1)
                 }
             }, 300)
             return () => clearTimeout(timer)
         }

         // Navigation finished — emit duration metric and hide
-        if (show && startTimeRef.current !== null) {
+        if (shownRef.current && startTimeRef.current !== null) {
             const duration = Date.now() - startTimeRef.current
             if (clientConfig.analytics.sentry) {
                 Sentry.metrics.distribution(
                     "navigation_progress.duration_ms",
                     duration,
                 )
             }
         }
         setShow(false)
+        shownRef.current = false
         startTimeRef.current = null
-    }, [state, show])
+    }, [state])
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fdm-app/app/components/custom/navigation-progress.tsx` around lines 19 - 45,
The effect is re-running when setShow(true) updates show, causing duplicate
navigation_progress.shown metrics; update the useEffect so it only depends on
state (remove show from the dependency array) and add a guard before arming the
timer that checks both startTimeRef.current === null and !show (so you only
create a timer and call Sentry.metrics.count once per navigation), keeping the
existing cleanup (clearTimeout) and the end-of-navigation logic that emits
duration and resets startTimeRef and show.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@fdm-app/app/components/custom/navigation-progress.tsx`:
- Around line 19-45: The effect is re-running when setShow(true) updates show,
causing duplicate navigation_progress.shown metrics; update the useEffect so it
only depends on state (remove show from the dependency array) and add a guard
before arming the timer that checks both startTimeRef.current === null and !show
(so you only create a timer and call Sentry.metrics.count once per navigation),
keeping the existing cleanup (clearTimeout) and the end-of-navigation logic that
emits duration and resets startTimeRef and show.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16e64ad and b5899ba.

📒 Files selected for processing (4)
  • .changeset/heavy-steaks-mix.md
  • .changeset/shy-times-fly.md
  • .changeset/wide-animals-tan.md
  • fdm-app/app/components/custom/navigation-progress.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • .changeset/shy-times-fly.md
  • .changeset/heavy-steaks-mix.md

Copy link
Copy Markdown
Collaborator

@BoraIneviNMI BoraIneviNMI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I see the spinner rather often, which might mean that there will be a lot of performance metric warnings; however, 300ms is also a load time that is reasonable to worry about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants