Skip to content

Commit

Permalink
Merge pull request #2289 from DataDog/fix/opentracing_context_propaga…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
marcotc committed Sep 27, 2022
1 parent ff4b5e5 commit 1048c1d
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 101 deletions.
10 changes: 4 additions & 6 deletions lib/datadog/opentracer/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,10 @@ def start_span(
tags: tags || {}
)

# Build or extend the OpenTracer::SpanContext
span_context = if parent_span_context
SpanContextFactory.clone(span_context: parent_span_context)
else
SpanContextFactory.build(datadog_context: datadog_context)
end
span_context = SpanContextFactory.build(
datadog_context: datadog_context || datadog_tracer.send(:call_context),
baggage: parent_span_context ? parent_span_context.baggage.dup : {}
)

# Wrap the Datadog span and OpenTracer::Span context in a OpenTracer::Span
Span.new(datadog_span: datadog_span, span_context: span_context)
Expand Down
227 changes: 132 additions & 95 deletions spec/datadog/opentracer/propagation_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@
datadog_tracer.shutdown!
end

def sampling_priority_metric(span)
span.get_metric(Datadog::OpenTracer::TextMapPropagator::TAG_SAMPLING_PRIORITY)
end

def origin_tag(span)
span.get_tag(Datadog::OpenTracer::TextMapPropagator::TAG_ORIGIN)
end

describe 'via OpenTracing::FORMAT_TEXT_MAP' do
def baggage_to_carrier_format(baggage)
baggage.map { |k, v| [Datadog::OpenTracer::TextMapPropagator::BAGGAGE_PREFIX + k, v] }.to_h
Expand Down Expand Up @@ -120,69 +112,91 @@ def baggage_to_carrier_format(baggage)
end

context 'in a round-trip' do
let(:sender_span_name) { 'operation.sender' }
let(:sender_datadog_span) { datadog_spans.last }
let(:receiver_datadog_span) { datadog_spans.first }
let(:receiver_span_name) { 'operation.receiver' }
let(:baggage) { { 'account_name' => 'acme' } }
let(:carrier) { {} }
let(:another_carrier) { {} }
let(:datadog_sender_trace) { datadog_traces.last }
let(:datadog_receiver_trace) { datadog_traces.first }
let(:origin_span_name) { 'operation.origin' }
let(:origin_datadog_trace) { datadog_traces.find { |x| x.name == origin_span_name } }
let(:origin_datadog_span) { datadog_spans.find { |x| x.name == origin_span_name } }

before do
tracer.start_active_span(sender_span_name) do |sender_scope|
sender_scope.span.context.datadog_context.active_trace.sampling_priority = 1
sender_scope.span.context.datadog_context.active_trace.origin = 'synthetics'
baggage.each { |k, v| sender_scope.span.set_baggage_item(k, v) }
tracer.inject(
sender_scope.span.context,
OpenTracing::FORMAT_TEXT_MAP,
carrier
)
let(:intermediate_span_name) { 'operation.intermediate' }
let(:intermediate_datadog_trace) { datadog_traces.find { |x| x.name == intermediate_span_name } }
let(:intermediate_datadog_span) { datadog_spans.find { |x| x.name == intermediate_span_name } }

span_context = tracer.extract(OpenTracing::FORMAT_TEXT_MAP, carrier)
tracer.start_active_span(receiver_span_name, child_of: span_context) do |receiver_scope|
@receiver_scope = receiver_scope
# Do some work.
let(:destination_span_name) { 'operation.destination' }
let(:destination_datadog_trace) { datadog_traces.find { |x| x.name == destination_span_name } }
let(:destination_datadog_span) { datadog_spans.find { |x| x.name == destination_span_name } }

tracer.inject(receiver_scope.span.context, OpenTracing::FORMAT_TEXT_MAP, another_carrier)
let(:baggage) { { 'account_name' => 'acme' } }

