Skip to content

Commit 0c13dba

Browse files
authored
feat: send knuth sampling rates tags (#250)
* feat: send knuth sampling rates tags Changes: - Set `_dd.p.ksr` tag with the knuth sampling rates computed. - Remove remaining devs from sampling delegation. - Add unit tests.
1 parent 286d0e3 commit 0c13dba

File tree

6 files changed

+63
-30
lines changed

6 files changed

+63
-30
lines changed

src/datadog/tags.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ const std::string trace_id_high = "_dd.p.tid";
2929
const std::string process_id = "process_id";
3030
const std::string language = "language";
3131
const std::string runtime_id = "runtime-id";
32-
const std::string sampling_decider = "_dd.is_sampling_decider";
3332
const std::string w3c_parent_id = "_dd.parent_id";
3433
const std::string trace_source = "_dd.p.ts";
3534
const std::string apm_enabled = "_dd.apm.enabled";
35+
const std::string ksr = "_dd.p.ksr";
3636

3737
} // namespace internal
3838

src/datadog/tags.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ extern const std::string trace_id_high;
3737
extern const std::string process_id;
3838
extern const std::string language;
3939
extern const std::string runtime_id;
40-
extern const std::string sampling_decider;
4140
extern const std::string w3c_parent_id;
4241
extern const std::string trace_source; // _dd.p.ts
4342
extern const std::string apm_enabled; // _dd.apm.enabled
43+
extern const std::string ksr; // _dd.p.ksr
4444

4545
} // namespace internal
4646

src/datadog/trace_segment.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <datadog/trace_segment.h>
1212

1313
#include <cassert>
14+
#include <charconv>
1415
#include <string>
1516
#include <unordered_map>
1617
#include <utility>
@@ -226,13 +227,6 @@ void TraceSegment::span_finished() {
226227
}
227228
}
228229

229-
if (decision.origin == SamplingDecision::Origin::DELEGATED &&
230-
local_root.parent_id == 0) {
231-
// Convey the fact that, even though we are the root service, we delegated
232-
// the sampling decision and so are not the "sampling decider."
233-
local_root.tags[tags::internal::sampling_decider] = "0";
234-
}
235-
236230
// RFC seems to only mandate that this be set if the trace is kept.
237231
// However, system-tests expect this to be always be set.
238232
// Add it all the time; can't hurt
@@ -292,6 +286,10 @@ void TraceSegment::make_sampling_decision_if_null() {
292286
sampling_decision_ = trace_sampler_->decide(local_root);
293287

294288
update_decision_maker_trace_tag();
289+
290+
trace_tags_.emplace_back(
291+
tags::internal::ksr,
292+
std::to_string(*sampling_decision_->configured_rate));
295293
}
296294

297295
void TraceSegment::update_decision_maker_trace_tag() {

test/test_span.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -784,8 +784,8 @@ TEST_SPAN("injecting W3C tracestate header") {
784784
{"x-datadog-parent-id", "1"},
785785
{"x-datadog-origin", "France"},
786786
},
787-
// The "s:-1" comes from the 0% sample rate.
788-
"dd=s:-1;p:$parent_id;o:France"},
787+
// The "s:-1" and "t.ksr:0.000000" comes from the 0% sample rate.
788+
"dd=s:-1;p:$parent_id;o:France;t.ksr:0.000000"},
789789

790790
{__LINE__,
791791
"trace tags",
@@ -794,8 +794,8 @@ TEST_SPAN("injecting W3C tracestate header") {
794794
{"x-datadog-parent-id", "1"},
795795
{"x-datadog-tags", "_dd.p.foo=x,_dd.p.bar=y,ignored=wrong_prefix"},
796796
},
797-
// The "s:-1" comes from the 0% sample rate.
798-
"dd=s:-1;p:$parent_id;t.foo:x;t.bar:y"},
797+
// The "s:-1" and "t.ksr:0.000000" comes from the 0% sample rate.
798+
"dd=s:-1;p:$parent_id;t.foo:x;t.bar:y;t.ksr:0.000000"},
799799

