@@ -4,6 +4,9 @@ if Code.ensure_loaded?(:otel_sampler) do
44
55 alias OpenTelemetry . { Span , Tracer }
66 alias Sentry.ClientReport
7+ alias SamplingContext
8+
9+ require Logger
710
811 @ behaviour :otel_sampler
912
@@ -24,27 +27,47 @@ if Code.ensure_loaded?(:otel_sampler) do
2427 @ impl true
2528 def should_sample (
2629 ctx ,
27- _trace_id ,
30+ trace_id ,
2831 _links ,
2932 span_name ,
30- _span_kind ,
31- _attributes ,
33+ span_kind ,
34+ attributes ,
3235 config
3336 ) do
3437 result =
3538 if span_name in config [ :drop ] do
3639 { :drop , [ ] , [ ] }
3740 else
38- sample_rate = Sentry.Config . traces_sample_rate ( )
41+ traces_sampler = Sentry.Config . traces_sampler ( )
42+ traces_sample_rate = Sentry.Config . traces_sample_rate ( )
3943
4044 case get_trace_sampling_decision ( ctx ) do
4145 { :inherit , trace_sampled , tracestate } ->
42- decision = if trace_sampled , do: :record_and_sample , else: :drop
43-
44- { decision , [ ] , tracestate }
46+ if traces_sampler do
47+ sampling_context =
48+ build_sampling_context (
49+ trace_sampled ,
50+ span_name ,
51+ span_kind ,
52+ attributes ,
53+ trace_id
54+ )
55+
56+ make_sampler_decision ( traces_sampler , sampling_context , tracestate )
57+ else
58+ decision = if trace_sampled , do: :record_and_sample , else: :drop
59+ { decision , [ ] , tracestate }
60+ end
4561
4662 :no_trace ->
47- make_sampling_decision ( sample_rate )
63+ if traces_sampler do
64+ sampling_context =
65+ build_sampling_context ( nil , span_name , span_kind , attributes , trace_id )
66+
67+ make_sampler_decision ( traces_sampler , sampling_context , [ ] )
68+ else
69+ make_sampling_decision ( traces_sample_rate )
70+ end
4871 end
4972 end
5073
@@ -121,6 +144,76 @@ if Code.ensure_loaded?(:otel_sampler) do
121144 end
122145 end
123146
147+ defp build_sampling_context ( parent_sampled , span_name , _span_kind , attributes , trace_id ) do
148+ transaction_context = % {
149+ name: span_name ,
150+ op: span_name ,
151+ trace_id: trace_id ,
152+ attributes: attributes
153+ }
154+
155+ sampling_context = % SamplingContext {
156+ transaction_context: transaction_context ,
157+ parent_sampled: parent_sampled
158+ }
159+
160+ if attributes && map_size ( attributes ) > 0 do
161+ Map . merge ( sampling_context , attributes )
162+ else
163+ sampling_context
164+ end
165+ end
166+
167+ defp make_sampler_decision ( traces_sampler , sampling_context , _existing_tracestate ) do
168+ try do
169+ result = call_traces_sampler ( traces_sampler , sampling_context )
170+ sample_rate = normalize_sampler_result ( result )
171+
172+ cond do
173+ sample_rate == 0.0 ->
174+ tracestate = build_tracestate ( 0.0 , 1.0 , false )
175+
176+ { :drop , [ ] , tracestate }
177+
178+ sample_rate == 1.0 ->
179+ tracestate = build_tracestate ( 1.0 , 0.0 , true )
180+
181+ { :record_and_sample , [ ] , tracestate }
182+
183+ is_float ( sample_rate ) and sample_rate > 0.0 and sample_rate < 1.0 ->
184+ random_value = :rand . uniform ( )
185+ sampled = random_value < sample_rate
186+ tracestate = build_tracestate ( sample_rate , random_value , sampled )
187+ decision = if sampled , do: :record_and_sample , else: :drop
188+
189+ { decision , [ ] , tracestate }
190+
191+ true ->
192+ tracestate = build_tracestate ( 0.0 , 1.0 , false )
193+
194+ { :drop , [ ] , tracestate }
195+ end
196+ rescue
197+ error ->
198+ Logger . warning ( "traces_sampler function failed: #{ inspect ( error ) } " )
199+
200+ tracestate = build_tracestate ( 0.0 , 1.0 , false )
201+ { :drop , [ ] , tracestate }
202+ end
203+ end
204+
205+ defp call_traces_sampler ( fun , sampling_context ) when is_function ( fun , 1 ) do
206+ fun . ( sampling_context )
207+ end
208+
209+ defp call_traces_sampler ( { module , function } , sampling_context ) do
210+ apply ( module , function , [ sampling_context ] )
211+ end
212+
213+ defp normalize_sampler_result ( true ) , do: 1.0
214+ defp normalize_sampler_result ( false ) , do: 0.0
215+ defp normalize_sampler_result ( rate ) when is_float ( rate ) , do: rate
216+
124217 defp record_discarded_transaction ( ) do
125218 ClientReport.Sender . record_discarded_events ( :sample_rate , "transaction" )
126219 end
0 commit comments