Skip to content

Commit e413676

Browse files
bm1549claude
andcommitted
Address PR feedback: fix locale bug, move ksr formatting to PropagationTags
- Use Locale.ROOT in String.format to prevent locale-sensitive decimal separators (e.g. comma in fr_FR) from corrupting x-datadog-tags - Move formatKnuthSamplingRate() from DDSpan to PTagsFactory so propagation encoding logic stays in the propagation layer - Change updateKnuthSamplingRate signature to accept double instead of pre-formatted String - Use indexOf('.') instead of contains(".") for minor perf improvement - Update test to exercise formatting through PropagationTags API Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 13b7d5e commit e413676

4 files changed

Lines changed: 38 additions & 32 deletions

File tree

dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -650,34 +650,12 @@ public DDSpan setSamplingPriority(
650650
|| samplingMechanism == SamplingMechanism.LOCAL_USER_RULE
651651
|| samplingMechanism == SamplingMechanism.REMOTE_USER_RULE
652652
|| samplingMechanism == SamplingMechanism.REMOTE_ADAPTIVE_RULE) {
653-
context.getPropagationTags().updateKnuthSamplingRate(formatKnuthSamplingRate(sampleRate));
653+
context.getPropagationTags().updateKnuthSamplingRate(sampleRate);
654654
}
655655
}
656656
return this;
657657
}
658658

659-
/**
660-
* Formats the sampling rate for the _dd.p.ksr propagated tag. Uses up to 6 significant digits
661-
* with no trailing zeros, matching the Go/Python reference implementations (%.6g format).
662-
*/
663-
static String formatKnuthSamplingRate(double rate) {
664-
// Use %.6g format: up to 6 significant digits, no trailing zeros
665-
// This matches Go's strconv.FormatFloat(rate, 'g', 6, 64) and Python's f"{rate:.6g}"
666-
String formatted = String.format("%.6g", rate);
667-
// Remove trailing zeros after decimal point (avoid forbidden String#replaceAll)
668-
if (formatted.contains(".")) {
669-
int end = formatted.length();
670-
while (end > 0 && formatted.charAt(end - 1) == '0') {
671-
end--;
672-
}
673-
if (end > 0 && formatted.charAt(end - 1) == '.') {
674-
end--;
675-
}
676-
formatted = formatted.substring(0, end);
677-
}
678-
return formatted;
679-
}
680-
681659
@Override
682660
public DDSpan setSpanSamplingPriority(double rate, int limit) {
683661
context.setSpanSamplingPriority(rate, limit);

dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,13 @@ public interface Factory {
132132

133133
/**
134134
* Updates the Knuth sampling rate (_dd.p.ksr) propagated tag. This records the sampling rate that
135-
* was applied when making an agent-based or rule-based sampling decision.
135+
* was applied when making an agent-based or rule-based sampling decision. The rate is formatted
136+
* with up to 6 significant digits and no trailing zeros, matching the Go/Python reference
137+
* implementations (%.6g format).
136138
*
137-
* @param rate the formatted sampling rate string (up to 6 significant digits, no trailing zeros)
139+
* @param rate the sampling rate value
138140
*/
139-
public abstract void updateKnuthSamplingRate(String rate);
141+
public abstract void updateKnuthSamplingRate(double rate);
140142

141143
public HashMap<String, String> createTagMap() {
142144
HashMap<String, String> result = new HashMap<>();

dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Collections;
1818
import java.util.EnumMap;
1919
import java.util.List;
20+
import java.util.Locale;
2021
import java.util.Map;
2122
import java.util.Objects;
2223
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
@@ -270,15 +271,32 @@ public String getDebugPropagation() {
270271
}
271272

272273
@Override
273-
public void updateKnuthSamplingRate(String rate) {
274-
TagValue newValue = rate == null ? null : TagValue.from(rate);
275-
if (!java.util.Objects.equals(knuthSamplingRateTagValue, newValue)) {
274+
public void updateKnuthSamplingRate(double rate) {
275+
TagValue newValue = TagValue.from(formatKnuthSamplingRate(rate));
276+
if (!Objects.equals(knuthSamplingRateTagValue, newValue)) {
276277
clearCachedHeader(DATADOG);
277278
clearCachedHeader(W3C);
278279
}
279280
knuthSamplingRateTagValue = newValue;
280281
}
281282

283+
/** Formats a sampling rate with up to 6 significant digits and no trailing zeros. */
284+
static String formatKnuthSamplingRate(double rate) {
285+
String formatted = String.format(Locale.ROOT, "%.6g", rate);
286+
int dotIndex = formatted.indexOf('.');
287+
if (dotIndex >= 0) {
288+
int end = formatted.length();
289+
while (end > dotIndex + 1 && formatted.charAt(end - 1) == '0') {
290+
end--;
291+
}
292+
if (formatted.charAt(end - 1) == '.') {
293+
end--;
294+
}
295+
formatted = formatted.substring(0, end);
296+
}
297+
return formatted;
298+
}
299+
282300
TagValue getKnuthSamplingRateTagValue() {
283301
return knuthSamplingRateTagValue;
284302
}

dd-trace-core/src/test/groovy/datadog/trace/core/KnuthSamplingRateTest.groovy

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import datadog.trace.common.sampling.RateByServiceTraceSampler
55
import datadog.trace.common.sampling.Sampler
66
import datadog.trace.common.writer.ListWriter
77
import datadog.trace.common.writer.ddagent.DDAgentApi
8+
import datadog.trace.core.propagation.PropagationTags
89
import datadog.trace.core.test.DDCoreSpecification
910

1011
import static datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT
@@ -16,9 +17,16 @@ import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP
1617
class KnuthSamplingRateTest extends DDCoreSpecification {
1718
static serializer = DDAgentApi.RESPONSE_ADAPTER
1819

19-
def "formatKnuthSamplingRate produces correct format"() {
20-
expect:
21-
DDSpan.formatKnuthSamplingRate(rate) == expected
20+
def "updateKnuthSamplingRate formats rate correctly"() {
21+
setup:
22+
def pTags = PropagationTags.factory().empty()
23+
24+
when:
25+
pTags.updateKnuthSamplingRate(rate)
26+
def tagMap = pTags.createTagMap()
27+
28+
then:
29+
tagMap.get('_dd.p.ksr') == expected
2230

2331
where:
2432
rate | expected

0 commit comments

Comments
 (0)