You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add full semantic traces for HTTP calls and database operations in apps/api.
We do not want to depend on Cloudflare's tracing API directly across the codebase. This issue includes building a thin internal tracing wrapper that encapsulates cloudflare:workers tracing behind our own interface. The Cloudflare implementation is the default; a no-op implementation is used in tests.
This builds on the observability work in #387 (logs) and requires observability.traces.enabled = true for custom spans to be recorded.
Goals
Full visibility into HTTP + DB paths in the Workers dashboard waterfall
Decouple business code from Cloudflare's tracing API (swappable provider)
Consistent span naming and attributes across the codebase
Testable: spans can be mocked/asserted in unit tests
No sensitive data is ever recorded (see Security section)
Security — no sensitive data in logs or traces
Request/response data in this API includes auth tokens, session cookies, device identifiers, payment data, and signed audio URLs. Logs and traces are persisted on Cloudflare (Workers Logs: 7-day retention) — treat anything written to a span attribute or log as potentially stored. Rules:
Headers: never record full header sets. Only whitelisted safe headers (e.g. content-type, user-agent). NEVER: authorization, cookie, set-cookie, x-api-key, MercadoPago signature headers.
Bodies: never record full request/response bodies. Only explicit, selected fields; redact PII (emails, names, device ids) and payment data.
URLs: record the path only, never the query string (may contain tokens/codes).
Attribute naming guard: names matching token|secret|key|password|cookie|authorization|signature are never recorded.
Env secrets (DB connection strings, signing keys) never appear in attributes.
The existing middleware/logger.ts and lib/http-client.ts currently log full headers + bodies — span attributes added there must follow this policy. Sanitizing the existing logger is a separate follow-up.
Tasks
Create internal tracing wrapper (src/lib/tracing.ts): own Span / Tracer interface, Cloudflare implementation over cloudflare:workers (enterSpan, startActiveSpan, setAttribute), and a no-op implementation for tests
Enforce the sensitive-data policy in the wrapper: no full headers/bodies, path-only URLs, redacted fields only (see Security section)
Enable [observability.traces] (with head_sampling_rate) in wrangler.toml and wrangler.staging.toml
Wrap DB operations in src/db/index.ts with semantic spans (db:operation, attributes: table, op) — Neon is HTTP-based, so platform instrumentation alone shows generic fetch spans
Wrap outgoing HTTP calls in src/lib/http-client.ts (http:request, attributes: method, path, status — no headers, no query string, no bodies)
Wrap MercadoPago operations in src/payments/mercadopago.ts (mp:operation, attribute: payment id — no card/PII data)
Update/extend unit tests to assert span creation (mock tracer)
Add tests asserting recorded span attributes/logs never contain sensitive data (headers, query strings, bodies, secrets)
Verify spans appear in the Workers dashboard with the full request waterfall (deploy staging first)
Refactor note
Acceptable to refactor db/index.ts, http-client.ts, and mercadopago.ts as needed to thread the tracer through. Keep the wrapper as the ONLY module that imports cloudflare:workers tracing.
Description
Add full semantic traces for HTTP calls and database operations in
apps/api.We do not want to depend on Cloudflare's tracing API directly across the codebase. This issue includes building a thin internal tracing wrapper that encapsulates
cloudflare:workerstracing behind our own interface. The Cloudflare implementation is the default; a no-op implementation is used in tests.This builds on the observability work in #387 (logs) and requires
observability.traces.enabled = truefor custom spans to be recorded.Goals
Security — no sensitive data in logs or traces
Request/response data in this API includes auth tokens, session cookies, device identifiers, payment data, and signed audio URLs. Logs and traces are persisted on Cloudflare (Workers Logs: 7-day retention) — treat anything written to a span attribute or log as potentially stored. Rules:
content-type,user-agent). NEVER:authorization,cookie,set-cookie,x-api-key, MercadoPago signature headers.token|secret|key|password|cookie|authorization|signatureare never recorded.middleware/logger.tsandlib/http-client.tscurrently log full headers + bodies — span attributes added there must follow this policy. Sanitizing the existing logger is a separate follow-up.Tasks
src/lib/tracing.ts): ownSpan/Tracerinterface, Cloudflare implementation overcloudflare:workers(enterSpan,startActiveSpan,setAttribute), and a no-op implementation for tests[observability.traces](withhead_sampling_rate) inwrangler.tomlandwrangler.staging.tomlsrc/db/index.tswith semantic spans (db:operation, attributes: table, op) — Neon is HTTP-based, so platform instrumentation alone shows generic fetch spanssrc/lib/http-client.ts(http:request, attributes: method, path, status — no headers, no query string, no bodies)src/payments/mercadopago.ts(mp:operation, attribute: payment id — no card/PII data)Refactor note
Acceptable to refactor
db/index.ts,http-client.ts, andmercadopago.tsas needed to thread the tracer through. Keep the wrapper as the ONLY module that importscloudflare:workerstracing.