diff --git a/manifests/cpp.yml b/manifests/cpp.yml index ca73d6d846a..4444b0f79d8 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -231,8 +231,7 @@ manifest: component_version: '>=2.0.0' tests/parametric/test_sampling_delegation.py::Test_Decisionless_Extraction: ">1.0.0" tests/parametric/test_sampling_manual.py::Test_Manual_Sampling: bug (APMAPI-1720) # Manual keep did not override the upstream drop decision - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=2.0.0' # Modified by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_knuth_sample_rate_trace_sampling_rule: missing_feature # Created by easy win activation script + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=2.1.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_kept_sst007: bug (APMAPI-737) diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index e49fb25082f..083956a69fa 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -959,8 +959,7 @@ manifest: tests/parametric/test_partial_flushing.py::Test_Partial_Flushing::test_partial_flushing_one_span_default: missing_feature (partial flushing not enabled by default) tests/parametric/test_process_discovery.py::Test_ProcessDiscovery: '>=3.36.0' # Modified by easy win activation script tests/parametric/test_process_discovery.py::Test_ProcessDiscovery::test_metadata_content_with_process_tags: missing_feature # Created by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=3.36.0' # Modified by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_knuth_sample_rate_trace_sampling_rule: missing_feature # Created by easy win activation script + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=3.41.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_kept_sst007: bug (APMAPI-737) diff --git a/manifests/golang.yml b/manifests/golang.yml index 869128ae1c0..28b1125b6d7 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1151,8 +1151,7 @@ manifest: tests/parametric/test_parametric_endpoints.py::Test_Parametric_Write_Log::test_write_log: incomplete_test_app (Logs endpoint is only implemented in python and node.js app) tests/parametric/test_partial_flushing.py::Test_Partial_Flushing::test_partial_flushing_one_span_default: missing_feature (partial flushing not enabled by default) tests/parametric/test_process_discovery.py::Test_ProcessDiscovery: v2.2.3 - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=2.5.0' # Modified by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_knuth_sample_rate_trace_sampling_rule: missing_feature # Created by easy win activation script + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=2.8.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_kept_sst007: bug (APMAPI-737) diff --git a/manifests/java.yml b/manifests/java.yml index f502d1b3e06..9d9c761b68a 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -3702,8 +3702,7 @@ manifest: tests/parametric/test_partial_flushing.py::Test_Partial_Flushing::test_partial_flushing_one_span_default: 'missing_feature (java uses ''>'' so it needs one more span to force a partial flush)' tests/parametric/test_process_discovery.py::Test_ProcessDiscovery: v1.55.0-SNAPSHOT tests/parametric/test_sampling_manual.py::Test_Manual_Sampling: v1.59.0-SNAPSHOT+419da213f7 - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=1.58.2+06122213c8' # Modified by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_knuth_sample_rate_trace_sampling_rule: missing_feature # Created by easy win activation script + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=1.61.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: - declaration: bug (APMAPI-737) diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 29873fc8efe..c19ffa7fe9c 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2059,7 +2059,7 @@ manifest: tests/parametric/test_partial_flushing.py::Test_Partial_Flushing: bug (APMLP-270) tests/parametric/test_process_discovery.py: missing_feature tests/parametric/test_sampling_manual.py::Test_Manual_Sampling: bug (APMAPI-1720) # Manual keep did not override the upstream drop decision - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: missing_feature + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=5.93.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_defaults_rate_1_and_rate_limit_0_sst008: bug (APMAPI-737) diff --git a/manifests/php.yml b/manifests/php.yml index 9708c790962..b612dea0838 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -801,7 +801,7 @@ manifest: tests/parametric/test_partial_flushing.py::Test_Partial_Flushing::test_partial_flushing_under_limit_one_payload: '>=1.16.0' tests/parametric/test_process_discovery.py: missing_feature tests/parametric/test_sampling_delegation.py::Test_Decisionless_Extraction: v1.13.0+4663b2fa7c20c6920f347d059b57dc2a419cb7f7 - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: missing_feature + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=1.18.0' ? tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_extract_knuth_sample_rate_distributed_tracing_datadog : '>=1.16.0' ? tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_extract_knuth_sample_rate_distributed_tracing_tracecontext diff --git a/manifests/python.yml b/manifests/python.yml index 75e455de7bd..553d33d8945 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1718,7 +1718,7 @@ manifest: tests/parametric/test_partial_flushing.py::Test_Partial_Flushing: flaky (APMAPI-734) tests/parametric/test_process_discovery.py::Test_ProcessDiscovery: v3.15.0+dev36.gb57f15308 tests/parametric/test_sampling_delegation.py::Test_Decisionless_Extraction: v2.8.0 - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: v3.14.0.dev + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: v4.7.0 tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags: v2.8.0 tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: bug (APMAPI-737) diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 198ba6ac3b1..87010851242 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -1496,8 +1496,7 @@ manifest: tests/parametric/test_process_discovery.py::Test_ProcessDiscovery: v2.18.0 tests/parametric/test_process_discovery.py::Test_ProcessDiscovery::test_metadata_content_with_process_tags: missing_feature (Not yet implemented) tests/parametric/test_sampling_delegation.py::Test_Decisionless_Extraction: v2.4.0 - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=2.27.0' # Modified by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_knuth_sample_rate_trace_sampling_rule: missing_feature # Created by easy win activation script + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=2.31.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_appsec_enabled_sst011: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_dropped_sst001: bug (APMAPI-737) tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags::test_tags_child_kept_sst007: bug (APMAPI-737) diff --git a/manifests/rust.yml b/manifests/rust.yml index 6256e36933b..f82376aafbf 100644 --- a/manifests/rust.yml +++ b/manifests/rust.yml @@ -237,7 +237,7 @@ manifest: tests/parametric/test_process_discovery.py: missing_feature tests/parametric/test_sampling_manual.py::Test_Manual_Sampling: missing_feature tests/parametric/test_sampling_span_tags.py: '>=0.2.1' # Modified by easy win activation script - tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate::test_sampling_knuth_sample_rate_trace_sampling_rule: missing_feature # Created by easy win activation script + tests/parametric/test_sampling_span_tags.py::Test_Knuth_Sample_Rate: '>=0.4.0' tests/parametric/test_sampling_span_tags.py::Test_Sampling_Span_Tags: missing_feature # Created by easy win activation script tests/parametric/test_span_events.py: missing_feature tests/parametric/test_span_links.py::Test_Span_Links: missing_feature diff --git a/tests/parametric/test_sampling_span_tags.py b/tests/parametric/test_sampling_span_tags.py index ee22bde1cd7..526ac16d48c 100644 --- a/tests/parametric/test_sampling_span_tags.py +++ b/tests/parametric/test_sampling_span_tags.py @@ -271,7 +271,7 @@ def test_tags_appsec_enabled_sst011(self, test_agent: TestAgentAPI, test_library @features.trace_sampling class Test_Knuth_Sample_Rate: @pytest.mark.parametrize( - ("library_env", "sample_rate"), + ("library_env", "expected_ksr"), [ ( { @@ -283,39 +283,51 @@ class Test_Knuth_Sample_Rate: ( { "DD_TRACE_SAMPLE_RATE": None, - "DD_TRACE_SAMPLING_RULES": '[{"sample_rate":0.7654321}]', + "DD_TRACE_SAMPLING_RULES": '[{"sample_rate":0.000001}]', }, - "0.765432", + "0.000001", + ), + ( + { + "DD_TRACE_SAMPLE_RATE": None, + "DD_TRACE_SAMPLING_RULES": '[{"sample_rate":0.0000001}]', + }, + "0", + ), + ( + { + "DD_TRACE_SAMPLE_RATE": None, + "DD_TRACE_SAMPLING_RULES": '[{"sample_rate":0.00000051}]', + }, + "0.000001", ), ], - ids=["truncate_trailing_zeros", "percision_of_6_digits"], + ids=[ + "rate_1_strips_trailing_zeros", + "six_decimal_precision_boundary", + "below_precision_rounds_to_zero", + "rounds_up_to_one_millionth", + ], ) def test_sampling_knuth_sample_rate_trace_sampling_rule( - self, test_agent: TestAgentAPI, test_library: APMLibrary, sample_rate: str + self, test_agent: TestAgentAPI, test_library: APMLibrary, expected_ksr: str ): """When a trace is sampled via a sampling rule, the knuth sample rate - is sent to the agent on the chunk root span with the _dd.p.ksr key in the meta field. + is sent to the agent on the root span with the _dd.p.ksr key in the meta field. + The value is formatted with up to 6 decimal digits of precision, with trailing + zeros stripped. """ with test_library: - with test_library.dd_start_span("span") as span1: + with test_library.dd_start_span("span"): pass test_library.dd_flush() - with test_library.dd_start_span("span", parent_id=span1.span_id) as span2: - pass - test_library.dd_flush() - - with test_library.dd_start_span("span", parent_id=span2.span_id): - pass - test_library.dd_flush() - - traces = test_agent.wait_for_num_traces(3) - assert len(traces) == 3, f"Expected 3 traces: {traces}" - for trace in traces: - assert len(trace) == 1, f"Expected 1 span in the trace: {trace}" - span = trace[0] - assert span["meta"].get("_dd.p.ksr") == sample_rate, f"Expected {sample_rate} for span {span}" + traces = test_agent.wait_for_num_traces(1) + span = find_only_span(traces) + assert span["meta"].get("_dd.p.ksr") == expected_ksr, ( + f"Expected _dd.p.ksr='{expected_ksr}', got: {span['meta'].get('_dd.p.ksr')}" + ) @pytest.mark.parametrize( "library_env", @@ -325,7 +337,13 @@ def test_sampling_knuth_sample_rate_trace_sampling_rule( # Ensure sampling configurationations are not set. "DD_TRACE_SAMPLE_RATE": None, "DD_TRACE_SAMPLING_RULES": None, - } + }, + { + "DD_TRACE_PROPAGATION_STYLE": "Datadog", + "DD_TRACE_SAMPLE_RATE": None, + # Verify upstream ksr is propagated unchanged even with local sampling rules set. + "DD_TRACE_SAMPLING_RULES": '[{"sample_rate":0.5}]', + }, ], ) def test_sampling_extract_knuth_sample_rate_distributed_tracing_datadog( @@ -333,7 +351,8 @@ def test_sampling_extract_knuth_sample_rate_distributed_tracing_datadog( ): """When a trace is extracted from datadog headers, the sampling decision and rate is extracted from X-Datadog-Sampling-Priority and X-Datadog-Tags - headers. These values are stored in the span's meta fields. + headers. These values are stored in the span's meta fields. The upstream + ksr is propagated unchanged even when local sampling rules are configured. """ with test_library: incoming_headers = [ @@ -384,3 +403,27 @@ def test_sampling_extract_knuth_sample_rate_distributed_tracing_tracecontext( assert span["meta"].get("_dd.p.dm") == "-1" assert span["meta"].get("_dd.p.ksr") == "0.1" assert span["metrics"].get(SAMPLING_PRIORITY_KEY) == 2 + + @pytest.mark.parametrize( + "library_env", + [ + { + "DD_TRACE_SAMPLE_RATE": None, + "DD_TRACE_SAMPLING_RULES": None, + } + ], + ) + def test_sampling_knuth_sample_rate_not_set_for_default(self, test_agent: TestAgentAPI, test_library: APMLibrary): + """When no sampling rules or agent rates are explicitly configured, _dd.p.ksr + may or may not be present depending on how the tracer classifies the default + agent rate. If present, it must be "1" (the default rate of 1.0). + """ + with test_library: + with test_library.dd_start_span("span"): + pass + test_library.dd_flush() + + traces = test_agent.wait_for_num_traces(1) + span = find_only_span(traces) + ksr = span.get("meta", {}).get("_dd.p.ksr") + assert ksr is None or ksr == "1", f"If _dd.p.ksr is set for default sampling, it should be '1', got: {ksr}"