Skip to content

Commit

Permalink
Extract helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyCTHsu committed Mar 2, 2023
1 parent 52c7a9a commit 4f8a8ad
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 196 deletions.
2 changes: 1 addition & 1 deletion lib/datadog/opentracer/distributed_headers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def origin

def id(header)
value = @carrier[header].to_i
return if value.zero? || value >= Datadog::Tracing::Utils::TraceId::MAX_ID
return if value.zero? || value > Datadog::Tracing::Utils::EXTERNAL_MAX_ID

value < 0 ? value + 0x1_0000_0000_0000_0000 : value
end
Expand Down
17 changes: 12 additions & 5 deletions lib/datadog/tracing/distributed/b3_multi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative 'helpers'
require_relative '../trace_digest'
require_relative '../utils'

module Datadog
module Tracing
Expand Down Expand Up @@ -45,13 +46,19 @@ def inject!(digest, data = {})
def extract(data)
# DEV: B3 doesn't have "origin"
fetcher = @fetcher.new(data)
trace_id = Helpers.parse_hex_id(fetcher[@trace_id_key], length: 32)
span_id = Helpers.parse_hex_id(fetcher[@span_id_key], length: 16)
# We don't need to try and convert sampled since B3 supports 0/1 (AUTO_REJECT/AUTO_KEEP)
sampling_priority = Helpers.parse_decimal_id(fetcher[@sampled_key])

trace_id = Helpers.parse_hex_id(fetcher[@trace_id_key])

# Return early if this propagation is not valid
return unless trace_id && span_id
return if trace_id.nil? || trace_id <= 0 || trace_id > Tracing::Utils::TraceId::MAX

span_id = Helpers.parse_hex_id(fetcher[@span_id_key])

# Return early if this propagation is not valid
return if span_id.nil? || span_id <= 0 || span_id >= Tracing::Utils::EXTERNAL_MAX_ID

# We don't need to try and convert sampled since B3 supports 0/1 (AUTO_REJECT/AUTO_KEEP)
sampling_priority = Helpers.parse_decimal_id(fetcher[@sampled_key])

