Skip to content

Commit

Permalink
w3c(phase 3): ensure last datadog parent id is always recorded (#3631)
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdinur authored Jun 7, 2024
1 parent 70e7fc4 commit c88f117
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
32 changes: 30 additions & 2 deletions lib/datadog/tracing/distributed/propagation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,22 @@ def extract(data)
# Only parse if it represent the same trace as the successfully extracted one
next unless tracecontext_digest.trace_id == extracted_trace_digest.trace_id

# Preserve the `tracestate`
parent_id = extracted_trace_digest.span_id
distributed_tags = extracted_trace_digest.trace_distributed_tags
unless extracted_trace_digest.span_id == tracecontext_digest.span_id
# span_id in the tracecontext header takes precedence over the value in all conflicting headers
parent_id = tracecontext_digest.span_id
if (lp_id = last_datadog_parent_id(data, tracecontext_digest.trace_distributed_tags))
distributed_tags = extracted_trace_digest.trace_distributed_tags&.dup || {}
distributed_tags[Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID] = lp_id
end
end
# Preserve the trace state and last datadog span id
extracted_trace_digest = extracted_trace_digest.merge(
span_id: parent_id,
trace_state: tracecontext_digest.trace_state,
trace_state_unknown_fields: tracecontext_digest.trace_state_unknown_fields
trace_state_unknown_fields: tracecontext_digest.trace_state_unknown_fields,
trace_distributed_tags: distributed_tags
)
end
rescue => e
Expand All @@ -115,6 +127,22 @@ def extract(data)

extracted_trace_digest
end

private

def last_datadog_parent_id(headers, tracecontext_tags)
dd_propagator = @propagation_style_extract.find { |propagator| propagator.is_a?(Datadog) }
if tracecontext_tags&.fetch(
Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID,
Tracing::Metadata::Ext::Distributed::DD_PARENT_ID_DEFAULT
) != Tracing::Metadata::Ext::Distributed::DD_PARENT_ID_DEFAULT
# tracecontext headers contain a p value, ensure this value is sent to backend
tracecontext_tags[Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID]
elsif dd_propagator && (dd_digest = dd_propagator.extract(headers))
# if p value is not present in tracestate, use the parent id from the datadog headers
format('%016x', dd_digest.span_id)
end
end
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/datadog/tracing/distributed/trace_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ def extract(data)
end

tags ||= {}
tags[Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID] = ts_parent_id || '0000000000000000'
tags[Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID] =
ts_parent_id || Tracing::Metadata::Ext::Distributed::DD_PARENT_ID_DEFAULT

TraceDigest.new(
span_id: parent_id,
Expand Down
1 change: 1 addition & 0 deletions lib/datadog/tracing/metadata/ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ module Distributed
TAG_SAMPLING_PRIORITY = '_sampling_priority_v1'

TAG_DD_PARENT_ID = '_dd.parent_id'
DD_PARENT_ID_DEFAULT = '0000000000000000'

# Trace tags with this prefix will propagate from a trace through distributed tracing.
# Distributed headers tags with this prefix will be injected into the active trace.
Expand Down
24 changes: 24 additions & 0 deletions spec/datadog/tracing/distributed/propagation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,30 @@
end
end
end

context 'and span_id is not matching' do
let(:data) { super().merge(prepare_key['x-datadog-parent-id'] => '15') }

context 'without tracestate' do
it 'extracts span_id from traceparent and stores x-datadog-parent-id in trace_distributed_tags' do
expect(trace_digest).to be_a_kind_of(Datadog::Tracing::TraceDigest)
expect(trace_digest.span_id).to eq(73456)
expect(trace_digest.trace_id).to eq(61185)
expect(trace_digest.trace_distributed_tags).to include('_dd.parent_id' => '000000000000000f')
end
end

context 'with tracestate' do
let(:data) { super().merge(prepare_key['tracestate'] => 'other=gg,dd=s:1;p:000000000000000a') }

it 'extracts span_id from traceparent and stores tracestate p value in trace_distributed_tags' do
expect(trace_digest).to be_a_kind_of(Datadog::Tracing::TraceDigest)
expect(trace_digest.span_id).to eq(73456)
expect(trace_digest.trace_id).to eq(61185)
expect(trace_digest.trace_distributed_tags).to eq({ '_dd.parent_id' => '000000000000000a' })
end
end
end
end
end

Expand Down

0 comments on commit c88f117

Please sign in to comment.