feat(httptrace): add query string parameter allowlist via DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST#4562
Conversation
|
✅ Tests 🎉 All green!❄️ No new flaky tests detected 🎯 Code Coverage (details) 🔗 Commit SHA: f0b4f60 | Docs | Datadog PR Page | Was this helpful? React with 👍/👎 or give us feedback! |
Codecov Report❌ Patch coverage is
Additional details and impacted files
🚀 New features to boost your workflow:
|
BenchmarksBenchmark execution time: 2026-04-08 16:23:30 Comparing candidate commit f0b4f60 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 215 metrics, 9 unstable metrics.
|
|
Hey @genesor |
Hi @hsiwikxperi I was OOO most of last week. I will pick it up and have it included in the next release of the tracer 👍 |
May I ask when you anticipate the next release? |
3cce1cc to
112a1e9
Compare
We've just release the Another question, this modification applies to both client and server queries. Is that okay for you ? If not I'd need to introduce two new settings (one for client and one for server, taking precedence over the global one) WDYT ? |
|
Hey @genesor, |
|
Hi @hsiwikxperi Having "per client" allowlist require some more plumbing, especially with the programmatic option. The allowlist is consumed deep in I will explore options to find a nice way to make it happen. In the meantime would it be okay for you to have three env var:
|
aa29f92 to
e7b72a8
Compare
|
Sure, for now it should be sufficient, however, I would keep in mind configuration per |
…TP_URL_QUERY_STRING_ALLOWLIST
…orted configurations
e7b72a8 to
54782a1
Compare
… allowlist configs
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6ad818387
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Provided that CPU overhead is the origin of this PR, could we have a benchmark comparing the new implementation against the previous?
There was a problem hiding this comment.
I've added a benchmark in b1ee83a
BenchmarkURLFromRequest
BenchmarkURLFromRequest/regex/few_params
BenchmarkURLFromRequest/regex/few_params-16 156728 7656 ns/op 186 B/op 6 allocs/op
BenchmarkURLFromRequest/allowlist/few_params
BenchmarkURLFromRequest/allowlist/few_params-16 10313593 117.2 ns/op 72 B/op 3 allocs/op
BenchmarkURLFromRequest/regex/many_params
BenchmarkURLFromRequest/regex/many_params-16 50014 24293 ns/op 447 B/op 7 allocs/op
BenchmarkURLFromRequest/allowlist/many_params
BenchmarkURLFromRequest/allowlist/many_params-16 5144888 238.5 ns/op 120 B/op 4 allocs/op
BenchmarkURLFromRequest/regex/really_long_1
BenchmarkURLFromRequest/regex/really_long_1-16 3770 316669 ns/op 4675 B/op 5 allocs/op
BenchmarkURLFromRequest/allowlist/really_long_1
BenchmarkURLFromRequest/allowlist/really_long_1-16 3190782 372.1 ns/op 216 B/op 5 allocs/op
BenchmarkURLFromRequest/regex/really_long_2
BenchmarkURLFromRequest/regex/really_long_2-16 3834 311909 ns/op 4418 B/op 5 allocs/op
BenchmarkURLFromRequest/allowlist/really_long_2
BenchmarkURLFromRequest/allowlist/really_long_2-16 3284832 373.2 ns/op 216 B/op 5 allocs/op
PASS
ok github.com/DataDog/dd-trace-go/v2/instrumentation/httptrace 10.320s
There was a problem hiding this comment.
@rarguelloF I ran BenchmarkURLFromRequest on main as asked. (regex
obfuscation only, current behavior)
main :
BenchmarkURLFromRequest
BenchmarkURLFromRequest/regex/few_params
BenchmarkURLFromRequest/regex/few_params-16 122654 9799 ns/op 185 B/op 6 allocs/op
BenchmarkURLFromRequest/regex/many_params
BenchmarkURLFromRequest/regex/many_params-16 17601 88960 ns/op 447 B/op 7 allocs/op
BenchmarkURLFromRequest/regex/really_long_1
BenchmarkURLFromRequest/regex/really_long_1-16 2037 753900 ns/op 4576 B/op 5 allocs/op
BenchmarkURLFromRequest/regex/really_long_2
BenchmarkURLFromRequest/regex/really_long_2-16 3505 331900 ns/op 4316 B/op 5 allocs/op
PASS
ok github.com/DataDog/dd-trace-go/v2/instrumentation/httptrace 63.928s
new:
BenchmarkURLFromRequest
BenchmarkURLFromRequest/regex/few_params
BenchmarkURLFromRequest/regex/few_params-16 156728 7656 ns/op 186 B/op 6 allocs/op
BenchmarkURLFromRequest/regex/many_params
BenchmarkURLFromRequest/regex/many_params-16 50014 24293 ns/op 447 B/op 7 allocs/op
BenchmarkURLFromRequest/regex/really_long_1
BenchmarkURLFromRequest/regex/really_long_1-16 3770 316669 ns/op 4675 B/op 5 allocs/op
| for rawQuery != "" { | ||
| // Split on "&" to isolate each key=value pair. | ||
| var pair string | ||
| if before, after, found := strings.Cut(rawQuery, "&"); found { |
There was a problem hiding this comment.
Keys and values can be URL-encoded. Maybe we should call url.QueryUnescape on rawQuery?
There was a problem hiding this comment.
Not sold to the idea for two reasons:
- calling
url.QueryUnescapeon the entire URL would break the&and then break the splitting. - calling
url.QueryUnescapeon each key would be a performance trap
Keys in RawQuery can indeed be percent-encoded. I've added handling for non-ASCII keys (e.g. CJK characters like 名前): parseAllowlist now stores both the raw UTF-8 form and the percent-encoded form (%E5%90%8D%E5%89%8D) in the map at config time. This way the lookup in filterQueryStringByAllowlist matches directly against the encoded key in RawQuery with zero runtime decoding cost.
For the case of percent-encoded ASCII keys (e.g. %70age for page), we intentionally skip it, no standard HTTP client encodes plain ASCII letters in parameter names
|
@genesor May I ask when we can expect the release with this future? |
| c.resourceRenamingEnabled = &vv | ||
| } | ||
| // Global allowlist applies to both client and server; specific env vars override it. | ||
| if v, ok := env.Lookup(envQueryStringAllowlist); ok && v != "" { |
There was a problem hiding this comment.
Just to make sure, if both DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST and DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST_CLIENT|SERVER specified together DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST will be overridden is this what we want?
We should document the presedence in any case. And add a test case for this.
There was a problem hiding this comment.
Yes @kakkoyun there is a global allowlist that can be overriden by specific ones, this is what the comment states. It is also included in the registry description and the docstring in the code
Two test cases already cover this exact scenario
There was a problem hiding this comment.
Okay, thanks for the pointers! I missed those. I have reviewed too many PRs today.
|
@genesor |
|
Hi @hsiwikxperi The |

What does this PR do?
Adds a new environment variable
DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLISTthat lets users specify a comma-separated list of query parameter keys to retain in thehttp.urlspan tag. When set, only the listed keys are kept and the expensive default obfuscation regex is bypassed entirely in favor of a simple split-and-filter pass over the raw query string.Additionally, two side-specific env vars are introduced for granular control:
DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST_CLIENT— overrides the global allowlist for client-side (outgoing) HTTP spans only.DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST_SERVER— overrides the global allowlist for server-side (incoming) HTTP spans only.The global env var populates both client and server allowlists. The specific env vars take precedence when set.
Motivation
A customer on dd-trace-go v2.5 reported ~70% CPU overhead caused by the default query string obfuscation regex in
URLFromRequestrunning on every HTTP span. Their query strings are large. Disabling query strings entirely (DD_TRACE_HTTP_URL_QUERY_STRING_DISABLED=true) was not viable since they need specific parameters for debugging. The customer requested the ability to pick specific query parameter keys to keep (e.g.[p1, p3]) with high performance.Related: APMS-18777
Reviewer's Checklist
make lintlocally.make testlocally.make generatelocally.make fix-moduleslocally.