Skip to content

fix(server): RPC spans join the client's trace - #67

Merged
yordis merged 1 commit into
mainfrom
yordis/fix-rpc-client-trace-parent
Sep 28, 2026
Merged

yordis merged 1 commit into
mainfrom
yordis/fix-rpc-client-trace-parent

Conversation

@yordis

@yordis yordis commented Sep 28, 2026 •

Copy link
Copy Markdown
Member
  • Server RPC spans ignored the trace context the client sends with each request, so every call nested under the long-lived WebSocket connection span instead of the client action that caused it.
  • That produced one giant trace per connection, and the web or desktop side of a request never appeared in the same trace as its server work.
  • Diagnostics RPCs keep their inner work untraced, and now cost one server span per call.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Improvements
    • RPC traces now consistently connect client calls, server processing, and handler work for both unary and streaming requests.
    • Traces include RPC context and aggregate information for unary calls, making request paths clearer in observability tools.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@cursor

cursor Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

PR Summary

Low Risk
Observability-only change to span parenting and attributes; no auth, data, or RPC behavior changes beyond trace shape.

Overview
RPC server spans now follow the client trace instead of nesting every call under the long-lived WebSocket connection.

The WebSocket RPC server is switched from disableTracing: true to shared rpcServerTracingOptions (ws.rpc prefix, transport/system attributes) so Effect RPC opens one server span per request parented to the client span carried on the wire. The observeRpc* helpers no longer create duplicate ws.rpc.* spans with withSpan; they annotate the RpcServer’s current span (rpc.method, rpc.aggregate, etc.) while metrics and the diagnostics-RPC opt-out stay the same.

Tests now drive a mini RpcClient/RpcServer loop and assert trace linkage: shared trace id, server span parent = client span, handler children parent = server span (unary and streamed).

Reviewed by Cursor Bugbot for commit d8b1157. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.5 KiB 13.5 KiB +16 B (+0.1%) 15.1 KiB ✅
Codex Thread snapshot wire 7.1 KiB 7.1 KiB +7 B (+0.1%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.4 KiB 6.4 KiB +9 B (+0.1%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 56.2 KiB 56.2 KiB 0 B (0.0%) 66.4 KiB ✅
Codex Live turn messages 9 9 0 (0.0%) 21 ✅
Claude Total thread wire 13.5 KiB 13.5 KiB +30 B (+0.2%) 15.1 KiB ✅
Claude Thread snapshot wire 7.1 KiB 7.1 KiB −1 B (−0.0%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.4 KiB 6.4 KiB +31 B (+0.5%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 57.0 KiB 57.0 KiB +44 B (+0.1%) 66.4 KiB ✅
Claude Live turn messages 8 9 +1 (+12.5%) 21 ✅

Baseline: 85d6c46 · PR result: d8b1157 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 114.0 KiB
  • Claude decoded thread snapshot: 114.7 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@coderabbitai

coderabbitai Bot commented Sep 28, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: TrogonStack/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: f8b04917-a50b-4ccd-9194-f210d9a3d332

📥 Commits

Reviewing files that changed from the base of the PR and between 85d6c46 and d8b1157.

📒 Files selected for processing (3)
  • apps/server/src/observability/RpcInstrumentation.test.ts
  • apps/server/src/observability/RpcInstrumentation.ts
  • apps/server/src/ws.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The WebSocket RPC server now uses exported tracing options. Trace-enabled unary and streamed RPC methods annotate the current span. Tests check trace propagation and span parentage across client, server, and handler calls.

Changes

WebSocket RPC tracing

Layer / File(s) Summary
Tracing options and span annotation
apps/server/src/observability/RpcInstrumentation.ts
Exports rpcServerTracingOptions with the ws.rpc span prefix and WebSocket/effect-RPC attributes. Trace-enabled unary and stream methods annotate the current span instead of creating method-specific spans. RPC method attributes no longer include the removed default attributes.
Server integration and trace validation
apps/server/src/ws.ts, apps/server/src/observability/RpcInstrumentation.test.ts
The WebSocket RPC server uses rpcServerTracingOptions. End-to-end tests check trace IDs, parent spans, RPC attributes, and handler child spans for unary and streamed calls.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant RPCClient
  participant WebSocketRPCServer
  participant RPCHandler
  RPCClient->>WebSocketRPCServer: Invoke unary or streamed RPC
  WebSocketRPCServer->>RPCHandler: Run method with server span
  RPCHandler->>RPCHandler: Create child span
Loading

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to d8b11

No actionable issue is established, so the change is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to d8b11

Authenticated clients can now influence the trace identity of server RPC work. Existing authentication and RPC scope checks remain in place, but the limits on trace export and behavior during interrupted or concurrent calls are not established.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — An authenticated WebSocket client can influence the trace identity associated with its server RPC work. The inspected code does not establish effects beyond tracing or determine the exporter’s exposure.

Trust Boundaries and Controls

  • observed — Client trace context crosses into server span parentage, while WebSocket authentication and per-method scope checks remain on the inspected request path.

Resilience and Maintainability Implications

  • inferred — Per-request span isolation and cleanup on interruption remain unverified because the observed test covers successful sequential calls and the inspected production helpers delegate span lifecycle to RpcServer.

Hardening Proposals

  • proposed — Verify how remote sampling flags, baggage, and trace identity affect server export, and check span isolation and termination across concurrent and interrupted requests before relying on these traces for security-sensitive correlation.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: server RPC spans now join the client trace.
Description check ✅ Passed The description explains the tracing problem and the intended behavior, including the diagnostics RPC behavior. It omits the template headings and checklist, but the core change and rationale are pres…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
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 docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@yordis
yordis merged commit f5cb3b4 into main Sep 28, 2026
22 of 23 checks passed
@yordis
yordis deleted the yordis/fix-rpc-client-trace-parent branch September 28, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant