From 4b84a81da22d7dab5c31e20971aee9df88031ba1 Mon Sep 17 00:00:00 2001 From: Munir Date: Thu, 2 Jul 2026 13:59:24 -0400 Subject: [PATCH] [OTel] Enable NodeJS client side stats tests --- manifests/nodejs.yml | 4 +-- tests/parametric/test_otlp_trace_metrics.py | 34 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index bdb9e546293..426150110ec 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -99,6 +99,7 @@ refs: - &ref_5_107_0 '>=5.107.0' - &ref_5_109_0 '>=5.109.0' - &ref_5_110_0 '>=5.110.0' + - &ref_5_111_0 '>=5.111.0' - &ref_6_0_0 '>=6.0.0-pre' manifest: tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: @@ -2193,8 +2194,7 @@ manifest: tests/parametric/test_otel_span_methods.py::Test_Otel_Span_Methods::test_otel_start_span: missing_feature (New operation name mapping not yet implemented) tests/parametric/test_otel_span_with_baggage.py::Test_Otel_Span_With_Baggage: *ref_5_32_0 tests/parametric/test_otel_tracer.py::Test_Otel_Tracer::test_otel_force_flush: missing_feature (Not implemented) - tests/parametric/test_otlp_trace_metrics.py: missing_feature - tests/parametric/test_otlp_trace_metrics.py::Test_FR02_Mutual_Exclusion::test_fr02_4_native_stats_no_otlp: missing_feature (nodejs has not implemented native client-side /v0.6/stats computation) + tests/parametric/test_otlp_trace_metrics.py: *ref_5_111_0 tests/parametric/test_otlp_trace_metrics.py::Test_FR05_Sampling_Independence::test_fr05_1_metrics_computed_before_sampling: missing_feature (nodejs does not drop sampled-out traces when client-side stats are computed) tests/parametric/test_otlp_trace_metrics.py::Test_FR06_Otel_Resource_Attributes::test_fr06_10_hostname: irrelevant (DD_HOSTNAME is only supported in Python) tests/parametric/test_otlp_trace_metrics.py::Test_FR08_Datadog_Attributes::test_fr08_5_top_level_child_different_service: missing_feature (nodejs does not tag child spans with a different service than their parent as top-level) diff --git a/tests/parametric/test_otlp_trace_metrics.py b/tests/parametric/test_otlp_trace_metrics.py index bfa9e055aea..9b713bf42c0 100644 --- a/tests/parametric/test_otlp_trace_metrics.py +++ b/tests/parametric/test_otlp_trace_metrics.py @@ -1155,6 +1155,40 @@ def test_fr08_8_process_tags( f"Expected at least one datadog. resource attribute, got: {list(resource_attrs)}" ) + @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) + def test_fr08_9_top_level_not_mixed_with_measured( + self, + otlp_trace_metrics_library_env: dict[str, str], # noqa: ARG002 + test_agent: TestAgentAPI, + test_library: APMLibrary, + ): + """A top-level and a non-top-level span with identical dimensions bucket separately. + + The measured child (selected per FR04) shares every aggregation dimension with its top-level root, + yet the two must yield separate data points -- one datadog.span.top_level=true, one false -- rather + than being merged into a single bucket mislabeled false. + """ + with test_library as t: + with ( + t.dd_start_span(name="web.request", service=SERVICE, typestr="web") as parent, + t.dd_start_span(name="web.request", service=SERVICE, typestr="web", parent_id=parent.span_id) as child, + ): + child.set_metric(SPAN_MEASURED_KEY, 1) + t.dd_flush() + + metrics = test_agent.wait_for_num_otlp_metrics(num=1) + points = [ + dp + for dp in _duration_data_points(metrics) + if _data_point_attrs(dp).get("datadog.operation.name") == "web.request" + ] + top_level_flags = {_data_point_attrs(dp).get("datadog.span.top_level") for dp in points} + assert top_level_flags == {True, False}, ( + "Top-level and non-top-level measured spans sharing the same aggregation dimensions must bucket " + "separately, each keeping its datadog.span.top_level flag; expected both a true and a false data " + f"point, got: {[_data_point_attrs(dp) for dp in points]}" + ) + @scenarios.parametric @features.client_side_stats_supported