TraceDigest.new(
trace_id: trace_id,
Expand Down
13 changes: 8 additions & 5 deletions lib/datadog/tracing/distributed/b3_single.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ def extract(env)
return unless value

parts = value.split('-')
trace_id = Helpers.parse_hex_id(parts[0], length: 32) unless parts.empty?
span_id = Helpers.parse_hex_id(parts[1], length: 16) if parts.length > 1
sampling_priority = Helpers.parse_decimal_id(parts[2]) if parts.length > 2
trace_id = Helpers.parse_hex_id(parts[0]) unless parts.empty?
# Return early if this propagation is not valid
return if trace_id.nil? || trace_id <= 0 || trace_id > Tracing::Utils::TraceId::MAX

span_id = Helpers.parse_hex_id(parts[1]) if parts.length > 1
# Return early if this propagation is not valid
return if span_id.nil? || span_id <= 0 || span_id >= Tracing::Utils::EXTERNAL_MAX_ID

# Return if this propagation is not valid
return unless trace_id && span_id
sampling_priority = Helpers.parse_decimal_id(parts[2]) if parts.length > 2

TraceDigest.new(
span_id: span_id,
Expand Down
23 changes: 21 additions & 2 deletions lib/datadog/tracing/distributed/datadog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ def inject!(digest, data)
def extract(data)
fetcher = @fetcher.new(data)

trace_id = Helpers.parse_decimal_id(fetcher[@trace_id_key])
parent_id = Helpers.parse_decimal_id(fetcher[@parent_id_key])
trace_id = parse_trace_id(fetcher)
parent_id = parse_parent_id(fetcher)

sampling_priority = Helpers.parse_decimal_id(fetcher[@sampling_priority_key])
origin = fetcher[@origin_key]

Expand All @@ -84,6 +85,24 @@ def extract(data)

private

def parse_trace_id(fetcher_object)
trace_id = Helpers.parse_decimal_id(fetcher_object[@trace_id_key])

return unless trace_id
return if trace_id <= 0 || trace_id >= Tracing::Utils::EXTERNAL_MAX_ID

trace_id
end

def parse_parent_id(fetcher_object)
parent_id = Helpers.parse_decimal_id(fetcher_object[@parent_id_key])

return unless parent_id
return if parent_id <= 0 || parent_id >= Tracing::Utils::EXTERNAL_MAX_ID

parent_id
end

def build_tags(digest)
high_order = Tracing::Utils::TraceId.to_high_order(digest.trace_id)
tags = digest.trace_distributed_tags || {}
Expand Down
30 changes: 15 additions & 15 deletions lib/datadog/tracing/distributed/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ def self.clamp_sampling_priority(sampling_priority)
sampling_priority
end

def self.format_base16_number(value)
# Lowercase if we want to parse base16 e.g. 3E8 => 3e8
# DEV: Ruby will parse `3E8` just fine, but to test
# `num.to_s(base) == value` we need to lowercase
value = value.downcase

# Remove any leading zeros
# DEV: When we call `num.to_s(16)` later Ruby will not add leading zeros
# for us so we want to make sure the comparision will work as expected
# DEV: regex, remove all leading zeros up until we find the last 0 in the string
# or we find the first non-zero, this allows `'0000' -> '0'` and `'00001' -> '1'`
value.sub(/^0*(?=(0$)|[^0])/, '')
end
# def self.format_base16_number(value)
# # Lowercase if we want to parse base16 e.g. 3E8 => 3e8
# # DEV: Ruby will parse `3E8` just fine, but to test
# # `num.to_s(base) == value` we need to lowercase
# value = value.downcase

# # Remove any leading zeros
# # DEV: When we call `num.to_s(16)` later Ruby will not add leading zeros
# # for us so we want to make sure the comparision will work as expected
# # DEV: regex, remove all leading zeros up until we find the last 0 in the string
# # or we find the first non-zero, this allows `'0000' -> '0'` and `'00001' -> '1'`
# value.sub(/^0*(?=(0$)|[^0])/, '')
# end

# def self.value_to_id(value, base: 10)
# id = value_to_number(value, base: base)
Expand Down Expand Up @@ -78,11 +78,11 @@ def self.parse_decimal_id(value)
num
end

def self.parse_hex_id(value, length: )
def self.parse_hex_id(value, length: nil)
return unless value

value = value.to_s.downcase
value = value[value.length - length, length] if value.length > length
value = value[value.length - length, length] if length && value.length > length
value = value.sub(/^0*(?=(0$)|[^0])/, '')

num = value.to_i(16)
Expand Down
2 changes: 1 addition & 1 deletion spec/datadog/tracing/correlation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def have_attribute(attribute)

it do
is_expected.to have_attribute(
"#{Datadog::Tracing::Correlation::Identifier::LOG_ATTR_TRACE_ID}=0xffffffffffffffffaaaaaaaaaaaaaaaa"
"#{Datadog::Tracing::Correlation::Identifier::LOG_ATTR_TRACE_ID}=ffffffffffffffffaaaaaaaaaaaaaaaa"
)
end
end
Expand Down
45 changes: 41 additions & 4 deletions spec/datadog/tracing/distributed/b3_multi_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,7 @@
let(:digest) do
Datadog::Tracing::TraceDigest.new(
trace_id: 0xaaaaaaaaaaaaaaaaffffffffffffffff,
span_id: 0xbbbbbbbbbbbbbbbb,
# trace_distributed_tags: {
# '_dd.p.tid' => 'aaaaaaaaaaaaaaaa'
# }
span_id: 0xbbbbbbbbbbbbbbbb
)
end

Expand Down Expand Up @@ -144,6 +141,46 @@
it { expect(digest.trace_sampling_priority).to be nil }
it { expect(digest.trace_origin).to be nil }
end

context 'when given invalid trace id' do
[
((1 << 128)).to_s(16), # 0
((1 << 128) + 1).to_s(16),
'0',
'-1',
].each do |invalid_trace_id|
context "when given trace id: #{invalid_trace_id}" do
let(:data) do
{
prepare_key['x-b3-traceid'] => invalid_trace_id,
prepare_key['x-b3-spanid'] => 20000.to_s(16)
}
end

it { is_expected.to be nil }
end
end
end

context 'when given invalid span id' do
[
((1 << 64)).to_s(16),
((1 << 64) + 1).to_s(16),
'0',
'-1',
].each do |invalid_span_id|
context "when given span id: #{invalid_span_id}" do
let(:data) do
{
prepare_key['x-b3-traceid'] => 10000.to_s(16),
prepare_key['x-b3-spanid'] => invalid_span_id,
}
end

it { is_expected.to be nil }
end
end
end
end

context 'with span_id' do
Expand Down
62 changes: 44 additions & 18 deletions spec/datadog/tracing/distributed/b3_single_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,21 @@
context 'with origin' do
let(:digest) do
Datadog::Tracing::TraceDigest.new(
span_id: 100000,
trace_id: 90000,
trace_id: 0xabcdef,
span_id: 0xfedcba,
trace_origin: 'synthetics'
)
end

it { expect(data).to eq(b3_single_header => '15f90-186a0') }
it { expect(data).to eq(b3_single_header => 'abcdef-fedcba') }
end
end

context 'with 128 bits trace id and distributed tag `_dd.p.tid`' do
let(:digest) do
Datadog::Tracing::TraceDigest.new(
trace_id: 0xaaaaaaaaaaaaaaaaffffffffffffffff,
span_id: 0xbbbbbbbbbbbbbbbb,
# trace_distributed_tags: {
# '_dd.p.tid' => 'aaaaaaaaaaaaaaaa'
# }
span_id: 0xbbbbbbbbbbbbbbbb
)
end

Expand All @@ -92,42 +89,71 @@
end

context 'with trace_id and span_id' do
let(:data) { { prepare_key[b3_single_header] => '15f90-186a0' } }
let(:data) { { prepare_key[b3_single_header] => 'abcdef-fedcba' } }

it { expect(digest.span_id).to eq(100000) }
it { expect(digest.trace_id).to eq(90000) }
it { expect(digest.trace_id).to eq(0xabcdef) }
it { expect(digest.span_id).to eq(0xfedcba) }
it { expect(digest.trace_origin).to be nil }
it { expect(digest.trace_sampling_priority).to be nil }

context 'with sampling priority' do
let(:data) { { prepare_key[b3_single_header] => '15f90-186a0-1' } }
let(:data) { { prepare_key[b3_single_header] => 'abcdef-fedcba-1' } }

it { expect(digest.span_id).to eq(100000) }
it { expect(digest.trace_id).to eq(90000) }
it { expect(digest.trace_id).to eq(0xabcdef) }
it { expect(digest.span_id).to eq(0xfedcba) }
it { expect(digest.trace_origin).to be nil }
it { expect(digest.trace_sampling_priority).to eq(1) }

context 'with parent_id' do
let(:data) do
{
prepare_key[b3_single_header] => '15f90-186a0-1-4e20'
prepare_key[b3_single_header] => 'abcdef-fedcba-1-4e20'
}
end

it { expect(digest.trace_id).to eq(90000) }
it { expect(digest.span_id).to eq(100000) }
it { expect(digest.trace_id).to eq(0xabcdef) }
it { expect(digest.span_id).to eq(0xfedcba) }
it { expect(digest.trace_sampling_priority).to eq(1) }
it { expect(digest.trace_origin).to be nil }
end
end

context 'when given invalid trace id' do
[
((1 << 128)).to_s(16), # 0
((1 << 128) + 1).to_s(16),
'0',
'-1',
].each do |invalid_trace_id|
context "when given trace id: #{invalid_trace_id}" do
let(:data) { { prepare_key[b3_single_header] => "#{invalid_trace_id}-fedcba" } }

it { is_expected.to be nil }
end
end
end

context 'when given invalid span id' do
[
((1 << 64)).to_s(16),
((1 << 64) + 1).to_s(16),
'0',
].each do |invalid_span_id|
context "when given span id: #{invalid_span_id}" do
let(:data) { { prepare_key[b3_single_header] => "abcdef-#{invalid_span_id}" } }

it { is_expected.to be nil }
end
end
end
end

context 'with trace_id' do
let(:data) { { prepare_key[b3_single_header] => '15f90' } }
let(:data) { { prepare_key[b3_single_header] => 'abcdef' } }

it { is_expected.to be nil }

context 'with trace id of 128 bits' do
context 'with 128 bits trace id and 64 bits span id' do
let(:data) do
{ prepare_key[b3_single_header] => 'aaaaaaaaaaaaaaaaffffffffffffffff-bbbbbbbbbbbbbbbb' }
end
Expand Down
34 changes: 34 additions & 0 deletions spec/datadog/tracing/distributed/datadog_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,40 @@
end
end
end

context 'when given invalid trace_id' do
[
(1 << 64).to_s,
'0',
'-1'
].each do |invalid_trace_id|
context "when given invalid trace_id: #{invalid_trace_id}" do
let(:data) do
{ prepare_key['x-datadog-trace-id'] => invalid_trace_id,
prepare_key['x-datadog-parent-id'] => '20000' }
end

it { is_expected.to be nil }
end
end
end

context 'when given invalid span_id' do
[
(1 << 64).to_s,
'0',
'-1'
].each do |invalid_span_id|
context "when given invalid span_id: #{invalid_span_id}" do
let(:data) do
{ prepare_key['x-datadog-trace-id'] => '10000',
prepare_key['x-datadog-parent-id'] => invalid_span_id }
end

it { is_expected.to be nil }
end
end
end
end

context 'with span_id' do
Expand Down
Loading

0 comments on commit 4f8a8ad

Please sign in to comment.