From 38e3622ede9c3b235f41d83a163fe2a3d9d7469d Mon Sep 17 00:00:00 2001 From: David Elner Date: Thu, 7 Mar 2019 11:35:26 -0500 Subject: [PATCH] Fix Rack http_server.queue spans missing from distributed traces. (#709) --- lib/ddtrace/contrib/rack/middlewares.rb | 12 +++++---- spec/ddtrace/contrib/rack/distributed_spec.rb | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/ddtrace/contrib/rack/middlewares.rb b/lib/ddtrace/contrib/rack/middlewares.rb index 5984d1fed3..a116a13d22 100644 --- a/lib/ddtrace/contrib/rack/middlewares.rb +++ b/lib/ddtrace/contrib/rack/middlewares.rb @@ -43,6 +43,13 @@ def call(env) # retrieve integration settings tracer = configuration[:tracer] + # Extract distributed tracing context before creating any spans, + # so that all spans will be added to the distributed trace. + if configuration[:distributed_tracing] + context = HTTPPropagator.extract(env) + tracer.provider.context = context if context.trace_id + end + # [experimental] create a root Span to keep track of frontend web servers # (i.e. Apache, nginx) if the header is properly set frontend_span = compute_queue_time(env, tracer) @@ -53,11 +60,6 @@ def call(env) span_type: Datadog::Ext::HTTP::TYPE } - if configuration[:distributed_tracing] - context = HTTPPropagator.extract(env) - tracer.provider.context = context if context.trace_id - end - # start a new request span and attach it to the current Rack environment; # we must ensure that the span `resource` is set later request_span = tracer.trace(Ext::SPAN_REQUEST, trace_options) diff --git a/spec/ddtrace/contrib/rack/distributed_spec.rb b/spec/ddtrace/contrib/rack/distributed_spec.rb index 51f7cc4305..6f84068f71 100644 --- a/spec/ddtrace/contrib/rack/distributed_spec.rb +++ b/spec/ddtrace/contrib/rack/distributed_spec.rb @@ -88,6 +88,32 @@ context 'with distributed tracing headers' do include_context 'distributed tracing headers' it_behaves_like 'a Rack request with distributed tracing' + + context 'and request_queuing is enabled' do + let(:rack_options) { super().merge(request_queuing: true, web_service_name: web_service_name) } + let(:web_service_name) { 'frontend_web_server' } + + let(:server_span) { spans.first } + let(:rack_span) { spans.last } + + before(:each) do + header 'X-Request-Start', "t=#{Time.now.to_f}" + end + + it 'contains a request_queuing span that belongs to the distributed trace' do + is_expected.to be_ok + expect(spans).to have(2).items + + expect(server_span.name).to eq('http_server.queue') + expect(server_span.trace_id).to eq(trace_id) + expect(server_span.parent_id).to eq(parent_id) + expect(server_span.get_metric(Datadog::Ext::DistributedTracing::SAMPLING_PRIORITY_KEY)).to eq(sampling_priority) + + expect(rack_span.name).to eq('rack.request') + expect(rack_span.trace_id).to eq(trace_id) + expect(rack_span.parent_id).to eq(server_span.span_id) + end + end end context 'without distributed tracing headers' do