Skip to content

✨ feat: propagate canonical request IDs through capture - #307

Merged
yeazelm merged 3 commits into
mainfrom
request-id-correlation/tapes
Aug 13, 2026
Merged

✨ feat: propagate canonical request IDs through capture#307
yeazelm merged 3 commits into
mainfrom
request-id-correlation/tapes

Conversation

@yeazelm

@yeazelm yeazelm commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Preserve canonical request IDs through consolidated ext-proc capture and distinguish missing-header fallbacks.
  • Install early Tapes API middleware that validates or generates the request ID and exposes it on the response and request context.
  • Carry bounded request_id and provider upstream_request_id metadata independently across asynchronous ingest and worker execution.
  • Keep both identifiers out of Prometheus labels and Loki stream labels.

How it works

The API establishes request-scoped correlation before handlers run. Ingest copies the Paper and provider identifiers into bounded job metadata, and workers restore both fields into their context and structured logger without allowing the provider ID to replace the Paper ID.

Test plan

  • Contract fixture parity
  • Full consolidated ext-proc suite
  • Ext-proc image build
  • Full E2E suite
  • Cross-platform binary build
  • Focused API, logger, ingest, and worker correlation suites

Fixes PCC-1177

@linear-code

linear-code Bot commented Aug 13, 2026

Copy link
Copy Markdown

PCC-1177

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds request-correlation middleware to the API and propagates distinct Paper and provider request IDs through ingest and asynchronous worker execution.

  • Validates or generates API request IDs and adds them to response headers, contexts, and structured logs.
  • Copies bounded correlation metadata into worker jobs and restores it for storage calls and worker diagnostics.
  • Persists both identifiers as raw-turn metadata while excluding them from metric labels.

Confidence Score: 4/5

The request-ID validation should be corrected before merging because parseable non-v4 UUIDs are currently returned as canonical identifiers.

The new middleware promises and tests for canonical UUIDv4 request IDs, but its implementation preserves any representation or UUID version accepted by uuid.Parse.

Files Needing Attention: api/request_id_middleware.go

Important Files Changed

Filename Overview
api/request_id_middleware.go Adds outermost request-ID middleware, but permissive UUID parsing does not enforce its asserted canonical UUIDv4 contract.
ingest/ingest.go Separately bounds Paper and provider identifiers before carrying them into asynchronous worker metadata.
pkg/logger/request.go Adds context accessors and structured logger construction that keep canonical and provider-issued IDs distinct.
proxy/worker/pool.go Restores correlation metadata in worker contexts and includes it in worker logs and raw-turn metadata.

Sequence Diagram

sequenceDiagram
  participant Client
  participant API
  participant ExtProc
  participant Ingest
  participant Worker
  participant Storage
  Client->>API: Request with optional X-Request-Id
  API->>API: Validate or generate request_id
  API-->>Client: X-Request-Id
  ExtProc->>Ingest: Turn with request_id and upstream_request_id
  Ingest->>Ingest: Bound worker correlation fields
  Ingest->>Worker: Enqueue job metadata
  Worker->>Worker: Restore context and scoped logger
  Worker->>Storage: Correlated storage operations
Loading
Prompt To Fix All With AI
### Issue 1
api/request_id_middleware.go:32-39
**Noncanonical UUIDs pass validation**

When a caller supplies a parseable UUID that is not a canonical hyphenated UUIDv4, `canonicalRequestID` preserves it in the response header, request context, and logs, causing downstream correlation to receive an identifier outside the middleware's asserted UUIDv4 format.

```suggestion
func canonicalRequestID(candidate string) string {
	if len(candidate) <= maxRequestIDTextBytes {
		if parsed, err := uuid.Parse(candidate); err == nil &&
			parsed.Version() == uuid.Version(4) && parsed.String() == candidate {
			return candidate
		}
	}
	return uuid.NewString()
}
```

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "✨ feat(ingest): preserve request IDs acr..." | Re-trigger Greptile

Comment on lines +32 to +39
func canonicalRequestID(candidate string) string {
if len(candidate) <= maxRequestIDTextBytes {
if _, err := uuid.Parse(candidate); err == nil {
return candidate
}
}
return uuid.NewString()
}

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.

P1 Noncanonical UUIDs pass validation

When a caller supplies a parseable UUID that is not a canonical hyphenated UUIDv4, canonicalRequestID preserves it in the response header, request context, and logs, causing downstream correlation to receive an identifier outside the middleware's asserted UUIDv4 format.

Suggested change
func canonicalRequestID(candidate string) string {
if len(candidate) <= maxRequestIDTextBytes {
if _, err := uuid.Parse(candidate); err == nil {
return candidate
}
}
return uuid.NewString()
}
func canonicalRequestID(candidate string) string {
if len(candidate) <= maxRequestIDTextBytes {
if parsed, err := uuid.Parse(candidate); err == nil &&
parsed.Version() == uuid.Version(4) && parsed.String() == candidate {
return candidate
}
}
return uuid.NewString()
}

Knowledge Base Used: API server (api/)

Prompt To Fix With AI
This is a comment left during a code review.
Path: api/request_id_middleware.go
Line: 32-39

Comment:
**Noncanonical UUIDs pass validation**

When a caller supplies a parseable UUID that is not a canonical hyphenated UUIDv4, `canonicalRequestID` preserves it in the response header, request context, and logs, causing downstream correlation to receive an identifier outside the middleware's asserted UUIDv4 format.

```suggestion
func canonicalRequestID(candidate string) string {
	if len(candidate) <= maxRequestIDTextBytes {
		if parsed, err := uuid.Parse(candidate); err == nil &&
			parsed.Version() == uuid.Version(4) && parsed.String() == candidate {
			return candidate
		}
	}
	return uuid.NewString()
}
```

**Knowledge Base Used:** [API server (api/)](https://app.greptile.com/paper-compute/-/custom-context/knowledge-base/papercomputeco/tapes/-/docs/api-server.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@yeazelm
yeazelm force-pushed the request-id-correlation/tapes branch from 21d1591 to 1a99cba Compare August 13, 2026 21:01
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploying docs-tapes-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: d1f525e
Status:🚫  Build failed.

View logs

@yeazelm
yeazelm force-pushed the request-id-correlation/tapes branch from 1a99cba to d1f525e Compare August 13, 2026 21:49
@yeazelm
yeazelm merged commit 39a74b8 into main Aug 13, 2026
25 of 26 checks passed
@yeazelm
yeazelm deleted the request-id-correlation/tapes branch August 13, 2026 22:31
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