Skip to content

feat(worker): correlate activity spans with Cloudflare colos #981 - #982

Merged
chrisdoc merged 3 commits into
mainfrom
fix/telemetry-cloudflare-colo
Aug 10, 2026
Merged

feat(worker): correlate activity spans with Cloudflare colos #981#982
chrisdoc merged 3 commits into
mainfrom
fix/telemetry-cloudflare-colo

Conversation

@chrisdoc

@chrisdoc chrisdoc commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Primary changes

  • Create Cloudflare-native custom spans around hosted Worker MCP activity.
  • Preserve the existing 10-character HMAC user pseudonym and add it to the activity span.
  • Read only the validated three-letter request.cf.colo; omit it for local/non-Cloudflare traffic.
  • Add privacy regression tests, TraceQL guidance, and privacy/data-dictionary documentation.

Reviewer walkthrough

  1. Derive the existing deterministic user pseudonym with Web Crypto and extract only Cloudflare's colo metadata.
  2. Enrich Worker MCP activity spans with user.hash and optional cloudflare.colo, keeping trace enrichment best effort.
  3. Cover Cloudflare and non-Cloudflare paths, ensure raw IPs/keys are never exported, and document the regional-proxy limitation/query.
  4. Run the Worker, unit, type, boundary, build, package, and performance validation lanes.

Correctness and invariants

  • Hosted Worker activity spans are enriched on a best-effort basis; tracing failures never affect MCP request handling.
  • user.hash remains the existing 10-character lowercase HMAC pseudonym derived from the API key; raw API keys, client IPs, and workout data are not exported.
  • cloudflare.colo is emitted only for a validated three-letter request.cf.colo; local and non-Cloudflare requests omit it.
  • Documentation treats the colo as a regional edge proxy rather than exact user geography and provides scoped TraceQL guidance.

Testing and QA

  • npm run check
  • npm run check:types
  • npm run check:boundaries
  • npm run test:unit
  • npm run test:worker
  • npm run test:worker-http
  • npm run test:pr
  • npm run test:performance
  • npm run worker:dry-run
  • npm run check:changeset

Summary by Sourcery

Correlate hosted Worker MCP activity spans with a pseudonymous user identifier and Cloudflare edge colo while preserving privacy guarantees.

New Features:

  • Attach a deterministic HMAC-based pseudonymous user hash and optional Cloudflare colo to hosted Worker MCP activity spans via Cloudflare tracing.

Enhancements:

  • Introduce worker telemetry helpers to derive the existing user hash and extract a validated Cloudflare colo from request metadata.
  • Wire the Worker handler and observer to pass telemetry context into span creation without affecting MCP behavior on failures.

Build:

  • Relax dependency-cruiser configuration to allow the workerd runtime module cloudflare:workers while still flagging unresolved package imports.

Documentation:

  • Update telemetry dashboard, privacy policy, and data dictionary documentation with guidance on user-hash and Cloudflare colo usage and privacy constraints.

Tests:

  • Add unit tests covering user-hash derivation, Cloudflare colo extraction, and span attribute behavior for Cloudflare and non-Cloudflare requests.

✨ PR Description

Purpose: Correlate Worker MCP activity spans with user pseudonyms and Cloudflare edge colos for regional telemetry analysis while maintaining privacy safeguards.

Main changes:

  • Implemented createWorkerUserHash and getCloudflareColo utilities to derive HMAC user pseudonyms and extract validated Cloudflare colo metadata from requests
  • Enhanced createWorkerToolObserver with tracing span creation via Cloudflare's startActiveSpan API, setting user/colo attributes with error isolation
  • Updated WorkerToolObserverOptions interface to accept injectable userHash, cloudflareColo, and tracing parameters for dependency injection and testing

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how

