Skip to content

Commit 116d0de

Browse files
bm1549claude
andauthored
Fix _dd.p.ksr scientific notation for very small sampling rates (#3721)
* Fix _dd.p.ksr scientific notation for very small sampling rates Very small sampling rates (e.g. 0.000001) were formatted using C's %.6g format which outputs scientific notation like "1e-06". This changes to explicit rounding at the integer level via floor(x * 1e6 + 0.5) and %.6f 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) <noreply@anthropic.com> * ci: retry CI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add tests for _dd.p.ksr rounding at 6-decimal boundary Test three boundary cases for small sampling rates: - 0.00000051 rounds up to 0.000001 - 0.000001 stays exactly 0.000001 - 0.0000001 rounds down to 0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 10064f5 commit 116d0de

6 files changed

Lines changed: 90 additions & 2 deletions

ext/priority_sampling/priority_sampling.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "../compat_string.h"
22
#include "priority_sampling.h"
33

4+
#include <math.h>
45
#include <vendor/mt19937/mt19937-64.h>
56

67
#include <uri_normalization/uri_normalization.h>
@@ -65,8 +66,20 @@ static void dd_update_decision_maker_tag(ddtrace_root_span_data *root_span,
6566
static void dd_update_knuth_sampling_rate_tag(ddtrace_root_span_data *root_span, double sample_rate) {
6667
zend_array *meta = ddtrace_property_array(&root_span->property_meta);
6768

69+
// Round to 6 decimal places at integer level to avoid IEEE 754 precision issues,
70+
// then format with fixed-point notation (never scientific notation).
71+
double rounded = floor(sample_rate * 1e6 + 0.5) / 1e6;
6872
char buf[32];
69-
snprintf(buf, sizeof(buf), "%.6g", sample_rate);
73+
snprintf(buf, sizeof(buf), "%.6f", rounded);
74+
75+
// Strip trailing zeros and optional decimal point
76+
size_t len = strlen(buf);
77+
while (len > 1 && buf[len - 1] == '0') {
78+
buf[--len] = '\0';
79+
}
80+
if (len > 1 && buf[len - 1] == '.') {
81+
buf[--len] = '\0';
82+
}
7083

7184
// Skip update if already set to the same value
7285
zval *existing = zend_hash_str_find(meta, ZEND_STRL("_dd.p.ksr"));

tests/ext/priority_sampling/028-ksr-tag-formatting.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
_dd.p.ksr propagated tag formats rate with up to 6 significant digits and no trailing zeros
2+
_dd.p.ksr propagated tag formats rate with up to 6 decimal digits and no trailing zeros
33
--ENV--
44
DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.7654321}]
55
DD_TRACE_GENERATE_ROOT_SPAN=1
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
_dd.p.ksr uses decimal notation (not scientific) for very small sampling rates
3+
--ENV--
4+
DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.000001}]
5+
DD_TRACE_GENERATE_ROOT_SPAN=1
6+
--FILE--
7+
<?php
8+
$root = \DDTrace\root_span();
9+
10+
\DDTrace\get_priority_sampling();
11+
12+
$ksr = isset($root->meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-";
13+
echo "_dd.p.ksr = ", $ksr, "\n";
14+
// Must be decimal notation, not scientific (e.g. "0.000001" not "1e-06")
15+
echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n";
16+
?>
17+
--EXPECT--
18+
_dd.p.ksr = 0.000001
19+
no_sci_notation = true
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
_dd.p.ksr rounds small rates correctly at 6-decimal boundary
3+
--ENV--
4+
DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.00000051}]
5+
DD_TRACE_GENERATE_ROOT_SPAN=1
6+
--FILE--
7+
<?php
8+
$root = \DDTrace\root_span();
9+
10+
\DDTrace\get_priority_sampling();
11+
12+
$ksr = isset($root->meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-";
13+
echo "_dd.p.ksr = ", $ksr, "\n";
14+
// 0.00000051 rounds up to 0.000001 at 6 decimal places
15+
echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n";
16+
?>
17+
--EXPECT--
18+
_dd.p.ksr = 0.000001
19+
no_sci_notation = true
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
_dd.p.ksr preserves exact 0.000001 rate without rounding away
3+
--ENV--
4+
DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.000001}]
5+
DD_TRACE_GENERATE_ROOT_SPAN=1
6+
--FILE--
7+
<?php
8+
$root = \DDTrace\root_span();
9+
10+
\DDTrace\get_priority_sampling();
11+
12+
$ksr = isset($root->meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-";
13+
echo "_dd.p.ksr = ", $ksr, "\n";
14+
echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n";
15+
?>
16+
--EXPECT--
17+
_dd.p.ksr = 0.000001
18+
no_sci_notation = true
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
_dd.p.ksr rounds rate below 6-decimal precision to 0
3+
--ENV--
4+
DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.0000001}]
5+
DD_TRACE_GENERATE_ROOT_SPAN=1
6+
--FILE--
7+
<?php
8+
$root = \DDTrace\root_span();
9+
10+
\DDTrace\get_priority_sampling();
11+
12+
$ksr = isset($root->meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-";
13+
echo "_dd.p.ksr = ", $ksr, "\n";
14+
// 0.0000001 rounds to 0 at 6 decimal places
15+
echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n";
16+
?>
17+
--EXPECT--
18+
_dd.p.ksr = 0
19+
no_sci_notation = true

0 commit comments

Comments
 (0)