Repository navigation
perf(tracer): use lookbehind for JWT prefix in default query-string regex - #9405
Conversation
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (9405) and master. ✅ No regressions detected |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
More details
The JWT lookbehind preserves delimiters and allows adjacent tokens to be redacted without re-emitting captured text. Runtime verification was limited to standalone .NET 8 checks because the required .NET 11 SDK was unavailable.
🤖 Bits Code Review · Commit e3ea59e
BenchmarksBenchmark execution time: 2026-10-15 13:13:42 Comparing candidate commit 4b3b947 in PR branch Found 0 performance improvements and 11 performance regressions! Performance is the same for 61 metrics, 0 unstable metrics, 76 known flaky benchmarks, 50 flaky benchmarks without significant changes.
|
anna-git
left a comment
There was a problem hiding this comment.
Nit, in the pr description it says "The lookbehind keeps the same left boundary.", it's the same boundary except for a lone % before the JWT, as v.3.55.0 also redacted that case.
…egex The consuming prefix group added in #9374 prevents .NET from skipping ahead to candidate match positions, making non-JWT query strings 2.5-5x slower. A zero-width lookbehind keeps the same left boundary, stays linear on the ReDoS inputs, and removes the need for the ${1} replacement and the isDefaultPattern plumbing.
ba51946 to
9679a63
Compare
Summary of changes
(?:(?<![\w-])|(?<=%[0-9a-f]{2}))ey[I-L]instead of the consuming group(^|[^\w%-]|%[0-9a-f]{2})ey[I-L]from perf(tracer): reduce query-string matching cost #9374.${1}<redacted>replacement and theisDefaultPattern/ObfuscationQueryStringRegexWasConfiguredplumbing are removed,since the default pattern no longer captures the delimiter.
Every pattern, default or custom, is replaced with
<redacted>again.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXPmoves to registry implementationK.Reason for change
The consuming group in #9374 stops .NET from skipping ahead to positions where a match can start,
so every query string without a JWT got slower.
Measured on .NET 10 with the tracer's regex options (µs per call):
?id=123&page=2Interpreted mode shows the same 2-3x gap for 3.55.1.
The lookbehind keeps the same left boundary as #9374, except that a lone
%before the JWT no longer blocks the match (3.55.0 redacted that case too).Other tracers stay on the capture-group form because Go and RE2/J have no lookbehind.
Implementation details
Because the lookbehind does not consume the delimiter, adjacent JWTs are now all redacted.
Before, a JWT whose delimiter had been eaten by the previous match was left in clear:
?q=eyJa.eyJb=eyJc.eyJd=eyJe.eyJf?q=<redacted>eyJc.eyJd=<redacted>?q=<redacted><redacted><redacted>?t=eyJa%3D.eyJb%3D%3DeyJc.eyJd?t=<redacted>eyJc.eyJd?t=<redacted><redacted>?x=%eyJa.eyJb?x=%<redacted>It also fixes the case where
DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXPis set to the default text:3.55.1 dropped the delimiter there (
?jwt<redacted>).Test coverage
%eyJand padded adjacent-JWT cases.Other details
Registry implementation
KofDD_TRACE_OBFUSCATION_QUERY_STRING_REGEXPholds the new default.