Summary by CodeRabbit

  • New Features
    • Added privacy-safe telemetry to hosted Worker activity, including pseudonymous user identifiers and Cloudflare edge location data.
    • Added tracing for worker operations with completion outcomes, while preserving normal behavior if tracing is unavailable.
  • Documentation
    • Updated privacy, telemetry dictionary, and dashboard guidance to clarify data usage, regional reporting, and restrictions on raw IP addresses and exact location data.
  • Bug Fixes
    • Improved handling of missing or invalid telemetry metadata without affecting request processing.

Resolves #981

@assert-app

assert-app Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review on Assert →

6 clusters identified

Merge candidate is ready!

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @chrisdoc, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@sourcery-ai

sourcery-ai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds Cloudflare Workers tracing integration to hosted Worker MCP activity spans, deriving a deterministic pseudonymous user hash and optional Cloudflare colo from requests, wiring them into span attributes in a privacy-safe, best-effort way, and documenting the new telemetry semantics and constraints.

Sequence diagram for Cloudflare tracing with user hash and colo on Worker MCP spans

sequenceDiagram
    actor Client
    participant CloudflareWorker as CloudflareWorker
    participant WorkerTelemetry as WorkerTelemetry
    participant WorkerObserver as WorkerObserver
    participant CloudflareTracing as CloudflareTracing

    Client->>CloudflareWorker: HTTP MCP request
    CloudflareWorker->>WorkerTelemetry: createWorkerUserHash(apiKey)
    WorkerTelemetry-->>CloudflareWorker: userHash
    CloudflareWorker->>WorkerTelemetry: getCloudflareColo(request)
    WorkerTelemetry-->>CloudflareWorker: cloudflareColo?

    CloudflareWorker->>WorkerObserver: createWorkerToolObserver({ userHash, cloudflareColo, tracing })
    CloudflareWorker->>WorkerObserver: start(invocation)
    WorkerObserver->>CloudflareTracing: startActiveSpan(spanName, callback)
    CloudflareTracing->>WorkerObserver: span
    WorkerObserver->>CloudflareTracing: span.setAttribute(mcp.span.category, kind)
    WorkerObserver->>CloudflareTracing: span.setAttribute(user.hash, userHash)
    WorkerObserver->>CloudflareTracing: span.setAttribute(cloudflare.colo, cloudflareColo)

    CloudflareWorker->>WorkerObserver: scope.run(operation)
    WorkerObserver->>CloudflareTracing: span.end() when finish(outcome)
Loading

File-Level Changes

Change Details Files
Enrich Worker MCP activity spans with Cloudflare tracing, pseudonymous user hashes, and optional colo metadata in a best-effort, privacy-safe manner.
  • Introduce WorkerTraceSpan/WorkerTracing interfaces and integrate Cloudflare tracing API into createWorkerToolObserver with safe span lifecycle handling.
  • Validate and forward userHash and cloudflareColo options into span attributes, guarding with strict regex patterns and ensuring tracing failures never affect MCP behavior.
  • Add tests to verify span creation, attribute setting for user hash and colo, and omission of colo for non-Cloudflare requests.
packages/worker/src/worker-observer.ts
packages/worker/src/worker-observer.test.ts
tests/cloudflare/cloudflare-workers.d.ts
tests/shims/cloudflare-workers.ts
Derive telemetry-safe user hash and Cloudflare colo from incoming Worker requests and plumb them into observer construction.
  • Add worker-telemetry utilities to compute a deterministic HMAC-based user hash with Web Crypto and extract a validated three-letter Cloudflare colo from request.cf.colo, ignoring invalid or missing metadata.
  • Wire createWorkerUserHash and getCloudflareColo into serveMcpRequest so each request constructs a Worker observer with userHash and cloudflareColo options.
  • Extend Worker dependency contracts to allow createObserver to receive WorkerToolObserverOptions and update tests to assert the propagated options.
packages/worker/src/worker-telemetry.ts
packages/worker/src/worker-telemetry.test.ts
packages/worker/src/worker.ts
packages/worker/src/worker.test.ts
Document and enforce telemetry and privacy guarantees around the new spans and Cloudflare integration.
  • Update telemetry dashboards, privacy policy, and telemetry data dictionary docs to describe user.hash and cloudflare.colo semantics, guidance for TraceQL queries, and explicit privacy constraints (no raw IPs, no identity reconstruction).
  • Tighten dependency-cruiser configuration to allow unresolved cloudflare:workers imports as runtime-provided, and add TypeScript declarations/shims for Cloudflare tracing in test and worker code.
  • Add a changeset entry describing the new Worker patch release behavior.
