@@ -131,14 +131,149 @@ defmodule Sentry.Opentelemetry.SamplerTest do
131131 end
132132 end
133133
134- describe "parent span inheritance" do
135- test "inherits sampling decision from parent span with same trace_id" do
134+ describe "trace-level sampling consistency" do
135+ defp create_span_context_with_tracestate ( trace_id , tracestate ) do
136+ {
137+ :span_ctx ,
138+ trace_id ,
139+ 123_456_789 ,
140+ 1 ,
141+ tracestate ,
142+ true ,
143+ false ,
144+ true ,
145+ nil
146+ }
147+ end
148+
149+ test "all spans in trace inherit sampling decision to drop when trace was not sampled" do
150+ :sys . replace_state ( ClientReport.Sender , fn _ -> % { } end )
151+
152+ trace_id = 12_345_678_901_234_567_890_123_456_789_012
153+
154+ trace_tracestate = [
155+ { "sentry-sample_rate" , "1.0" } ,
156+ { "sentry-sample_rand" , "0.5" } ,
157+ { "sentry-sampled" , "false" }
158+ ]
159+
160+ existing_span_ctx = create_span_context_with_tracestate ( trace_id , trace_tracestate )
161+
162+ ctx = :otel_ctx . new ( )
163+ ctx_with_span = :otel_tracer . set_current_span ( ctx , existing_span_ctx )
164+ token = :otel_ctx . attach ( ctx_with_span )
165+
166+ try do
167+ result =
168+ Sampler . should_sample ( ctx_with_span , trace_id , nil , "new span in trace" , nil , nil ,
169+ drop: [ ]
170+ )
171+
172+ assert { :drop , [ ] , returned_tracestate } = result
173+ assert returned_tracestate == trace_tracestate
174+
175+ Process . sleep ( 10 )
176+
177+ state = :sys . get_state ( ClientReport.Sender )
178+ assert state == % { { :sample_rate , "transaction" } => 1 }
179+ after
180+ :otel_ctx . detach ( token )
181+ end
182+ end
183+
184+ test "all spans in trace inherit sampling decision to sample when trace was sampled" do
185+ trace_id = 12_345_678_901_234_567_890_123_456_789_012
186+
187+ # Simulate existing trace context with sample decision
188+ trace_tracestate = [
189+ { "sentry-sample_rate" , "1.0" } ,
190+ { "sentry-sample_rand" , "0.5" } ,
191+ { "sentry-sampled" , "true" }
192+ ]
193+
194+ existing_span_ctx = create_span_context_with_tracestate ( trace_id , trace_tracestate )
195+
196+ ctx = :otel_ctx . new ( )
197+ ctx_with_span = :otel_tracer . set_current_span ( ctx , existing_span_ctx )
198+ token = :otel_ctx . attach ( ctx_with_span )
199+
200+ try do
201+ result =
202+ Sampler . should_sample ( ctx_with_span , trace_id , nil , "new span in trace" , nil , nil ,
203+ drop: [ ]
204+ )
205+
206+ assert { :record_and_sample , [ ] , returned_tracestate } = result
207+ assert returned_tracestate == trace_tracestate
208+ after
209+ :otel_ctx . detach ( token )
210+ end
211+ end
212+
213+ test "makes new sampling decision when no existing trace context" do
136214 Sentry.Config . put_config ( :traces_sample_rate , 1.0 )
137215
138216 test_ctx = create_test_span_context ( )
139217
140218 assert { :record_and_sample , [ ] , _tracestate } =
141- Sampler . should_sample ( test_ctx , 123 , nil , "test span" , nil , nil , drop: [ ] )
219+ Sampler . should_sample ( test_ctx , 123 , nil , "root span" , nil , nil , drop: [ ] )
220+ end
221+
222+ test "makes new sampling decision when tracestate has no sentry sampling info" do
223+ trace_id = 12_345_678_901_234_567_890_123_456_789_012
224+
225+ non_sentry_tracestate = [
226+ { "other-system" , "some-value" }
227+ ]
228+
229+ existing_span_ctx = create_span_context_with_tracestate ( trace_id , non_sentry_tracestate )
230+
231+ ctx = :otel_ctx . new ( )
232+ ctx_with_span = :otel_tracer . set_current_span ( ctx , existing_span_ctx )
233+ token = :otel_ctx . attach ( ctx_with_span )
234+
235+ try do
236+ Sentry.Config . put_config ( :traces_sample_rate , 1.0 )
237+
238+ result =
239+ Sampler . should_sample ( ctx_with_span , trace_id , nil , "span in external trace" , nil , nil ,
240+ drop: [ ]
241+ )
242+
243+ assert { :record_and_sample , [ ] , new_tracestate } = result
244+ assert { "sentry-sampled" , "true" } in new_tracestate
245+ after
246+ :otel_ctx . detach ( token )
247+ end
248+ end
249+
250+ test "trace_id parameter is now irrelevant for inheritance decisions" do
251+ trace_id = 12_345_678_901_234_567_890_123_456_789_012
252+ different_trace_id = 98_765_432_109_876_543_210_987_654_321_098
253+
254+ trace_tracestate = [
255+ { "sentry-sample_rate" , "1.0" } ,
256+ { "sentry-sample_rand" , "0.5" } ,
257+ { "sentry-sampled" , "false" }
258+ ]
259+
260+ existing_span_ctx = create_span_context_with_tracestate ( trace_id , trace_tracestate )
261+
262+ ctx = :otel_ctx . new ( )
263+ ctx_with_span = :otel_tracer . set_current_span ( ctx , existing_span_ctx )
264+ token = :otel_ctx . attach ( ctx_with_span )
265+
266+ try do
267+ result =
268+ Sampler . should_sample ( ctx_with_span , different_trace_id , nil , "span" , nil , nil ,
269+ drop: [ ]
270+ )
271+
272+ assert { :drop , [ ] , returned_tracestate } = result
273+ assert returned_tracestate == trace_tracestate
274+ after
275+ :otel_ctx . detach ( token )
276+ end
142277 end
143278 end
144279
0 commit comments