800800
{__LINE__,
801801
"extra fields",
@@ -815,15 +815,18 @@ TEST_SPAN("injecting W3C tracestate header") {
815815
// The "s:0" comes from the sampling decision in `traceparent_drop`.
816816
"dd=s:0;p:$parent_id;o:France;t.foo:x;t.bar:y;foo:bar;boing:boing"},
817817

818-
{__LINE__,
819-
"replace invalid characters in origin",
820-
{
821-
{"x-datadog-trace-id", "1"},
822-
{"x-datadog-parent-id", "1"},
823-
{"x-datadog-origin", "France, is a country=nation; so is 台北."},
824-
},
825-
// The "s:-1" comes from the 0% sample rate.
826-
"dd=s:-1;p:$parent_id;o:France_ is a country~nation_ so is ______."},
818+
{
819+
__LINE__,
820+
"replace invalid characters in origin",
821+
{
822+
{"x-datadog-trace-id", "1"},
823+
{"x-datadog-parent-id", "1"},
824+
{"x-datadog-origin", "France, is a country=nation; so is 台北."},
825+
},
826+
// The "s:-1" comes from the 0% sample rate.
827+
"dd=s:-1;p:$parent_id;o:France_ is a country~nation_ so is "
828+
"______.;t.ksr:0.000000",
829+
},
827830

828831
{__LINE__,
829832
"replace invalid characters in trace tag key",
@@ -833,7 +836,7 @@ TEST_SPAN("injecting W3C tracestate header") {
833836
{"x-datadog-tags", "_dd.p.a;d台北x =foo,_dd.p.ok=bar"},
834837
},
835838
// The "s:-1" comes from the 0% sample rate.
836-
"dd=s:-1;p:$parent_id;t.a_d______x_:foo;t.ok:bar"},
839+
"dd=s:-1;p:$parent_id;t.a_d______x_:foo;t.ok:bar;t.ksr:0.000000"},
837840

838841
{__LINE__,
839842
"replace invalid characters in trace tag value",
@@ -843,7 +846,8 @@ TEST_SPAN("injecting W3C tracestate header") {
843846
{"x-datadog-tags", "_dd.p.wacky=hello fr~d; how are คุณ?"},
844847
},
845848
// The "s:-1" comes from the 0% sample rate.
846-
"dd=s:-1;p:$parent_id;t.wacky:hello fr_d_ how are _________?"},
849+
"dd=s:-1;p:$parent_id;t.wacky:hello fr_d_ how are "
850+
"_________?;t.ksr:0.000000"},
847851

848852
{__LINE__,
849853
"replace equal signs with tildes in trace tag value",
@@ -853,7 +857,7 @@ TEST_SPAN("injecting W3C tracestate header") {
853857
{"x-datadog-tags", "_dd.p.base64_thingy=d2Fra2EhIHdhaw=="},
854858
},
855859
// The "s:-1" comes from the 0% sample rate.
856-
"dd=s:-1;p:$parent_id;t.base64_thingy:d2Fra2EhIHdhaw~~"},
860+
"dd=s:-1;p:$parent_id;t.base64_thingy:d2Fra2EhIHdhaw~~;t.ksr:0.000000"},
857861