docs/telemetry-dashboards.md
docs/privacy-policy.md
docs/telemetry-data-dictionary.md
.dependency-cruiser.cjs
packages/worker/src/cloudflare-workers.d.ts
tests/cloudflare/cloudflare-workers.d.ts
tests/shims/cloudflare-workers.ts
.changeset/bright-colos-trace.md

Assessment against linked issues

Issue Objective Addressed Explanation
#981 Propagate Cloudflare colo and the existing pseudonymous user hash onto the same hosted Worker MCP activity spans, only when Cloudflare metadata is present, without affecting MCP behavior.
#981 Add tests ensuring Cloudflare-enriched requests include the colo and user hash on activity spans, non-Cloudflare requests omit the colo, and no raw IP addresses or sensitive data are persisted.
#981 Document that the Cloudflare colo is a regional edge location (not user geography), and provide TraceQL guidance to count distinct users by colo.

Possibly linked issues

  • #[telemetry] Propagate Cloudflare colo onto user-associated spans: PR implements Cloudflare colo and user hash propagation onto MCP activity spans, with tests and TraceQL docs, matching issue.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Cloudflare Worker preview

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

feat(worker): correlate activity spans with Cloudflare colos

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add Cloudflare-native activity spans enriched with user hash and optional colo.
• Derive deterministic 10-char HMAC pseudonym and validate request.cf.colo when present.
• Add privacy regression tests plus TraceQL and privacy/data-dictionary documentation.
Diagram

