diff --git a/sdk/lib/opentelemetry/sdk/internal.rb b/sdk/lib/opentelemetry/sdk/internal.rb index fae806960c..bd338b78fa 100644 --- a/sdk/lib/opentelemetry/sdk/internal.rb +++ b/sdk/lib/opentelemetry/sdk/internal.rb @@ -25,27 +25,34 @@ def numeric?(value) end def valid_simple_value?(value) - value.instance_of?(String) || boolean?(value) || numeric?(value) + value.instance_of?(String) || boolean?(value) || numeric?(value) || value.nil? end - def valid_array_value?(value) - return false unless value.is_a?(Array) - return true if value.empty? + def valid_value?(value) + to_check = [value] + seen = Set.new + until to_check.empty? + current = to_check.pop + next if valid_simple_value?(current) - case value.first - when String - value.all? { |v| v.instance_of?(String) } - when TrueClass, FalseClass - value.all? { |v| boolean?(v) } - when Numeric - value.all? { |v| numeric?(v) } - else - false - end - end + return false if seen.include?(current.object_id) - def valid_value?(value) - valid_simple_value?(value) || valid_array_value?(value) + seen << current.object_id + + case current + when Array + current.each { |v| to_check << v } + when Hash + current.each do |k, v| + return false unless valid_key?(k) + + to_check << v + end + else + return false + end + end + true end def valid_attributes?(owner, kind, attrs) diff --git a/sdk/test/opentelemetry/sdk/trace/span_test.rb b/sdk/test/opentelemetry/sdk/trace/span_test.rb index 396d9e3ee4..aac2e3c506 100644 --- a/sdk/test/opentelemetry/sdk/trace/span_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/span_test.rb @@ -114,11 +114,11 @@ end end - it 'reports an error for a NilClass value, which is invalid' do + it 'does not report an error for a NilClass value, as empty values are valid' do OpenTelemetry::TestHelpers.with_test_logger do |log_stream| span.set_attribute('foo', nil) span.finish - _(log_stream.string).must_match(/invalid span attribute value type NilClass for key 'foo' on span 'name'/) + _(log_stream.string.length).must_equal(0) end end @@ -223,12 +223,12 @@ _(events.first.attributes).must_equal(attrs) end - it 'does not keep nil-valued attributes' do + it 'keeps nil-valued attributes' do attrs = { 'foo' => nil } span.add_event('added', attributes: attrs) events = span.events _(events.size).must_equal(1) - _(events.first.attributes).must_equal({}) + _(events.first.attributes).must_equal({ 'foo' => nil }) end it 'accepts array-valued attributes' do @@ -247,12 +247,12 @@ _(events.first.attributes).must_equal({}) end - it 'does not accept array-valued attributes if the elements are different types' do + it 'accepts array-valued attributes even if the elements are different types' do attrs = { 'foo' => [1, 2, 'bar'] } span.add_event('added', attributes: attrs) events = span.events _(events.size).must_equal(1) - _(events.first.attributes).must_equal({}) + _(events.first.attributes).must_equal({ 'foo' => [1, 2, 'bar'] }) end it 'accepts array-valued attributes if the elements are true and false' do