before do
tracer.start_active_span(origin_span_name) do |origin_scope|
origin_datadog_context = origin_scope.span.context.datadog_context
origin_datadog_context.active_trace.sampling_priority = 1
origin_datadog_context.active_trace.origin = 'synthetics'
baggage.each { |k, v| origin_scope.span.set_baggage_item(k, v) }

@origin_carrier = {}.tap do |c|
tracer.inject(origin_scope.span.context, OpenTracing::FORMAT_TEXT_MAP, c)
end
origin_datadog_context.activate!(nil) do
tracer.start_active_span(
intermediate_span_name,
child_of: tracer.extract(OpenTracing::FORMAT_TEXT_MAP, @origin_carrier)
) do |intermediate_scope|
@intermediate_scope = intermediate_scope

@intermediate_carrier = {}.tap do |c|
tracer.inject(intermediate_scope.span.context, OpenTracing::FORMAT_TEXT_MAP, c)
end

tracer.start_active_span(
destination_span_name,
child_of: tracer.extract(OpenTracing::FORMAT_TEXT_MAP, @intermediate_carrier)
) do |destination_scope|
@destination_scope = destination_scope
# Do something
end
end
end
end
end

it { expect(datadog_spans).to have(2).items }
it { expect(datadog_traces).to have(3).items }
it { expect(datadog_spans).to have(3).items }

it { expect(datadog_sender_trace.sampling_priority).to eq(1) }
it { expect(datadog_sender_trace.origin).to eq('synthetics') }
it { expect(sender_datadog_span.name).to eq(sender_span_name) }
it { expect(sender_datadog_span.finished?).to be(true) }
it { expect(sender_datadog_span.parent_id).to eq(0) }
it { expect(origin_datadog_trace.sampling_priority).to eq(1) }
it { expect(origin_datadog_trace.origin).to eq('synthetics') }
it { expect(origin_datadog_span.finished?).to be(true) }
it { expect(origin_datadog_span.parent_id).to eq(0) }

it { expect(datadog_receiver_trace.sampling_priority).to eq(1) }
it { expect(datadog_receiver_trace.origin).to eq('synthetics') }
it { expect(receiver_datadog_span.name).to eq(receiver_span_name) }
it { expect(receiver_datadog_span.finished?).to be(true) }
it { expect(receiver_datadog_span.trace_id).to eq(sender_datadog_span.trace_id) }
it { expect(receiver_datadog_span.parent_id).to eq(sender_datadog_span.span_id) }
it { expect(@receiver_scope.span.context.baggage).to include(baggage) }
it { expect(intermediate_datadog_trace.sampling_priority).to eq(1) }
it { expect(intermediate_datadog_trace.origin).to eq('synthetics') }
it { expect(intermediate_datadog_span.finished?).to be(true) }
it { expect(intermediate_datadog_span.trace_id).to eq(origin_datadog_span.trace_id) }
it { expect(intermediate_datadog_span.parent_id).to eq(origin_datadog_span.span_id) }
it { expect(@intermediate_scope.span.context.baggage).to include(baggage) }

it { expect(destination_datadog_trace.sampling_priority).to eq(1) }
it { expect(destination_datadog_trace.origin).to eq('synthetics') }
it { expect(destination_datadog_span.finished?).to be(true) }
it { expect(destination_datadog_span.trace_id).to eq(intermediate_datadog_span.trace_id) }
it { expect(destination_datadog_span.parent_id).to eq(intermediate_datadog_span.span_id) }
it { expect(@destination_scope.span.context.baggage).to include(baggage) }

