Skip to content

feat: add cache hit statuses to expr context#2643

Merged
SkArchon merged 7 commits intomainfrom
milinda/eng-9179-router-add-cache-metric-hits-to-the-expression-context
Mar 16, 2026
Merged

feat: add cache hit statuses to expr context#2643
SkArchon merged 7 commits intomainfrom
milinda/eng-9179-router-add-cache-metric-hits-to-the-expression-context

Conversation

@SkArchon
Copy link
Copy Markdown
Contributor

@SkArchon SkArchon commented Mar 12, 2026

This PR adds cache hit statuses to the expr context. Right not they are only available as router response headers, which cannot be added to access logs.

Summary by CodeRabbit

  • New Features

    • Expanded cache hit observability by enabling access to cache state for normalization, variable normalization, variable remapping, persisted operations, and query planning in logs and monitoring.
  • Tests

    • Added comprehensive test coverage for cache hit tracking across multiple operation stages, validating correct propagation into access logs.

Checklist

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Walkthrough

This PR extends GraphQL operation observability by introducing five new cache-hit indicator boolean fields to the expression context's Operation struct and propagating cache state from the prehandler and WebSocket layers into the expression context for telemetry and access log evaluation.

Changes

Cohort / File(s) Summary
Expression Context Schema
router/internal/expr/expr.go
Added five new boolean fields to Operation struct: NormalizationCacheHit, VariablesNormalizationCacheHit, VariablesRemappingCacheHit, PersistedOperationCacheHit, and PlanCacheHit with corresponding expr tags for expression evaluation.
Cache State Propagation
router/core/graphql_prehandler.go, router/core/websocket.go
Assigns cache hit flags from operation context to expressionContext.Request.Operation after respective cache checks (persisted operation, normalization, variables normalization, variables remapping, and planning stages).
Test Coverage
router-tests/structured_logging_test.go
Adds multiple subtests validating each cache-hit expression through sequential GraphQL requests, checking for cache misses followed by cache hits, and verifying proper propagation into access log context fields.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Title check ✅ Passed The title 'feat: add cache hit statuses to expr context' directly and clearly describes the main change—adding cache hit status fields to the expression context.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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)
📝 Coding Plan
  • Generate coding plan for human review comments

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 12, 2026

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-58645481f3c2ab25ea55080e2b64d510aae8dfc6

@github-actions
Copy link
Copy Markdown

Router-nonroot image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-a5bf7d3aaf2949144aca213eebdd38f36a61600d-nonroot

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.88%. Comparing base (36cda91) to head (2e756cb).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2643      +/-   ##
==========================================
+ Coverage   62.85%   62.88%   +0.02%     
==========================================
  Files         244      244              
  Lines       25831    25836       +5     
==========================================
+ Hits        16237    16246       +9     
+ Misses       8259     8255       -4     
  Partials     1335     1335              
Files with missing lines Coverage Δ
router/core/graphql_prehandler.go 84.47% <100.00%> (+0.11%) ⬆️
router/internal/expr/expr.go 95.74% <ø> (ø)

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

🧹 Nitpick comments (1)
router-tests/structured_logging_test.go (1)

2914-3130: Please add a websocket/subscription case for these new expressions.

These assertions only go through the HTTP path via MakeGraphQLRequest*. The PR also changes router/core/websocket.go, and that propagation path is separate enough that it deserves at least one subscription test here—especially for persistedOperationCacheHit and planCacheHit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router-tests/structured_logging_test.go` around lines 2914 - 3130, Add a
websocket/subscription test that mirrors the HTTP tests but uses the WS
subscription path so the new propagation in router/core/websocket.go is
exercised: create a new t.Run that calls the environment's websocket
subscription helper (e.g., xEnv.MakeGraphQLSubscription or
xEnv.MakeWebsocketSubscription equivalent), send a persisted operation
subscription (and a normal subscription for planCacheHit), then inspect
xEnv.Observer().FilterMessage("/graphql") context maps for
"persisted_operation_cache_hit" and "plan_cache_hit" (and/or the other cache
keys as desired) asserting first request is false (miss) and a subsequent
identical subscription is true (hit); reuse the same testenv.Run/testenv.Config
setup pattern and Observer assertions used in the existing HTTP tests so the
fields are validated over the WS path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@router/core/websocket.go`:
- Around line 909-925: The websocket expression context is only getting the
three normalization-related cache flags but not PersistedOperationCacheHit and
PlanCacheHit, causing subscriptions to see false even when caches hit; in the
same block where you assign
reqCtx.expressionContext.Request.Operation.NormalizationCacheHit,
VariablesNormalizationCacheHit and VariablesRemappingCacheHit, also set
reqCtx.expressionContext.Request.Operation.PersistedOperationCacheHit =
opContext.persistedOperationCacheHit and
reqCtx.expressionContext.Request.Operation.PlanCacheHit = opContext.planCacheHit
(these names are set earlier in parseAndPlan/operationKit and consulted by
executeSubscription), ensuring all five cache-hit flags mirror into the
websocket expr context.

---

Nitpick comments:
In `@router-tests/structured_logging_test.go`:
- Around line 2914-3130: Add a websocket/subscription test that mirrors the HTTP
tests but uses the WS subscription path so the new propagation in
router/core/websocket.go is exercised: create a new t.Run that calls the
environment's websocket subscription helper (e.g., xEnv.MakeGraphQLSubscription
or xEnv.MakeWebsocketSubscription equivalent), send a persisted operation
subscription (and a normal subscription for planCacheHit), then inspect
xEnv.Observer().FilterMessage("/graphql") context maps for
"persisted_operation_cache_hit" and "plan_cache_hit" (and/or the other cache
keys as desired) asserting first request is false (miss) and a subsequent
identical subscription is true (hit); reuse the same testenv.Run/testenv.Config
setup pattern and Observer assertions used in the existing HTTP tests so the
fields are validated over the WS path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 10300af6-3b57-47c1-8cd6-08a79beeee10

📥 Commits

Reviewing files that changed from the base of the PR and between 0f18fcd and 21cc5dc.

📒 Files selected for processing (4)
  • router-tests/structured_logging_test.go
  • router/core/graphql_prehandler.go
  • router/core/websocket.go
  • router/internal/expr/expr.go

Comment thread router/core/websocket.go Outdated
@SkArchon SkArchon marked this pull request as ready for review March 12, 2026 17:42
@SkArchon SkArchon requested review from a team as code owners March 15, 2026 16:54
@SkArchon SkArchon requested a review from Aenimus March 15, 2026 16:54
@SkArchon SkArchon merged commit 4e0213c into main Mar 16, 2026
102 checks passed
@SkArchon SkArchon deleted the milinda/eng-9179-router-add-cache-metric-hits-to-the-expression-context branch March 16, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants