Skip to content

feat(render): add observability headers for lazy sections and pages#1029

Open
vibegui wants to merge 1 commit intomainfrom
feat/e2e-observability
Open

feat(render): add observability headers for lazy sections and pages#1029
vibegui wants to merge 1 commit intomainfrom
feat/e2e-observability

Conversation

@vibegui
Copy link
Copy Markdown
Contributor

@vibegui vibegui commented Jan 18, 2026

  • Add x-deco-section header with component type and title
  • Add x-deco-route header with matched route template
  • Add x-deco-page header with matched page block name

Summary by CodeRabbit

  • Chores
    • Enhanced internal observability and debugging capabilities by adding route and page tracking headers to response metadata.
    • Improved section identification and tracking for better diagnostic information during request processing.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add x-deco-section header with component type and title
- Add x-deco-route header with matched route template
- Add x-deco-page header with matched page block name
@vibegui vibegui requested a review from mcandeia January 18, 2026 19:23
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 18, 2026

📝 Walkthrough

Walkthrough

The pull request enhances observability in the rendering system by computing a sectionName identifier and exposing it alongside new debugging headers (x-deco-route, x-deco-page, x-deco-section). The core rendering behavior remains unchanged; these additions are purely informational.

Changes

Cohort / File(s) Summary
Observability Enhancements
runtime/features/render.tsx
Adds sectionName field to RenderResponse. Implements logic to compute section name by inspecting resolved section, extracting cleaned component type names, appending shortened titles, and falling back to block ID resolution for debugging purposes.
Observability Enhancements
runtime/middleware.ts
Introduces two new response headers: x-deco-route (from ctx.var.pathTemplate) and x-deco-page (from ctx.var.matchedPageBlock) to expose route and page matching information.
Observability Enhancements
runtime/routes/render.tsx
Consumes sectionName from deco.render return value and conditionally adds x-deco-section header to HTTP response when section name is available. Updates method signature of deco.render to include optional sectionName field.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Through the tangled routes and rendered streams so bright,
We leave our breadcrumb headers, shining in the light,
Each section gets a name, each page a proper trace,
Debugging gets easier—debuggers find their place!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding observability headers (x-deco-section, x-deco-route, x-deco-page) for lazy sections and pages across render, middleware, and routes files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

@github-actions
Copy link
Copy Markdown
Contributor

Tagging Options

Should a new tag be published when this PR is merged?

  • 👍 for Patch 1.133.4 update
  • 🎉 for Minor 1.134.0 update
  • 🚀 for Major 2.0.0 update

Copy link
Copy Markdown

@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: 1

🤖 Fix all issues with AI agents
In `@runtime/middleware.ts`:
- Around line 364-366: The code references ctx.var.matchedPageBlock but that
property isn't declared on the State types; add matchedPageBlock?: string to the
appropriate state interface (e.g., DecoState in types.ts, alongside
pathTemplate) so ctx.var.matchedPageBlock is typed; update any related
RequestState/DecoSiteState aliases if necessary to propagate the optional string
property through the state union.
🧹 Nitpick comments (2)
runtime/features/render.tsx (2)

150-193: Consider extracting the resolveChain index lookup to avoid duplication.

The resolveChain.findLastIndex((x) => x.type === "resolvable") logic is duplicated from lines 67-68. Consider extracting it to a variable earlier in the function and reusing it here.

Also, verify the prefix being stripped in the fallback (pages- on line 187). The AI summary mentions page- prefix, so confirm which is correct for your block IDs.

♻️ Optional refactor to reduce duplication
   let section;
+  let resolvableIndex = -1;

   if (resolveChain) {
-    const index = resolveChain.findLastIndex((x) => x.type === "resolvable");
-    section = resolvables[resolveChain[index].value];
+    resolvableIndex = resolveChain.findLastIndex((x) => x.type === "resolvable");
+    section = resolvables[resolveChain[resolvableIndex].value];
     // ... rest of loop
   }
   
   // Later in the fallback:
-  if (!sectionName && resolveChain) {
-    const index = resolveChain.findLastIndex((x) => x.type === "resolvable");
-    if (index >= 0) {
+  if (!sectionName && resolveChain && resolvableIndex >= 0) {
-      const blockId = resolveChain[index].value?.toString();
+      const blockId = resolveChain[resolvableIndex].value?.toString();

173-177: Title truncation produces 20 characters, not fewer.

The condition checks title.length > 20 but the substring produces 17 chars + 3 for ellipsis = 20 chars total. This is fine, just noting the math for clarity. The header value will include the component type plus this truncated title, so total length could be significant.

Consider whether a shorter limit might be more appropriate for HTTP headers, though this is unlikely to cause issues in practice.

Comment thread runtime/middleware.ts
Comment on lines +364 to +366
if (ctx?.var?.matchedPageBlock) {
newHeaders.set("x-deco-page", ctx.var.matchedPageBlock);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find State type definition and related interfaces
fd -t f "\.(ts|tsx)$" runtime/ | head -20

# Look for State type definitions
rg -n "type State|interface State|interface.*State|type.*State\s*=" runtime/ --type ts | head -30

Repository: deco-cx/deco

Length of output: 607


🏁 Script executed:

#!/bin/bash
# Search for matchedPageBlock usage/declaration
rg -n "matchedPageBlock" --type ts -C2

# Search for pathTemplate usage/declaration  
rg -n "pathTemplate" --type ts -C2 | head -40

Repository: deco-cx/deco

Length of output: 2212


🏁 Script executed:

#!/bin/bash
# Get the specific lines mentioned in the review (364-366 and 299-301)
sed -n '295,305p' runtime/middleware.ts
echo "---"
sed -n '357,370p' runtime/middleware.ts

Repository: deco-cx/deco

Length of output: 947


🏁 Script executed:

#!/bin/bash
# Get the State type definition from runtime/mod.ts starting at line 52
sed -n '52,150p' runtime/mod.ts

Repository: deco-cx/deco

Length of output: 2820


🏁 Script executed:

#!/bin/bash
# Search more carefully for matchedPageBlock - check all file types
rg -n "matchedPageBlock" . --type-list | head -10

# Also search without type restriction
rg -n "matchedPageBlock" . 2>/dev/null | head -20

Repository: deco-cx/deco

Length of output: 623


🏁 Script executed:

#!/bin/bash
# Search for where pathTemplate is set/defined in ctx.var
rg -n "pathTemplate\s*=" runtime/middleware.ts -B2 -A2 | head -30

# Search for where matchedPageBlock might be set
rg -n "matchedPageBlock\s*=" runtime/ -B2 -A2 | head -30

Repository: deco-cx/deco

Length of output: 38


🏁 Script executed:

#!/bin/bash
# Find RequestState definition
rg -n "interface RequestState|type RequestState" runtime/ --type ts -A 20

# Also search in the entire codebase
rg -n "RequestState" runtime/ --type ts | head -20

Repository: deco-cx/deco

Length of output: 388


🏁 Script executed:

#!/bin/bash
# Check middleware.ts imports to understand the context structure
head -50 runtime/middleware.ts | grep -E "^import|^export|interface|type"

Repository: deco-cx/deco

Length of output: 954


🏁 Script executed:

#!/bin/bash
# Search for where var properties might be set or typed
rg -n "ctx\.var\s*=" runtime/middleware.ts -B2 -A2 | head -40

# Look for type definitions of ctx.var
rg -n "var\s*:" runtime/middleware.ts -B2 -A2 | head -40

Repository: deco-cx/deco

Length of output: 38


🏁 Script executed:

#!/bin/bash
# Find and read the RequestState definition
rg -n "interface RequestState|type RequestState" blocks/utils.tsx -A 50 | head -80

Repository: deco-cx/deco

Length of output: 1262


🏁 Script executed:

#!/bin/bash
# Also check the full blocks/utils.tsx file structure
wc -l blocks/utils.tsx
head -100 blocks/utils.tsx

Repository: deco-cx/deco

Length of output: 2793


🏁 Script executed:

#!/bin/bash
# Look for the handler function signature to see what type ctx has
rg -n "export.*handler|function.*handler" runtime/middleware.ts -B5 -A10 | head -50

# Check for any ctx typing in middleware.ts
rg -n "ctx:" runtime/middleware.ts | head -20

Repository: deco-cx/deco

Length of output: 126


🏁 Script executed:

#!/bin/bash
# Search for where matchedPageBlock might be set in the codebase
rg -n "matchedPageBlock" . -B5 -A5 2>/dev/null

# Also check if this is a recent addition not yet in type definitions
git log --oneline -20 -- runtime/middleware.ts 2>/dev/null || echo "Git history not available"

Repository: deco-cx/deco

Length of output: 866


🏁 Script executed:

#!/bin/bash
# Check if ctx.var has type definitions somewhere in middleware or context handling
rg -n "\.var\s*\?" runtime/middleware.ts -B3 -A3 | head -60

Repository: deco-cx/deco

Length of output: 2015


🏁 Script executed:

#!/bin/bash
# Find DecoMiddlewareContext definition
rg -n "type DecoMiddlewareContext|interface DecoMiddlewareContext" runtime/ --type ts -A 30

Repository: deco-cx/deco

Length of output: 7413


🏁 Script executed:

#!/bin/bash
# Check what type ctx.var has - search for var property definitions
rg -n "var\s*:" runtime/ blocks/ --type ts | grep -E "var\s*:" | head -20

# Also check Hono context types since this appears to be Hono middleware
rg -n "HttpContext|Context<" runtime/middleware.ts --type ts -A5 | head -40

Repository: deco-cx/deco

Length of output: 849


🏁 Script executed:

#!/bin/bash
# Find DecoRouteState definition - this is what ctx.var should be
rg -n "type DecoRouteState|interface DecoRouteState" runtime/ --type ts -A 40

Repository: deco-cx/deco

Length of output: 2467


🏁 Script executed:

#!/bin/bash
# Double-check by searching for where pathTemplate and matchedPageBlock might be assigned
rg -n "\.var\.pathTemplate\s*=" runtime/ --type ts -B2 -A2

# Also search for where these fields are assigned to ctx or context
rg -n "pathTemplate|matchedPageBlock" runtime/ --type ts -B3 -A3 | grep -E "=|set|assign" -B3 -A3

Repository: deco-cx/deco

Length of output: 3932


🏁 Script executed:

#!/bin/bash
# Find DecoState definition to see if it has pathTemplate or matchedPageBlock
rg -n "type DecoState|interface DecoState" --type ts -A 30 | head -60

Repository: deco-cx/deco

Length of output: 1392


🏁 Script executed:

#!/bin/bash
# Check if State type extends something else that might have these properties
rg -n "DecoState<" runtime/mod.ts --type ts -B5 -A5

# Also verify what DecoSiteState contains
rg -n "DecoSiteState|interface DecoSiteState|type DecoSiteState" --type ts -A20 | head -50

Repository: deco-cx/deco

Length of output: 2525


Add matchedPageBlock property to the State type definition.

The code at lines 364-366 references ctx.var.matchedPageBlock, but this property is not declared in the State type. Unlike pathTemplate (which is defined in DecoState at types.ts:130), matchedPageBlock does not exist in DecoState, RequestState, or DecoSiteState. You need to add this property to the appropriate type definition so the code type-checks correctly.

🧰 Tools
🪛 GitHub Actions: ci

[error] 364-364: TypeScript error: Property 'matchedPageBlock' does not exist on type 'Readonly<ContextVariableMap & DecoSiteState & { deco: Deco; url: URL; correlationId?: string | undefined; ... 6 more ...; routes?: Route[] | undefined; } & RequestState>'.


[error] 365-365: TypeScript error: Property 'matchedPageBlock' does not exist on type 'Readonly<ContextVariableMap & DecoSiteState & { deco: Deco; url: URL; correlationId?: string | undefined; ... 6 more ...; routes?: Route[] | undefined; } & RequestState>'.

🤖 Prompt for AI Agents
In `@runtime/middleware.ts` around lines 364 - 366, The code references
ctx.var.matchedPageBlock but that property isn't declared on the State types;
add matchedPageBlock?: string to the appropriate state interface (e.g.,
DecoState in types.ts, alongside pathTemplate) so ctx.var.matchedPageBlock is
typed; update any related RequestState/DecoSiteState aliases if necessary to
propagate the optional string property through the state union.

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