graph TD
  R["Incoming Request"] --> W["worker.ts handler"] --> T["worker-telemetry.ts"] --> O["worker-observer.ts"] --> CF{{"cloudflare:workers tracing"}} --> B["Tracing backend"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use OpenTelemetry JS API / baggage instead of Cloudflare tracing
  • ➕ Vendor-neutral attributes and better portability across runtimes
  • ➕ Potentially richer semantic conventions and tooling support
  • ➖ Not always available/supported in Workers runtime without additional wiring
  • ➖ More complexity and higher risk of affecting request execution if misconfigured
2. Emit only privacy-safe structured events (no spans)
  • ➕ Simpler runtime behavior; no dependency on Cloudflare tracing API
  • ➕ Avoids any span-enrichment failure modes entirely
  • ➖ Harder to correlate in distributed traces; weaker integration with tracing UI/TraceQL workflows
  • ➖ Less discoverable for operations teams relying on spans

Recommendation: The chosen approach (Cloudflare-native spans with best-effort enrichment + strict validation) fits the Worker runtime constraints and keeps telemetry failure-isolated. The added input validation ([0-9a-f]{10} for user.hash, [A-Z]{3} for cloudflare.colo) plus explicit privacy tests/doc updates make this a reasonable and low-risk way to enable regional correlation.

Files changed (14) +388 / -10

Enhancement (3) +171 / -5
worker-observer.tsCreate Cloudflare-native activity spans with safe attributes +98/-1

Create Cloudflare-native activity spans with safe attributes

• Integrates Cloudflare 'tracing.startActiveSpan' into the Worker tool observer to wrap MCP tool/prompt execution in an activity span. Adds strict validation for 'userHash' and 'cloudflareColo', best-effort attribute setting, and guaranteed span finishing without impacting MCP behavior on tracing failures.

packages/worker/src/worker-observer.ts

worker-telemetry.tsAdd Worker telemetry helpers for user hash and Cloudflare colo +58/-0

Add Worker telemetry helpers for user hash and Cloudflare colo

• Implements WebCrypto-based HMAC derivation of the existing short pseudonymous user hash and safe extraction of the Cloudflare colo from request metadata. Both enrichments are explicitly best-effort and return 'undefined' on invalid/missing inputs or runtime errors.

packages/worker/src/worker-telemetry.ts

worker.tsWire per-request telemetry context into observer creation +15/-4

Wire per-request telemetry context into observer creation

• Changes the Worker dependency injection shape so 'createObserver' receives per-request options. Computes 'userHash' from the validated API key and optionally includes 'cloudflareColo' from request metadata when constructing the tool observer.

packages/worker/src/worker.ts

Tests (5) +162 / -1
worker-observer.test.tsTest span attributes for user hash and optional colo +66/-1

Test span attributes for user hash and optional colo

• Introduces unit tests that inject a tracing double to verify span creation and attribute setting. Adds coverage to ensure colo is omitted for non-Cloudflare requests and that secrets like raw API keys are not leaked via attributes.

packages/worker/src/worker-observer.test.ts

worker-telemetry.test.tsAdd privacy regression tests for hash derivation and colo parsing +42/-0

Add privacy regression tests for hash derivation and colo parsing

• Verifies deterministic 10-character HMAC pseudonym generation matches existing expectations and is not derived for empty credentials. Ensures only valid 'request.cf.colo' values are returned and sensitive metadata like client IP is not surfaced.

packages/worker/src/worker-telemetry.test.ts

worker.test.tsAssert handler passes user hash and colo into observer creation +30/-0

Assert handler passes user hash and colo into observer creation

• Extends Worker integration tests to confirm the handler computes 'userHash' and reads 'request.cf.colo', then passes both into the observer factory per request.

packages/worker/src/worker.test.ts

cloudflare-workers.d.tsExtend test Cloudflare module typings with tracing API +12/-0

Extend test Cloudflare module typings with tracing API

• Updates the test-only 'cloudflare:workers' declaration to include 'tracing.startActiveSpan' and span attribute methods so Worker tests typecheck consistently.

tests/cloudflare/cloudflare-workers.d.ts

cloudflare-workers.tsAdd tracing shim for non-workerd test environments +12/-0

Add tracing shim for non-workerd test environments

• Implements a no-op 'tracing.startActiveSpan' shim that returns a span with 'setAttribute' and 'end', allowing unit/integration tests to run outside the Cloudflare runtime without conditional logic in production code.

tests/shims/cloudflare-workers.ts

Documentation (3) +31 / -3
privacy-policy.mdDocument pseudonymous user hash + colo in hosted telemetry +6/-2

Document pseudonymous user hash + colo in hosted telemetry

• Expands the privacy policy to describe the HMAC-based pseudonym and Cloudflare colo usage in hosted MCP activity spans. Explicitly reiterates that raw IP addresses and API keys are not collected in operational telemetry.

docs/privacy-policy.md

telemetry-dashboards.mdAdd TraceQL guidance for per-user/per-colo analysis +18/-0

Add TraceQL guidance for per-user/per-colo analysis

• Adds a hosted Worker regional activity section describing 'span.user.hash' and 'span.cloudflare.colo' semantics and limitations. Provides a scoped TraceQL metrics query and guidance to avoid storing per-user behavioral history.

docs/telemetry-dashboards.md

telemetry-data-dictionary.mdAdd 'user.hash' and 'cloudflare.colo' to telemetry dictionary +7/-1

Add 'user.hash' and 'cloudflare.colo' to telemetry dictionary

• Documents the new span attributes, their validation constraints, and privacy intent. Extends the "never send" list to include raw client IP addresses and exact location data.

docs/telemetry-data-dictionary.md

Other (3) +24 / -1
bright-colos-trace.mdAdd patch changeset for Worker span enrichment +5/-0

Add patch changeset for Worker span enrichment

• Introduces a changeset documenting the patch release for propagating 'user.hash' and 'cloudflare.colo' onto hosted Worker activity spans, including privacy-safe tests and dashboard guidance.

.changeset/bright-colos-trace.md

.dependency-cruiser.cjsAllow unresolved 'cloudflare:workers' runtime module +6/-1

Allow unresolved 'cloudflare:workers' runtime module

• Updates dependency-cruiser rules to ignore resolution failures for 'cloudflare:workers', which is provided by the workerd runtime rather than npm.

.dependency-cruiser.cjs

cloudflare-workers.d.tsDeclare Cloudflare tracing types for Worker runtime +13/-0

Declare Cloudflare tracing types for Worker runtime

• Adds TypeScript declarations for 'cloudflare:workers' tracing ('tracing.startActiveSpan' and span attribute APIs) so Worker code can compile with typed access to the runtime module.

packages/worker/src/cloudflare-workers.d.ts

@deepsource-io

deepsource-io Bot commented Aug 10, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in ac18809...5807ade on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Aug 10, 2026 6:50p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Unit Test Results

  1 files   78 suites   31s ⏱️
775 tests 775 ✅ 0 💤 0 ❌
782 runs  782 ✅ 0 💤 0 ❌

Results for commit 5807ade.

♻️ This comment has been updated with latest results.

@charliecreates charliecreates Bot changed the title feat(worker): correlate activity spans with Cloudflare colos feat(worker): correlate activity spans with Cloudflare colos #981 Aug 10, 2026
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.38462% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.84%. Comparing base (ac18809) to head (5807ade).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/worker/src/worker-observer.ts 90.32% 2 Missing and 1 partial ⚠️
packages/worker/src/worker-telemetry.ts 86.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #982      +/-   ##
==========================================
+ Coverage   73.60%   73.84%   +0.24%     
==========================================
  Files          90       92       +2     
  Lines        6058     6107      +49     
  Branches     1722     1733      +11     
==========================================
+ Hits         4459     4510      +51     
+ Misses       1019     1017       -2     
  Partials      580      580              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

};
const tracing: NonNullable<WorkerToolObserverOptions["tracing"]> = {
startActiveSpan<T>(
this: void,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

void is only valid as a return type or generic type argument


Disallows usage of void type outside of return types or generic type arguments. If void is used as return type, it shouldn’t be a part of intersection/union type with most other types.

Comment thread packages/worker/src/worker-observer.ts Outdated

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Gitar has auto-approved this PR (configure)

@gitar-bot gitar-bot Bot added the gitar-approved Added by Gitar label Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@chrisdoc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d86198d-4525-4c95-8c8a-e8aee68a740f

📥 Commits

Reviewing files that changed from the base of the PR and between 3ed66c2 and 5807ade.

📒 Files selected for processing (5)
  • docs/privacy-policy.md
  • docs/telemetry-dashboards.md
  • docs/telemetry-data-dictionary.md
  • packages/worker/src/worker-observer.test.ts
  • packages/worker/src/worker-observer.ts
📝 Walkthrough

Walkthrough

Hosted Worker requests now derive pseudonymous user hashes and Cloudflare colo values, pass them to MCP observers, and record them on activity spans. Tests, Cloudflare type shims, privacy documentation, dashboard guidance, and release metadata support the change.

Changes

Hosted Worker telemetry

Layer / File(s) Summary
Telemetry derivation and validation
packages/worker/src/worker-telemetry.ts, packages/worker/src/worker-telemetry.test.ts
Adds deterministic HMAC user hashes and validated Cloudflare colo extraction. Tests cover valid, missing, invalid, and failure cases.
Activity span instrumentation
packages/worker/src/worker-observer.ts, packages/worker/src/worker-observer.test.ts, tests/shims/cloudflare-workers.ts, tests/cloudflare/cloudflare-workers.d.ts, package.json, packages/worker/tsconfig.json
Adds injectable Cloudflare tracing, bounded span attributes, completion outcomes, failure isolation, and tracing test support.
Request-to-observer propagation
packages/worker/src/worker.ts, packages/worker/src/worker.test.ts
Passes the derived user hash and Cloudflare colo into the observer before MCP server construction.
Telemetry documentation and release support
docs/privacy-policy.md, docs/telemetry-data-dictionary.md, docs/telemetry-dashboards.md, .dependency-cruiser.cjs, .changeset/bright-colos-trace.md
Documents pseudonymous hashes, edge colos, TraceQL analysis, and exclusions for raw IP and exact location data. Adds dependency validation and a worker patch Changeset.

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

Sequence Diagram(s)

sequenceDiagram
  participant MCPRequest
  participant workerTelemetry
  participant WorkerObserver
  participant CloudflareTracing
  participant MCPOperation

  MCPRequest->>workerTelemetry: Derive user hash and colo
  MCPRequest->>WorkerObserver: Create observer with telemetry options
  WorkerObserver->>CloudflareTracing: Start active span
  CloudflareTracing-->>WorkerObserver: Return active span
  WorkerObserver->>MCPOperation: Execute operation
  WorkerObserver->>CloudflareTracing: Set attributes and completion outcome
  WorkerObserver->>CloudflareTracing: End span
Loading

Possibly related PRs

Suggested reviewers: gitstream-cm

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the worker telemetry change that correlates activity spans with Cloudflare colos.
Linked Issues check ✅ Passed The changes satisfy the linked issue objectives for colo propagation, pseudonymous user hashes, privacy safeguards, tests, and TraceQL documentation.
Out of Scope Changes check ✅ Passed The implementation, tests, configuration, dependency, and documentation changes directly support the linked telemetry objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/telemetry-cloudflare-colo

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/privacy-policy.md`:
- Around line 20-23: Update the privacy-policy section describing hosted MCP
activity spans to state that traces containing sanitized client metadata,
including span.user.hash and span.cloudflare.colo, are retained for 30 days and
accessible only to repository maintainers and the on-call operator, matching the
rule in telemetry-dashboards.md.

In `@docs/telemetry-dashboards.md`:
- Around line 33-38: Update the TraceQL filter in the documented scoped metrics
query to use nil-presence checks for both span.cloudflare.colo and
span.user.hash instead of empty-string comparisons, while preserving the
existing count_over_time grouping by colo and user hash.

In `@docs/telemetry-data-dictionary.md`:
- Around line 65-68: Clarify the metrics prohibition in the telemetry data
dictionary text around the API-key-derived identity statement so it explicitly
applies to emitted metric attributes or dimensions, not TraceQL metrics derived
from trace data. Preserve the existing allowance for span.user.hash in
hosted-worker traces and keep the wording consistent with the dashboard
guidance.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3acb9b25-f587-4450-988b-a4d4b1b0e141

📥 Commits

Reviewing files that changed from the base of the PR and between ac18809 and fc7843a.

📒 Files selected for processing (14)
  • .changeset/bright-colos-trace.md
  • .dependency-cruiser.cjs
  • docs/privacy-policy.md
  • docs/telemetry-dashboards.md
  • docs/telemetry-data-dictionary.md
  • packages/worker/src/cloudflare-workers.d.ts
  • packages/worker/src/worker-observer.test.ts
  • packages/worker/src/worker-observer.ts
  • packages/worker/src/worker-telemetry.test.ts
  • packages/worker/src/worker-telemetry.ts
  • packages/worker/src/worker.test.ts
  • packages/worker/src/worker.ts
  • tests/cloudflare/cloudflare-workers.d.ts
  • tests/shims/cloudflare-workers.ts

Comment thread docs/privacy-policy.md
Comment thread docs/telemetry-dashboards.md
Comment thread docs/telemetry-data-dictionary.md Outdated
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Aug 10, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Hard tracing named import ✓ Resolved 🐞 Bug ☼ Reliability
Description
worker-observer.ts uses a named ESM import for { tracing } from cloudflare:workers, making the
tracing export mandatory at module-link time. If cloudflare:workers exists but does not export
tracing in some environments, the Worker will fail to initialize before any best-effort fallback
logic can run.
Code

packages/worker/src/worker-observer.ts[1]

+import { tracing } from "cloudflare:workers";
Evidence
The code explicitly treats tracing as best-effort (swallowing errors when setting attributes and
ending spans), and even supports injecting a tracing implementation via options. However, the new
named import makes tracing a required export before any runtime checks can run.

packages/worker/src/worker-observer.ts[1-1]
packages/worker/src/worker-observer.ts[491-518]
packages/worker/src/worker-observer.ts[520-571]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`packages/worker/src/worker-observer.ts` imports `tracing` as a named export from `cloudflare:workers`. Named ESM imports are validated during module linking; if the module doesn’t export `tracing`, the Worker can fail to load, which contradicts the intent that tracing enrichment should be best-effort.
### Issue Context
The rest of the observer is carefully written to ensure trace enrichment failures never impact MCP behavior (try/catch around attribute setting and span ending, and injectable tracing for tests). The top-level named import is the one remaining “hard” dependency.
### Fix Focus Areas
- packages/worker/src/worker-observer.ts[1-2]
- packages/worker/src/worker-observer.ts[520-572]
### Suggested change
- Replace `import { tracing } from "cloudflare:workers";` with a namespace import, e.g.:
- `import * as cloudflareWorkers from "cloudflare:workers";`
- Resolve tracing as optional:
- `const workerTracing = options.tracing ?? cloudflareWorkers.tracing;`
- In `run()`, guard that `workerTracing?.startActiveSpan` exists; otherwise just `return operation()`.
This preserves the current behavior when tracing is available, while ensuring the Worker can still start when tracing isn’t provided by the runtime module.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can reply 'qodo' on any finding to push back, ask questions, or dig deeper

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread packages/worker/src/worker-observer.ts Outdated
@socket-security

socket-security Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​cloudflare/​workers-types@​5.20260801.11001009699100

View full report

@chrisdoc

Copy link
Copy Markdown
Owner Author

Addressed the review feedback in 5807ade:

  • Documented 30-day retention and maintainer/on-call access for user-hash/colo spans.
  • Updated TraceQL presence checks to use != nil.
  • Clarified emitted metrics versus TraceQL-derived metrics.
  • Namespaced prompt outcomes as mcp.prompt.outcome and added a regression test.
  • Removed the unnecessary this: void test parameter.
  • Made the Cloudflare tracing namespace import/fallback best-effort.

Validation passed: unit (782), Worker, Worker HTTP, type, formatting/lint, boundaries, dry-run, and pre-push checks.

@gitar-bot

gitar-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 resolved / 1 findings

Enriches hosted Worker MCP activity spans with pseudonymous user identifiers and validated Cloudflare edge colos, recording outcomes under mcp.tool.outcome while preserving privacy guarantees. No issues found.

Auto-approved: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria.

✅ 1 resolved
Quality: Prompt spans record outcome under mcp.tool.outcome key

📄 packages/worker/src/worker-observer.ts:508-509 📄 packages/worker/src/worker-observer.ts:554-556
In setSpanAttributes the span name attribute correctly branches on kind (mcp.prompt.name vs mcp.tool.name), but finishSpan always writes the outcome to the hardcoded mcp.tool.outcome key even when safe.kind === "prompt". This makes prompt-kind activity spans carry a tool-namespaced attribute, which is inconsistent with the name convention and can complicate TraceQL filtering by operation kind. Consider branching the outcome key the same way, e.g. span.setAttribute(outcomeKind === "prompt" ? "mcp.prompt.outcome" : "mcp.tool.outcome", outcome).

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@@ -1,3 +1,5 @@
import type { Span } from "@cloudflare/workers-types";
import * as cloudflareWorkers from "cloudflare:workers";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Explicitly import the specific method needed


Wildcard imports are easier to write, but make it harder to pick out the specific functions or objects from a dependency that are used in a file.

@chrisdoc
chrisdoc merged commit 4685bbb into main Aug 10, 2026
25 checks passed
@chrisdoc
chrisdoc deleted the fix/telemetry-cloudflare-colo branch August 10, 2026 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gitar-approved Added by Gitar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[telemetry] Propagate Cloudflare colo onto user-associated spans

1 participant