Skip to content

Enable Ruby FFE APM span-enrichment parametric tests#7151

Draft
leoromanovsky wants to merge 1 commit into
mainfrom
leo.romanovsky/ffe-enrichment-enable-ruby
Draft

Enable Ruby FFE APM span-enrichment parametric tests#7151
leoromanovsky wants to merge 1 commit into
mainfrom
leo.romanovsky/ffe-enrichment-enable-ruby

Conversation

@leoromanovsky

Copy link
Copy Markdown
Contributor

Motivation

The FFE APM feature-flag span-enrichment contract (frozen against dd-trace-js#8343)
is now implemented in the Ruby tracer (DataDog/dd-trace-rb#5910). This PR enables the
existing frozen parametric suite tests/parametric/test_ffe/test_span_enrichment.py
for Ruby so the harness asserts Ruby's ffe_* tags (ffe_flags_enc,
ffe_subjects_enc, ffe_runtime_defaults) stay in parity with the backend/Trino
decode and the Node.js reference.

Changes

Two language-scoped changes, no cross-language drift:

  1. utils/build/docker/ruby/parametric/server.rb — the /ffe/evaluate handler now
    re-activates the caller-supplied span's live TraceOperation around the
    evaluation (the in-process equivalent of the Node reference's
    tracer.scope().activate(span, fn) in utils/build/docker/nodejs/parametric/server.js).

    • OpenFeatureArgs now reads span_id (cast to Integer — the test client sends it as
      a string, DD_SPANS is keyed by integer span id).
    • The eval runs via call_context.activate!(trace_op) { ... } so the SDK's
      SpanEnrichmentHook — which keys its accumulator and its span_before_finish
      subscription by the active TraceOperation — aggregates every flag onto the
      test's real root span.
    • Missing/unknown span_id falls through to a plain eval; never raises.
  2. manifests/ruby.yml — flip tests/parametric/test_ffe/test_span_enrichment.py
    from missing_feature to v2.36.0-dev.

Decisions

  • Why call_context.activate! and not continue_from: — a continue_from: digest
    starts a new TraceOperation per call (Tracer#continue_trace!
    start_trace(continue_from:)). Each /ffe/evaluate would then land on a throwaway
    forked root span, so multi-flag / multi-subject / child-span tests would aggregate
    nothing onto the test's actual root. Activating the stored live trace keeps all evals
    on the one trace the test created — matching the Node reference behavior exactly. This
    was a parametric-app harness fix; no dd-trace-rb source change was needed.

  • Limit-test parity — serial IDs (200), subjects (10), experiments/subject (20),
    runtime defaults (5), 64-char value truncation all pass against the frozen assertions.

Validation results

Run locally against the dd-trace-rb#5910 gem (datadog-2.36.0.dev,
libdatadog-33.0.0.1.0):

TEST_LIBRARY=ruby ./run.sh PARAMETRIC -k span_enrichment
...
============================= 18 passed in 30.48s ==============================

All 18 cases green: delta-varint codec (5), serial-ID/subject aggregation, multiple
subjects tracked separately, child-span→root propagation, SHA256 subject hashing,
__dd_do_log gating, runtime-default detection + 64-char truncation, and all frozen
limits.

Host-arch note (not a code issue): utils/build/docker/ruby/parametric/Dockerfile
pins FROM --platform=linux/amd64. On an arm64 host the in-container native-ext build
of ext/libdatadog_api/di.c segfaults under QEMU x86_64 emulation
(make: *** [di.o] Segmentation fault). The 18-passing run above was produced on arm64
using a local-only workaround (dropping the --platform pin so the ext compiles
natively); that workaround is intentionally not part of this PR. The server.rb
delta validated is byte-identical to the one in this PR, and the gem/enrichment behavior
is platform-independent — so CI (amd64) exercises the same code path. Flagging the host
QEMU bug explicitly so the PR is not blocked on it.

Activate the test span-enrichment suite for the Ruby tracer by:

- Re-activating the caller-supplied span's live trace around each /ffe/evaluate
  in the parametric app (server.rb), so the SpanEnrichmentHook accumulates flag
  metadata onto the test's real root span. This mirrors the Node reference's
  tracer.scope().activate(span, fn). The prior continue_from: approach forked a
  fresh TraceOperation per eval, so multi-flag / multi-subject / child-span
  aggregation never landed on the test's root span.
- Flipping tests/parametric/test_ffe/test_span_enrichment.py in manifests/ruby.yml
  from missing_feature to v2.36.0-dev.
@github-actions

Copy link
Copy Markdown
Contributor

CODEOWNERS have been resolved as:

manifests/ruby.yml                                                      @DataDog/ruby-guild @DataDog/asm-ruby
utils/build/docker/ruby/parametric/server.rb                            @DataDog/ruby-guild @DataDog/asm-ruby @DataDog/system-tests-core

@datadog-prod-us1-6

datadog-prod-us1-6 Bot commented Jun 16, 2026

Copy link
Copy Markdown

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 3 Pipeline jobs failed

Testing the test | System Tests (ruby, dev) / parametric / parametric (2)   View in Datadog   GitHub Actions

🧪 12 Tests failed

tests.parametric.test_ffe.test_span_enrichment.Test_Span_Enrichment_Child_Span_Propagation.test_child_span_flag_evaluation_propagates_to_root[library_env0, parametric-ruby] from system_tests_suite   View in Datadog
AssertionError: ffe_flags_enc not found in root span meta: ['_dd.base_service', '_dd.svc_src', '_dd.p.dm', '_dd.p.ksr', 'language', 'runtime-id', '_dd.p.tid']
assert 'ffe_flags_enc' in {'_dd.base_service': 'server', '_dd.p.dm': '-0', '_dd.p.ksr': '1', '_dd.p.tid': '6a31df1500000000', ...}

self = <tests.parametric.test_ffe.test_span_enrichment.Test_Span_Enrichment_Child_Span_Propagation object at 0x7fbb8e596000>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fbb5e09c290>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fbb5e5d6300>

    @parametrize("library_env", [{**DEFAULT_ENVVARS}])
    def test_child_span_flag_evaluation_propagates_to_root(
        self, test_agent: TestAgentAPI, test_library: APMLibrary
...
tests.parametric.test_ffe.test_span_enrichment.Test_Span_Enrichment_Default_Fallback.test_ffe_runtime_defaults_value_truncated_at_64_chars[library_env0, parametric-ruby] from system_tests_suite   View in Datadog
AssertionError: ffe_runtime_defaults not found in span meta: ['_dd.base_service', '_dd.svc_src', '_dd.p.dm', '_dd.p.ksr', 'language', 'runtime-id', '_dd.p.tid', '_dd.tags.process']
assert 'ffe_runtime_defaults' in {'_dd.base_service': 'server', '_dd.p.dm': '-0', '_dd.p.ksr': '1', '_dd.p.tid': '6a31df1d00000000', ...}

self = <tests.parametric.test_ffe.test_span_enrichment.Test_Span_Enrichment_Default_Fallback object at 0x7fcdcafd59a0>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fcdca0f6300>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fcdca4f7890>

    @parametrize("library_env", [{**DEFAULT_ENVVARS}])
    def test_ffe_runtime_defaults_value_truncated_at_64_chars(
        self, test_agent: TestAgentAPI, test_library: APMLibrary
...
View all 12 test failures

Testing the test | System Tests (cpp_kong, dev) / Build end-to-end (kong)   View in Datadog   GitHub Actions

Testing the test | all-jobs-are-green   View in Datadog   GitHub Actions

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 8cafaf0 | Docs | Datadog PR Page | Give us feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant