Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion manifests/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2129,7 +2129,7 @@ manifest:
tests/parametric/test_dynamic_configuration.py::TestDynamicConfigV2::test_capability_tracing_custom_tags: missing_feature # Created by easy win activation script
tests/parametric/test_dynamic_configuration.py::TestDynamicConfigV2::test_tracing_client_tracing_tags: missing_feature # Created by easy win activation script
tests/parametric/test_ffe/test_dynamic_evaluation.py::Test_Feature_Flag_Dynamic_Evaluation: v2.23.0
tests/parametric/test_ffe/test_span_enrichment.py: missing_feature
tests/parametric/test_ffe/test_span_enrichment.py: v2.36.0-dev
tests/parametric/test_headers_b3.py::Test_Headers_B3::test_headers_b3_extract_invalid: # Easy win for all weblogs and version 2.27.0
- declaration: missing_feature (Missing for 2.x)
component_version: '>1.99.0'
Expand Down
28 changes: 26 additions & 2 deletions utils/build/docker/ruby/parametric/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -816,14 +816,17 @@ def to_json(*_args)
end

class OpenFeatureArgs
attr_reader :flag, :variation_type, :default_value, :targeting_key, :attributes
attr_reader :flag, :variation_type, :default_value, :targeting_key, :attributes, :span_id

def initialize(params)
@flag = params['flag']
@variation_type = params['variationType']
@default_value = params['defaultValue']
@targeting_key = params['targetingKey']
@attributes = params['attributes']
# The test client sends span_id as a STRING (see _test_client_parametric.py:814-815). DD_SPANS is
# keyed by the integer span id (handle_trace_span_start: DD_SPANS[span.id]); cast for the lookup.
@span_id = params['span_id'].nil? ? nil : Integer(params['span_id'], exception: false)
end
end

Expand Down Expand Up @@ -872,7 +875,7 @@ def handle_ffe_evaluation(req, res)
flag_key: args.flag, default_value: args.default_value, evaluation_context: context
}

value =
evaluate = lambda do
case args.variation_type
when 'BOOLEAN'then client.fetch_boolean_value(**options)
when 'STRING' then client.fetch_string_value(**options)
Expand All @@ -881,6 +884,27 @@ def handle_ffe_evaluation(req, res)
when 'JSON' then client.fetch_object_value(**options)
else 'FATAL_UNEXPECTED_VARIATION_TYPE'
end
end

# Re-activate the caller-supplied span's LIVE trace around the eval so the span-enrichment
# hook (Phase 2) accumulates onto the test's real root span. This is the in-process
# equivalent of the Node reference's `tracer.scope().activate(span, fn)`
# (utils/build/docker/nodejs/parametric/server.js): the hook keys its accumulator and its
# `span_before_finish` subscription by the ACTIVE TraceOperation, so every /ffe/evaluate call
# must run on the SAME live trace as the root span. Using `continue_from:` instead would fork a
# fresh TraceOperation per call -- each eval would land on a throwaway root and the test's root
# span would aggregate nothing. An unknown/missing span_id falls through to a plain eval --
# never throw (T-01-DOS).
trace_op =
if !args.span_id.nil? && (span = DD_SPANS[args.span_id])
DD_TRACES[span.trace_id]
end
value =
if trace_op
Datadog::Tracing.send(:tracer).send(:call_context).activate!(trace_op) { evaluate.call }
else
evaluate.call
end

res.write({value: value, reason: 'DEFAULT'}.to_json)
rescue => e
Expand Down
Loading