Skip to content

Commit f657b07

Browse files
bm1549claudeBridgeAR
authored
fix(tracing): format _dd.p.ksr with decimal notation instead of scientific notation (#7846)
* fix(tracing): format _dd.p.ksr with decimal notation instead of scientific notation Very small sampling rates (e.g. 0.0000001) were formatted using toPrecision(6) + toString() which outputs scientific notation like "1e-7". This changes to explicit rounding at the integer level and toFixed(6) formatting to always produce decimal notation with up to 6 decimal digits, trailing zeros stripped (e.g. "0.000001"). Fixes APMAPI-1869 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix(tracing): replace regex with loop in formatKnuthRate for hot-path perf Addresses PR review feedback: replaces the regex-based trailing-zero strip with a manual loop to avoid regex overhead on the hot path. Also adds Number() coercion as defensive measure per reviewer suggestion. Math.round pre-rounding is intentionally kept — toFixed(6) has imprecise rounding for sub-precision values in V8 (e.g. 0.0000005.toFixed(6) returns '0.000000' in Node 23). JSDoc updated to explain this. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(tracing): simplify formatKnuthRate loop per review feedback Drop Math.round pre-rounding — the edge case (0.0000005 rounding down in V8) is acceptable imprecision. Test updated to use 0.00000051 which rounds up unambiguously without Math.round. Drop indexOf('.') — check for '.' directly in the loop instead, which handles integer rates (0, 1) without the overhead of a separate scan. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * Update packages/dd-trace/src/priority_sampler.js Co-authored-by: Ruben Bridgewater <[email protected]> * fix(tracing): resolve lint errors in formatKnuthRate - Flip negated conditions to positive checks (unicorn/no-negated-condition) - Remove @returns tag since linter can't statically verify loop always returns (jsdoc/require-returns-check) - Preserve BridgeAR's single-check-per-iteration optimization Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]> Co-authored-by: Ruben Bridgewater <[email protected]>
1 parent da201ff commit f657b07

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

packages/dd-trace/src/priority_sampler.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ const {
3737
const DEFAULT_KEY = 'service:,env:'
3838

3939
/**
40-
* Formats a sampling rate as a string with up to 6 significant digits and no trailing zeros.
40+
* Formats a sampling rate as a string with up to 6 decimal digits and no trailing zeros.
4141
*
4242
* @param {number} rate
43-
* @returns {string}
4443
*/
4544
function formatKnuthRate (rate) {
46-
return Number(rate.toPrecision(6)).toString()
45+
const string = Number(rate).toFixed(6)
46+
for (let i = string.length - 1; i > 0; i--) {
47+
if (string[i] === '0') continue
48+
return string.slice(0, i + (string[i] === '.' ? 0 : 1))
49+
}
4750
}
4851

4952
const defaultSampler = new Sampler(AUTO_KEEP)

packages/dd-trace/test/priority_sampler.spec.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,45 @@ describe('PrioritySampler', () => {
421421
assert.strictEqual(typeof context._trace.tags[SAMPLING_KNUTH_RATE], 'string')
422422
})
423423

424+
it('should format _dd.p.ksr with decimal notation for very small rates', () => {
425+
Sampler.withArgs(0.000001).returns({
426+
isSampled: sinon.stub().returns(true),
427+
rate: sinon.stub().returns(0.000001),
428+
})
429+
prioritySampler = new PrioritySampler('test', {
430+
sampleRate: 0.000001,
431+
})
432+
prioritySampler.sample(span)
433+
434+
assert.strictEqual(context._trace.tags[SAMPLING_KNUTH_RATE], '0.000001')
435+
})
436+
437+
it('should round _dd.p.ksr to zero when rate is below 6 decimal precision', () => {
438+
Sampler.withArgs(0.0000001).returns({
439+
isSampled: sinon.stub().returns(true),
440+
rate: sinon.stub().returns(0.0000001),
441+
})
442+
prioritySampler = new PrioritySampler('test', {
443+
sampleRate: 0.0000001,
444+
})
445+
prioritySampler.sample(span)
446+
447+
assert.strictEqual(context._trace.tags[SAMPLING_KNUTH_RATE], '0')
448+
})
449+
450+
it('should round _dd.p.ksr up to 0.000001 when rate rounds up', () => {
451+
Sampler.withArgs(0.00000051).returns({
452+
isSampled: sinon.stub().returns(true),
453+
rate: sinon.stub().returns(0.00000051),
454+
})
455+
prioritySampler = new PrioritySampler('test', {
456+
sampleRate: 0.00000051,
457+
})
458+
prioritySampler.sample(span)
459+
460+
assert.strictEqual(context._trace.tags[SAMPLING_KNUTH_RATE], '0.000001')
461+
})
462+
424463
it('should not set _dd.p.ksr tag for manual sampling', () => {
425464
context._tags[MANUAL_KEEP] = undefined
426465

0 commit comments

Comments
 (0)