feat(fetch): add redactUrl option and sanitizeUrl helper - #12
Conversation
Allows callers to rewrite `url.full` before it is recorded as a span attribute, stripping secrets from query strings or paths while keeping the span. Unlike `ignore`, the request still goes through. `sanitizeUrl()` follows OTel URL semconv: sensitive query-parameter values and `user:pass@` credentials are replaced with `REDACTED`, with parameter keys preserved. A built-in default list covers common AWS/GCP signing parameters. On Node, requesting `redactUrl` forces the `globalThis.fetch` wrap instead of the native undici instrumentation, which has no hook to rewrite `url.full`.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (14)
Disabled knowledge base sources:
📝 WalkthroughWalkthroughAdds a ChangesredactUrl and sanitizeUrl feature
Sequence Diagram(s)sequenceDiagram
participant App
participant instrumentFetch
participant fetchAttributes
participant sanitizeUrl
participant Span
App->>instrumentFetch: fetch(url with token)
instrumentFetch->>fetchAttributes: fetchAttributes(name, url, options.redactUrl)
fetchAttributes->>sanitizeUrl: redactUrl(url)
sanitizeUrl-->>fetchAttributes: redacted url string
fetchAttributes->>Span: set url.full = redacted, server.address from original
instrumentFetch->>App: perform real fetch using original URL
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Summary
redactUrlfetch option.redactUrl: (url) => stringrewrites the value stored asurl.full, so you can strip tokens/secrets from the query string or path while keeping the span — unlikeignore, which drops the span entirely.server.address/server.portare still derived from the original URL, so an aggressive redactor can't break host resolution, and the real request still uses the original, unredacted URL — only telemetry is rewritten. Available oninstrumentFetch,createInstrumentedFetch, andsetupOtel({ instrumentFetch }).sanitizeUrl(url, options?)helper. Semantic-convention URL redaction: sensitive query-parameter values anduser:pass@credentials are replaced with the literalREDACTED, keeping the key (sig=REDACTED). Ships a built-in default list (X-Amz-Signature,X-Amz-Credential,X-Amz-Security-Token,sig,X-Goog-Signature); add your own viaparams, or disable the defaults withredactDefaults: false. Unparseable input — and input with nothing to redact — is returned unchanged (no query-string re-encoding). Exported alongside the newSanitizeUrlOptionstype.globalThis.fetchwrap whenredactUrlis set. The native undici instrumentation has no hook to rewriteurl.full, so requesting redaction declines the native path and falls back to the wrap — the same tradeoff already made for staticattributes.redactUrl/sanitizeUrland the keep-the-span-vs-ignoredistinction.Usage
Or per client, without touching global fetch:
Changes
src/sanitize.tssanitizeUrl()+SanitizeUrlOptions. Semconv query-param +user:pass@redaction with a default sensitive-param list, aparamsextension, and aredactDefaultstoggle; returns the input unchanged when nothing matches or the URL is unparseable.src/instrument-fetch.tsredactUrltoFetchSpanOptions;fetchAttributes()applies it toATTR_URL_FULLonly, leavingserver.*derived from the original URL.src/instrument-fetch-native.tsredactUrl(or staticattributes) is requested, forcing theglobalThis.fetchwrap that can rewriteurl.full.src/index.tssanitizeUrland theSanitizeUrlOptionstype.tests/sanitize.test.tssanitizeUrltests: listed param, semconv defaults,user:pass@, no-match passthrough, unparseable passthrough,redactDefaults: false.tests/instrument-fetch.test.tsredactUrlrewritesurl.fullbut keepsserver.address/server.portand the real request URL.tests/create-instrumented-fetch.test.tstests/instrument-fetch-native.test.tsundefined, registers nothing) whenredactUrlis set.README.md,docs/*redactUrl/sanitizeUrl; reframe the "secrets in URLs" guidance around redact-vs-ignore.Test plan
bun run test— 86 unit tests pass (9 new)bun run build— tsdown ESM (26.40 kB) + DTS (11.90 kB) build succeedsbun x ultracite check src tests— clean (20 files)bun run test:integration— real OTLP/HTTP round-trip; requires Docker, runs in CI🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by CodeRabbit
New Features
url.fullwhile removing sensitive values.Bug Fixes