Skip to content

fix(webapp): report full route path on Remix request spans#4309

Draft
carderne wants to merge 1 commit into
mainfrom
fix/remix-full-route-http-route
Draft

fix(webapp): report full route path on Remix request spans#4309
carderne wants to merge 1 commit into
mainfrom
fix/remix-full-route-http-route

Conversation

@carderne

Copy link
Copy Markdown
Collaborator

Summary

Traces from the webapp's Remix server can't always tell which route served a request. The @sentry/remix OpenTelemetry instrumentation sets a request span's name and http.route from only the matched leaf route's own path segment, so nested routes collapse to an ambiguous segment (e.g. :runParam) and several distinct pages share one opaque label.

Fix

Reconstruct the full matched path by joining every segment in the match chain, falling back to the leaf path when the chain is empty. Flat routes such as api/v1/tasks/:taskId/trigger are unchanged; nested routes now report their full URL pattern (e.g. orgs/:organizationSlug/projects/:projectParam/env/:envParam/runs/:runParam). Applied to both the CJS and ESM builds through the existing @sentry/remix pnpm patch.

The @sentry/remix OpenTelemetry instrumentation sets each request span's
name and http.route from only the matched leaf route's own path segment.
For nested routes that made distinct pages collapse to one ambiguous
segment (e.g. ":runParam"), so traces could not tell which route served
a request.

Reconstruct the full matched path by joining every segment in the match
chain, falling back to the leaf path. Flat routes such as
"api/v1/tasks/:taskId/trigger" are unchanged; nested routes now carry
their full URL pattern. Applied to both the CJS and ESM builds via the
existing pnpm patch.
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: d83bd21

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Remix instrumentation now combines all matched nested route segments when setting http.route and naming spans in both CJS and ESM bundles. Action instrumentation uses the original request instead of cloning it and no longer parses form data or attaches configured formData.* attributes to action spans.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description lacks the required template sections, including Closes #issue, checklist, testing details, changelog, and screenshots. Add the missing template sections, including Closes #issue, checklist items, testing steps, changelog, and screenshots or a note if none.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: reporting full route paths on Remix request spans.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/remix-full-route-http-route

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0a9bd2bc-fd0b-4950-a754-2ead92238d21

📥 Commits

Reviewing files that changed from the base of the PR and between d5f1696 and d83bd21.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • patches/@sentry__remix@9.46.0.patch
📜 Review details
⏰ Context from checks skipped due to timeout. (32)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 12)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 3)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 12)
  • GitHub Check: sdk-compat / Node.js 20.20 (warp-ubuntu-latest-x64-4x)
  • GitHub Check: e2e / 🧪 CLI v3 tests (warp-windows-latest-x64-8x - pnpm)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 12)
  • GitHub Check: e2e / 🧪 CLI v3 tests (warp-ubuntu-latest-x64-4x - npm)
  • GitHub Check: sdk-compat / Node.js 24.18 (warp-ubuntu-latest-x64-4x)
  • GitHub Check: sdk-compat / Node.js 22.23 (warp-ubuntu-latest-x64-4x)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: sdk-compat / Node.js 26.4 (warp-ubuntu-latest-x64-4x)
  • GitHub Check: e2e / 🧪 CLI v3 tests (warp-ubuntu-latest-x64-4x - pnpm)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (2, 3)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: packages / 🧪 Unit Tests: Packages (3, 3)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp
  • GitHub Check: typecheck / typecheck
  • GitHub Check: runops-guard / runops-guard
  • GitHub Check: code-quality / code-quality
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Build and publish previews

Comment on lines +13 to +17
+ const routePath =
+ (result || [])
+ .map((match) => match?.route?.path)
+ .filter((segment) => typeof segment === 'string' && segment.length > 0)
+ .join('/') || route?.path;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Normalize multiple slashes in joined route paths.

When a root route segment (e.g., '/') is joined with child segments (e.g., 'users'), the resulting path will contain double slashes (e.g., '//users'). Normalizing the joined string prevents incorrectly formatted span names.

  • patches/@sentry__remix@9.46.0.patch#L13-L17: Append .replace(/\/\/+/g, '/') to the joined string in the CJS build to safely clean up the path.
  • patches/@sentry__remix@9.46.0.patch#L68-L72: Append .replace(/\/\/+/g, '/') to the joined string in the ESM build to safely clean up the path.
💡 Proposed fixes

For the CJS build (patches/@sentry__remix@9.46.0.patch#L13-L17):

-        const routePath =
-          (result || [])
-            .map((match) => match?.route?.path)
-            .filter((segment) => typeof segment === 'string' && segment.length > 0)
-            .join('/') || route?.path;
+        const routePath =
+          (result || [])
+            .map((match) => match?.route?.path)
+            .filter((segment) => typeof segment === 'string' && segment.length > 0)
+            .join('/')
+            .replace(/\/\/+/g, '/') || route?.path;

For the ESM build (patches/@sentry__remix@9.46.0.patch#L68-L72):

-        const routePath =
-          (result || [])
-            .map((match) => match?.route?.path)
-            .filter((segment) => typeof segment === 'string' && segment.length > 0)
-            .join('/') || route?.path;
+        const routePath =
+          (result || [])
+            .map((match) => match?.route?.path)
+            .filter((segment) => typeof segment === 'string' && segment.length > 0)
+            .join('/')
+            .replace(/\/\/+/g, '/') || route?.path;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
+ const routePath =
+ (result || [])
+ .map((match) => match?.route?.path)
+ .filter((segment) => typeof segment === 'string' && segment.length > 0)
+ .join('/') || route?.path;
const routePath =
(result || [])
.map((match) => match?.route?.path)
.filter((segment) => typeof segment === 'string' && segment.length > 0)
.join('/')
.replace(/\/\/+/g, '/') || route?.path;
📍 Affects 1 file
  • patches/@sentry__remix@9.46.0.patch#L13-L17 (this comment)
  • patches/@sentry__remix@9.46.0.patch#L68-L72

Comment on lines +56 to +75
diff --git a/build/esm/vendor/instrumentation.js b/build/esm/vendor/instrumentation.js
index e33b84eecdffe3b10a5e50f13bafaf90775747c5..652a89c9194ea1d0bb0d748fb8f7f060ca2cf5ba 100644
--- a/build/esm/vendor/instrumentation.js
+++ b/build/esm/vendor/instrumentation.js
@@ -138,7 +138,14 @@ class RemixInstrumentation extends InstrumentationBase {

const route = (result || []).slice(-1)[0]?.route;

- const routePath = route?.path;
+ // Join every matched route segment so nested routes report their
+ // full URL pattern on http.route (and the span name), not just the
+ // leaf route's own path segment.
+ const routePath =
+ (result || [])
+ .map((match) => match?.route?.path)
+ .filter((segment) => typeof segment === 'string' && segment.length > 0)
+ .join('/') || route?.path;
if (span && routePath) {
span.setAttribute(SemanticAttributes.HTTP_ROUTE, routePath);
span.updateName(`remix.request ${routePath}`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Missing action processing changes for the ESM build.

The patch applies the nested-route joining logic to the ESM build but entirely omits the callRouteAction modifications that were successfully applied to the CJS build (lines 24-54). Consequently, ESM consumers will still experience request cloning and form-data parsing, which breaks the intended bundle consistency and could result in request-body-consumption bugs.

Please add the missing patch hunks targeting build/esm/vendor/instrumentation.js to remove params.request.clone() and the formData() span enrichment, matching the CJS changes.

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.

1 participant