diff --git a/ext/priority_sampling/priority_sampling.c b/ext/priority_sampling/priority_sampling.c index 96533bed9f5..d92cf1d9425 100644 --- a/ext/priority_sampling/priority_sampling.c +++ b/ext/priority_sampling/priority_sampling.c @@ -1,6 +1,7 @@ #include "../compat_string.h" #include "priority_sampling.h" +#include #include #include @@ -65,8 +66,20 @@ static void dd_update_decision_maker_tag(ddtrace_root_span_data *root_span, static void dd_update_knuth_sampling_rate_tag(ddtrace_root_span_data *root_span, double sample_rate) { zend_array *meta = ddtrace_property_array(&root_span->property_meta); + // Round to 6 decimal places at integer level to avoid IEEE 754 precision issues, + // then format with fixed-point notation (never scientific notation). + double rounded = floor(sample_rate * 1e6 + 0.5) / 1e6; char buf[32]; - snprintf(buf, sizeof(buf), "%.6g", sample_rate); + snprintf(buf, sizeof(buf), "%.6f", rounded); + + // Strip trailing zeros and optional decimal point + size_t len = strlen(buf); + while (len > 1 && buf[len - 1] == '0') { + buf[--len] = '\0'; + } + if (len > 1 && buf[len - 1] == '.') { + buf[--len] = '\0'; + } // Skip update if already set to the same value zval *existing = zend_hash_str_find(meta, ZEND_STRL("_dd.p.ksr")); diff --git a/tests/ext/priority_sampling/028-ksr-tag-formatting.phpt b/tests/ext/priority_sampling/028-ksr-tag-formatting.phpt index cbcafc6a73a..c4bed53b9b2 100644 --- a/tests/ext/priority_sampling/028-ksr-tag-formatting.phpt +++ b/tests/ext/priority_sampling/028-ksr-tag-formatting.phpt @@ -1,5 +1,5 @@ --TEST-- -_dd.p.ksr propagated tag formats rate with up to 6 significant digits and no trailing zeros +_dd.p.ksr propagated tag formats rate with up to 6 decimal digits and no trailing zeros --ENV-- DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.7654321}] DD_TRACE_GENERATE_ROOT_SPAN=1 diff --git a/tests/ext/priority_sampling/029-ksr-tag-small-rate-formatting.phpt b/tests/ext/priority_sampling/029-ksr-tag-small-rate-formatting.phpt new file mode 100644 index 00000000000..070cf651f7a --- /dev/null +++ b/tests/ext/priority_sampling/029-ksr-tag-small-rate-formatting.phpt @@ -0,0 +1,19 @@ +--TEST-- +_dd.p.ksr uses decimal notation (not scientific) for very small sampling rates +--ENV-- +DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.000001}] +DD_TRACE_GENERATE_ROOT_SPAN=1 +--FILE-- +meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-"; +echo "_dd.p.ksr = ", $ksr, "\n"; +// Must be decimal notation, not scientific (e.g. "0.000001" not "1e-06") +echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n"; +?> +--EXPECT-- +_dd.p.ksr = 0.000001 +no_sci_notation = true diff --git a/tests/ext/priority_sampling/030-ksr-tag-rounding-boundary.phpt b/tests/ext/priority_sampling/030-ksr-tag-rounding-boundary.phpt new file mode 100644 index 00000000000..14fc369b7ec --- /dev/null +++ b/tests/ext/priority_sampling/030-ksr-tag-rounding-boundary.phpt @@ -0,0 +1,19 @@ +--TEST-- +_dd.p.ksr rounds small rates correctly at 6-decimal boundary +--ENV-- +DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.00000051}] +DD_TRACE_GENERATE_ROOT_SPAN=1 +--FILE-- +meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-"; +echo "_dd.p.ksr = ", $ksr, "\n"; +// 0.00000051 rounds up to 0.000001 at 6 decimal places +echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n"; +?> +--EXPECT-- +_dd.p.ksr = 0.000001 +no_sci_notation = true diff --git a/tests/ext/priority_sampling/031-ksr-tag-exact-sixth-decimal.phpt b/tests/ext/priority_sampling/031-ksr-tag-exact-sixth-decimal.phpt new file mode 100644 index 00000000000..e106dee6904 --- /dev/null +++ b/tests/ext/priority_sampling/031-ksr-tag-exact-sixth-decimal.phpt @@ -0,0 +1,18 @@ +--TEST-- +_dd.p.ksr preserves exact 0.000001 rate without rounding away +--ENV-- +DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.000001}] +DD_TRACE_GENERATE_ROOT_SPAN=1 +--FILE-- +meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-"; +echo "_dd.p.ksr = ", $ksr, "\n"; +echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n"; +?> +--EXPECT-- +_dd.p.ksr = 0.000001 +no_sci_notation = true diff --git a/tests/ext/priority_sampling/032-ksr-tag-below-precision-rounds-to-zero.phpt b/tests/ext/priority_sampling/032-ksr-tag-below-precision-rounds-to-zero.phpt new file mode 100644 index 00000000000..0f5f2379936 --- /dev/null +++ b/tests/ext/priority_sampling/032-ksr-tag-below-precision-rounds-to-zero.phpt @@ -0,0 +1,19 @@ +--TEST-- +_dd.p.ksr rounds rate below 6-decimal precision to 0 +--ENV-- +DD_TRACE_SAMPLING_RULES=[{"sample_rate": 0.0000001}] +DD_TRACE_GENERATE_ROOT_SPAN=1 +--FILE-- +meta["_dd.p.ksr"]) ? $root->meta["_dd.p.ksr"] : "-"; +echo "_dd.p.ksr = ", $ksr, "\n"; +// 0.0000001 rounds to 0 at 6 decimal places +echo "no_sci_notation = ", (strpos($ksr, 'e') === false) ? "true" : "false", "\n"; +?> +--EXPECT-- +_dd.p.ksr = 0 +no_sci_notation = true