it do
expect(carrier).to include(
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_TRACE_ID => a_kind_of(Integer),
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_PARENT_ID => a_kind_of(Integer),
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_SAMPLING_PRIORITY => a_kind_of(Integer),
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_ORIGIN => a_kind_of(String),
expect(@origin_carrier).to include(
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_TRACE_ID => origin_datadog_span.trace_id,
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_PARENT_ID => origin_datadog_span.span_id,
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_SAMPLING_PRIORITY => 1,
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_ORIGIN => 'synthetics',
'ot-baggage-account_name' => 'acme'
)
end

it do
expect(another_carrier).to include(
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_TRACE_ID => a_kind_of(Integer),
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_PARENT_ID => a_kind_of(Integer),
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_SAMPLING_PRIORITY => a_kind_of(Integer),
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_ORIGIN => a_kind_of(String),
expect(@intermediate_carrier).to include(
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_TRACE_ID => intermediate_datadog_span.trace_id,
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_PARENT_ID => intermediate_datadog_span.span_id,
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_SAMPLING_PRIORITY => 1,
Datadog::OpenTracer::TextMapPropagator::HTTP_HEADER_ORIGIN => 'synthetics',
'ot-baggage-account_name' => 'acme'
)
end
Expand Down Expand Up @@ -290,12 +304,17 @@ def baggage_to_carrier_format(baggage)
end

context 'in a round-trip' do
let(:sender_span_name) { 'operation.sender' }
let(:sender_datadog_span) { datadog_spans.last }
let(:receiver_datadog_span) { datadog_spans.first }
let(:receiver_span_name) { 'operation.receiver' }
let(:datadog_sender_trace) { datadog_traces.last }
let(:datadog_receiver_trace) { datadog_traces.first }
let(:origin_span_name) { 'operation.origin' }
let(:origin_datadog_trace) { datadog_traces.find { |x| x.name == origin_span_name } }
let(:origin_datadog_span) { datadog_spans.find { |x| x.name == origin_span_name } }

let(:intermediate_span_name) { 'operation.intermediate' }
let(:intermediate_datadog_trace) { datadog_traces.find { |x| x.name == intermediate_span_name } }
let(:intermediate_datadog_span) { datadog_spans.find { |x| x.name == intermediate_span_name } }

let(:destination_span_name) { 'operation.destination' }
let(:destination_datadog_trace) { datadog_traces.find { |x| x.name == destination_span_name } }
let(:destination_datadog_span) { datadog_spans.find { |x| x.name == destination_span_name } }

# NOTE: If these baggage names include either dashes or uppercase characters
# they will not make a round-trip with the same key format. They will
Expand All @@ -305,57 +324,75 @@ def baggage_to_carrier_format(baggage)
let(:baggage) { { 'account_name' => 'acme' } }

before do
tracer.start_active_span(sender_span_name) do |sender_scope|
sender_scope.span.context.datadog_context.active_trace.sampling_priority = 1
sender_scope.span.context.datadog_context.active_trace.origin = 'synthetics'
baggage.each { |k, v| sender_scope.span.set_baggage_item(k, v) }
tracer.start_active_span(origin_span_name) do |origin_scope|
origin_datadog_context = origin_scope.span.context.datadog_context
origin_datadog_context.active_trace.sampling_priority = 1
origin_datadog_context.active_trace.origin = 'synthetics'

@carrier = {}.tap do |c|
tracer.inject(sender_scope.span.context, OpenTracing::FORMAT_RACK, c)
end
baggage.each { |k, v| origin_scope.span.set_baggage_item(k, v) }

span_context = tracer.extract(OpenTracing::FORMAT_RACK, carrier_to_rack_format(@carrier))
tracer.start_active_span(receiver_span_name, child_of: span_context) do |receiver_scope|
@receiver_scope = receiver_scope
# Do some work.
@origin_carrier = {}.tap do |c|
tracer.inject(origin_scope.span.context, OpenTracing::FORMAT_RACK, c)
end

@another_carrier = {}.tap do |c|
tracer.inject(receiver_scope.span.context, OpenTracing::FORMAT_RACK, c)
origin_datadog_context.activate!(nil) do
tracer.start_active_span(
intermediate_span_name,
child_of: tracer.extract(OpenTracing::FORMAT_RACK, carrier_to_rack_format(@origin_carrier))
) do |intermediate_scope|
@intermediate_scope = intermediate_scope

@intermediate_carrier = {}.tap do |c|
tracer.inject(intermediate_scope.span.context, OpenTracing::FORMAT_RACK, c)
end

tracer.start_active_span(
destination_span_name,
child_of: tracer.extract(OpenTracing::FORMAT_RACK, carrier_to_rack_format(@intermediate_carrier))
) do |destination_scope|
@destination_scope = destination_scope
# Do something
end
end
end
end
end

it { expect(datadog_spans).to have(2).items }
it { expect(datadog_traces).to have(3).items }
it { expect(datadog_spans).to have(3).items }

it { expect(origin_datadog_trace.sampling_priority).to eq(1) }
it { expect(origin_datadog_span.finished?).to be(true) }
it { expect(origin_datadog_span.parent_id).to eq(0) }

it { expect(datadog_sender_trace.sampling_priority).to eq(1) }
it { expect(sender_datadog_span.name).to eq(sender_span_name) }
it { expect(sender_datadog_span.finished?).to be(true) }
it { expect(sender_datadog_span.parent_id).to eq(0) }
it { expect(intermediate_datadog_trace.sampling_priority).to eq(1) }
it { expect(intermediate_datadog_span.finished?).to be(true) }
it { expect(intermediate_datadog_span.trace_id).to eq(origin_datadog_span.trace_id) }
it { expect(intermediate_datadog_span.parent_id).to eq(origin_datadog_span.span_id) }
it { expect(@intermediate_scope.span.context.baggage).to include(baggage) }

it { expect(datadog_receiver_trace.sampling_priority).to eq(1) }
it { expect(receiver_datadog_span.name).to eq(receiver_span_name) }
it { expect(receiver_datadog_span.finished?).to be(true) }
it { expect(receiver_datadog_span.trace_id).to eq(sender_datadog_span.trace_id) }
it { expect(receiver_datadog_span.parent_id).to eq(sender_datadog_span.span_id) }
it { expect(@receiver_scope.span.context.baggage).to include(baggage) }
it { expect(destination_datadog_trace.sampling_priority).to eq(1) }
it { expect(destination_datadog_span.finished?).to be(true) }
it { expect(destination_datadog_span.trace_id).to eq(intermediate_datadog_span.trace_id) }
it { expect(destination_datadog_span.parent_id).to eq(intermediate_datadog_span.span_id) }
it { expect(@destination_scope.span.context.baggage).to include(baggage) }

it do
expect(@carrier).to include(
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_TRACE_ID => a_kind_of(String),
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_PARENT_ID => a_kind_of(String),
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_SAMPLING_PRIORITY => a_kind_of(String),
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_ORIGIN => a_kind_of(String),
expect(@origin_carrier).to include(
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_TRACE_ID => origin_datadog_span.trace_id.to_s,
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_PARENT_ID => origin_datadog_span.span_id.to_s,
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_SAMPLING_PRIORITY => '1',
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_ORIGIN => 'synthetics',
'ot-baggage-account_name' => 'acme'
)
end

it do
expect(@another_carrier).to include(
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_TRACE_ID => a_kind_of(String),
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_PARENT_ID => a_kind_of(String),
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_SAMPLING_PRIORITY => a_kind_of(String),
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_ORIGIN => a_kind_of(String),
expect(@intermediate_carrier).to include(
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_TRACE_ID => intermediate_datadog_span.trace_id.to_s,
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_PARENT_ID => intermediate_datadog_span.span_id.to_s,
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_SAMPLING_PRIORITY => '1',
Datadog::OpenTracer::RackPropagator::HTTP_HEADER_ORIGIN => 'synthetics',
'ot-baggage-account_name' => 'acme'
)
end
Expand Down

0 comments on commit 1048c1d

Please sign in to comment.