From 7e6886eed2fbfcfcee05ca22c6d3b57e1233577d Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Tue, 16 Jun 2026 18:47:39 -0400 Subject: [PATCH] test(parametric): enable Python FFE span-enrichment suite Honor span_id in the Python parametric /ffe/evaluate handler so ffe_* tags land on the test's root span, and flip the six class-level missing_feature entries in manifests/python.yml so the frozen test_span_enrichment.py classes run and assert for Python (>=4.9.0; validated against ddtrace 4.12.0rc1). Validated locally: TEST_LIBRARY=python ./run.sh PARAMETRIC -k span_enrichment -> 18 passed (8 enrichment classes), 0 skipped. --- manifests/python.yml | 6 ------ .../python/parametric/apm_test_client/server.py | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/manifests/python.yml b/manifests/python.yml index 360741e1019..e58b0430a61 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1831,12 +1831,6 @@ manifest: component_version: '>3.7.0' tests/parametric/test_ffe/test_dynamic_evaluation.py::Test_Feature_Flag_Dynamic_Evaluation: v4.0.0 tests/parametric/test_ffe/test_span_enrichment.py: '>=4.9.0' # TODO: a lower version might be supported - tests/parametric/test_ffe/test_span_enrichment.py::Test_Span_Enrichment_Child_Span_Propagation: missing_feature - tests/parametric/test_ffe/test_span_enrichment.py::Test_Span_Enrichment_Default_Fallback: missing_feature - tests/parametric/test_ffe/test_span_enrichment.py::Test_Span_Enrichment_Max_Experiments_Per_Subject: missing_feature - tests/parametric/test_ffe/test_span_enrichment.py::Test_Span_Enrichment_Max_Serial_IDs: missing_feature - tests/parametric/test_ffe/test_span_enrichment.py::Test_Span_Enrichment_Serial_IDs: missing_feature - tests/parametric/test_ffe/test_span_enrichment.py::Test_Span_Enrichment_Subjects: missing_feature tests/parametric/test_headers_b3.py::Test_Headers_B3: v2.8.0 tests/parametric/test_headers_b3.py::Test_Headers_B3::test_headers_b3_extract_invalid: - declaration: irrelevant (Deprecated in 3.x) diff --git a/utils/build/docker/python/parametric/apm_test_client/server.py b/utils/build/docker/python/parametric/apm_test_client/server.py index e5c491c33e4..181e02a4178 100644 --- a/utils/build/docker/python/parametric/apm_test_client/server.py +++ b/utils/build/docker/python/parametric/apm_test_client/server.py @@ -1431,9 +1431,24 @@ async def ffe_evaluate(request: Request) -> JSONResponse: default_value = body.get("defaultValue") targeting_key = body.get("targetingKey") attributes = body.get("attributes", {}) + # span_id is sent by the test client as a STRING (see _test_client_parametric.py:814-815); + # re-activate the caller-supplied root span around the eval so the ffe_* tags (Phase 2) land + # on the test's span. Unknown/missing/unparsable id -> skip activation, never throw (T-01-DOS). + span_id = body.get("span_id") # Build context context = EvaluationContext(targeting_key=targeting_key, attributes=attributes) + # Look up the registered span and re-activate it for the duration of the eval, reusing the + # same context-activation primitive that /trace/span/start's start_span(activate=True) relies on. + target_span = None + if span_id is not None: + try: + target_span = spans.get(int(span_id)) + except (TypeError, ValueError): + target_span = None + if target_span is not None: + ddtrace.tracer.context_provider.activate(target_span) + # Evaluate based on variation type value = default_value reason = "DEFAULT"