858862
{__LINE__,
859863
"oversized origin truncates it and subsequent fields",

test/test_trace_segment.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ TEST_CASE("TraceSegment finalization of spans") {
310310
REQUIRE_THAT(span.tags, ContainsSubset(filtered));
311311
// "_dd.p.dm" will be added, because we made a sampling decision.
312312
REQUIRE(span.tags.count("_dd.p.dm") == 1);
313+
REQUIRE(span.tags.count("_dd.p.ksr") == 1);
313314
}
314315

315316
SECTION("rate tags") {
@@ -324,6 +325,7 @@ TEST_CASE("TraceSegment finalization of spans") {
324325
REQUIRE(collector->span_count() == 1);
325326
const auto& span = collector->first_span();
326327
REQUIRE(span.numeric_tags.at(tags::internal::agent_sample_rate) == 1.0);
328+
REQUIRE(span.tags.at(tags::internal::ksr) == "1.000000");
327329
}
328330

329331
SECTION(
@@ -343,17 +345,24 @@ TEST_CASE("TraceSegment finalization of spans") {
343345
auto span = tracer.create_span();
344346
(void)span;
345347
}
346-
REQUIRE(collector_response->span_count() == 1);
348+
{
349+
REQUIRE(collector_response->span_count() == 1);
350+
const auto& span = collector_response->first_span();
351+
CHECK(span.tags.at(tags::internal::ksr) == "1.000000");
352+
}
347353

348354
collector_response->chunks.clear();
349355
// Second trace will use the rate from `collector->response`.
350356
{
351357
auto span = tracer.create_span();
352358
(void)span;
353359
}
354-
REQUIRE(collector_response->span_count() == 1);
355-
const auto& span = collector_response->first_span();
356-
REQUIRE(span.numeric_tags.at(tags::internal::agent_sample_rate) == 1.0);
360+
{
361+
REQUIRE(collector_response->span_count() == 1);
362+
const auto& span = collector_response->first_span();
363+
CHECK(span.numeric_tags.at(tags::internal::agent_sample_rate) == 1.0);
364+
CHECK(span.tags.at(tags::internal::ksr) == "1.000000");
365+
}
357366
}
358367

359368
SECTION("rules (implicit and explicit)") {
@@ -383,6 +392,7 @@ TEST_CASE("TraceSegment finalization of spans") {
383392
const auto& span = collector->first_span();
384393
REQUIRE(span.numeric_tags.at(tags::internal::rule_sample_rate) ==
385394
sample_rate);
395+
CHECK(span.tags.at(tags::internal::ksr) == std::to_string(sample_rate));
386396
if (sample_rate == 1.0) {
387397
REQUIRE(span.numeric_tags.at(
388398
tags::internal::rule_limiter_sample_rate) == 1.0);

test/test_tracer.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,11 +995,13 @@ TEST_TRACER("span extraction") {
995995
__LINE__,
996996
"origin, trace tags, parent, and extra fields",
997997
traceparent_drop, // traceparent
998-
"dd=o:France;p:00000000000d69ac;t.foo:thing1;t.bar:thing2;x:wow;y:"
998+
"dd=o:France;p:00000000000d69ac;t.ksr:0.728;t.foo:thing1;t.bar:"
999+
"thing2;x:wow;y:"
9991000
"wow", // tracestate
10001001
0, // expected_sampling_priority
10011002
"France", // expected_origin
10021003
{
1004+
{"_dd.p.ksr", "0.728"},
10031005
{"_dd.p.foo", "thing1"},
10041006
{"_dd.p.bar", "thing2"},
10051007
}, // expected_trace_tags
@@ -2034,3 +2036,22 @@ TEST_TRACER("APM tracing disabled") {
20342036
}
20352037
}
20362038
}
2039+
2040+
TEST_TRACER("_dd.p.ksr is NOT set when overriding the sampling decision") {
2041+
const auto collector = std::make_shared<MockCollector>();
2042+
2043+
TracerConfig config;
2044+
config.collector = collector;
2045+
auto finalized_config = finalize_config(config);
2046+
REQUIRE(finalized_config);
2047+
2048+
Tracer tracer{*finalized_config};
2049+
2050+
{
2051+
auto span = tracer.create_span();
2052+
span.trace_segment().override_sampling_priority(10);
2053+
}
2054+
2055+
auto c = collector->first_span();
2056+
CHECK(c.tags.count(tags::internal::ksr) == 0);
2057+
}

0 commit comments

Comments
 (0)