Skip to content

Commit 80582bf

Browse files
committed
fix(tracing): use established propagation context's span_id
1 parent cbde3a6 commit 80582bf

4 files changed

Lines changed: 55 additions & 3 deletions

File tree

sentry-rails/spec/sentry/rails/capture_context_spec.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,25 @@
33
require "spec_helper"
44

55
RSpec.describe Sentry::Rails::CaptureContext do
6-
# Records the current scope's trace_id every time it's called, so specs can
6+
# Records the current scope's trace context every time it's called, so specs can
77
# compare what a piece of middleware would see at different points in the stack.
88
class CaptureContextSpecProbe
99
def self.captured_trace_ids
1010
@captured_trace_ids ||= []
1111
end
1212

13+
def self.captured_span_ids
14+
@captured_span_ids ||= []
15+
end
16+
1317
def initialize(app)
1418
@app = app
1519
end
1620

1721
def call(env)
18-
self.class.captured_trace_ids << Sentry.get_current_scope.get_trace_context[:trace_id]
22+
trace_context = Sentry.get_current_scope.get_trace_context
23+
self.class.captured_trace_ids << trace_context[:trace_id]
24+
self.class.captured_span_ids << trace_context[:span_id]
1925
@app.call(env)
2026
end
2127
end
@@ -103,6 +109,7 @@ def call(env)
103109
context "when composed with CaptureExceptions", type: :request do
104110
before do
105111
CaptureContextSpecProbe.captured_trace_ids.clear
112+
CaptureContextSpecProbe.captured_span_ids.clear
106113
end
107114

108115
context "without tracing enabled" do
@@ -132,6 +139,15 @@ def call(env)
132139
end
133140
end
134141

142+
it "points a span_id captured before CaptureExceptions at the started transaction" do
143+
get "/world"
144+
145+
transaction = Sentry.get_current_client.transport.events.last
146+
early_span_id = CaptureContextSpecProbe.captured_span_ids.first
147+
148+
expect(early_span_id).to eq(transaction.contexts.dig(:trace, :span_id))
149+
end
150+
135151
it "keeps the same trace_id from before CaptureExceptions through the started transaction" do
136152
get "/world"
137153

sentry-ruby/lib/sentry/hub.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,11 @@ def start_transaction(transaction: nil, custom_sampling_context: {}, instrumente
123123
return unless instrumenter == configuration.instrumenter
124124

125125
if transaction.nil? && !options.key?(:trace_id) && established
126-
# reuse the already-established trace_id instead of generating an unrelated one
126+
# adopt the already-established trace and span rather than generating unrelated
127+
# ones, so anything already logged against them resolves to this transaction
127128
propagation_context = current_scope.propagation_context
128129
options[:trace_id] = propagation_context.trace_id
130+
options[:span_id] ||= propagation_context.span_id
129131
options[:sample_rand] ||= propagation_context.sample_rand
130132
end
131133

@@ -391,6 +393,7 @@ def continue_trace(env, established: false, **options)
391393

392394
Transaction.new(
393395
trace_id: propagation_context.trace_id,
396+
span_id: propagation_context.span_id,
394397
parent_span_id: propagation_context.parent_span_id,
395398
parent_sampled: propagation_context.parent_sampled,
396399
baggage: propagation_context.baggage,

sentry-ruby/spec/sentry_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,24 @@
597597
expect(transaction.sample_rand).to eq(propagation_context.sample_rand)
598598
end
599599

600+
it "adopts the scope's propagation context span_id" do
601+
propagation_context = Sentry.get_current_scope.propagation_context
602+
603+
transaction = described_class.start_transaction(
604+
name: "test", op: "test.op", established: true
605+
)
606+
607+
expect(transaction.span_id).to eq(propagation_context.span_id)
608+
end
609+
610+
it "does not override an explicitly provided span_id" do
611+
transaction = described_class.start_transaction(
612+
name: "test", op: "test.op", span_id: "b" * 16, established: true
613+
)
614+
615+
expect(transaction.span_id).to eq("b" * 16)
616+
end
617+
600618
it "does not override an explicitly provided trace_id" do
601619
transaction = described_class.start_transaction(
602620
name: "test", op: "test.op", trace_id: "a" * 32, established: true
@@ -1262,6 +1280,14 @@
12621280
expect(transaction.baggage.mutable).to eq(false)
12631281
end
12641282

1283+
it "gives the Transaction the propagation context's span_id" do
1284+
Sentry.configuration.traces_sample_rate = 1.0
1285+
1286+
transaction = described_class.continue_trace(env, name: "foobar")
1287+
1288+
expect(transaction.span_id).to eq(Sentry.get_current_scope.propagation_context.span_id)
1289+
end
1290+
12651291
describe "sample_rand propagation" do
12661292
before do
12671293
Sentry.configuration.traces_sample_rate = 1.0

spec/features/trace_context_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ def request_transaction
1818
.to eq(request_transaction.dig("contexts", "trace", "trace_id"))
1919
end
2020

21+
it "points a log emitted before CaptureExceptions at the transaction's span" do
22+
without_trace_propagation { make_request("/trace_context") }
23+
24+
expect(early_middleware_logs.first["span_id"])
25+
.to eq(request_transaction.dig("contexts", "trace", "span_id"))
26+
end
27+
2128
it "continues an incoming distributed trace in a log emitted before CaptureExceptions" do
2229
incoming_trace_id = propagated_trace_id
2330

0 commit comments

Comments
 (0)