From c741ba4dc8fddf50dd4d9fbd5d0c3b9849186499 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Mon, 23 Mar 2026 21:23:11 -0400 Subject: [PATCH 1/3] 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) --- ext/priority_sampling/priority_sampling.c | 15 ++++++++++++++- .../028-ksr-tag-formatting.phpt | 2 +- .../029-ksr-tag-small-rate-formatting.phpt | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/ext/priority_sampling/029-ksr-tag-small-rate-formatting.phpt 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 From ce2a0e40c896510e783d009e2e42f0d180e22e55 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Tue, 24 Mar 2026 07:01:43 -0400 Subject: [PATCH 2/3] ci: retry CI Co-Authored-By: Claude Opus 4.6 (1M context) From 67b831221a1b695910b182aa7143e09a3ca3b97b Mon Sep 17 00:00:00 2001 From: bm1549 Date: Wed, 25 Mar 2026 11:10:26 -0400 Subject: [PATCH 3/3] 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) --- .../030-ksr-tag-rounding-boundary.phpt | 19 +++++++++++++++++++ .../031-ksr-tag-exact-sixth-decimal.phpt | 18 ++++++++++++++++++ ...sr-tag-below-precision-rounds-to-zero.phpt | 19 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/ext/priority_sampling/030-ksr-tag-rounding-boundary.phpt create mode 100644 tests/ext/priority_sampling/031-ksr-tag-exact-sixth-decimal.phpt create mode 100644 tests/ext/priority_sampling/032-ksr-tag-below-precision-rounds-to-zero.phpt 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