@@ -4,6 +4,7 @@ if Code.ensure_loaded?(:otel_sampler) do
4
4
5
5
alias OpenTelemetry . { Span , Tracer }
6
6
alias Sentry.ClientReport
7
+ alias SamplingContext
7
8
8
9
@ behaviour :otel_sampler
9
10
@@ -24,27 +25,47 @@ if Code.ensure_loaded?(:otel_sampler) do
24
25
@ impl true
25
26
def should_sample (
26
27
ctx ,
27
- _trace_id ,
28
+ trace_id ,
28
29
_links ,
29
30
span_name ,
30
- _span_kind ,
31
- _attributes ,
31
+ span_kind ,
32
+ attributes ,
32
33
config
33
34
) do
34
35
result =
35
36
if span_name in config [ :drop ] do
36
37
{ :drop , [ ] , [ ] }
37
38
else
38
- sample_rate = Sentry.Config . traces_sample_rate ( )
39
+ traces_sampler = Sentry.Config . traces_sampler ( )
40
+ traces_sample_rate = Sentry.Config . traces_sample_rate ( )
39
41
40
42
case get_trace_sampling_decision ( ctx ) do
41
43
{ :inherit , trace_sampled , tracestate } ->
42
- decision = if trace_sampled , do: :record_and_sample , else: :drop
43
-
44
- { decision , [ ] , tracestate }
44
+ if traces_sampler do
45
+ sampling_context =
46
+ build_sampling_context (
47
+ trace_sampled ,
48
+ span_name ,
49
+ span_kind ,
50
+ attributes ,
51
+ trace_id
52
+ )
53
+
54
+ make_sampler_decision ( traces_sampler , sampling_context , tracestate )
55
+ else
56
+ decision = if trace_sampled , do: :record_and_sample , else: :drop
57
+ { decision , [ ] , tracestate }
58
+ end
45
59
46
60
:no_trace ->
47
- make_sampling_decision ( sample_rate )
61
+ if traces_sampler do
62
+ sampling_context =
63
+ build_sampling_context ( nil , span_name , span_kind , attributes , trace_id )
64
+
65
+ make_sampler_decision ( traces_sampler , sampling_context , [ ] )
66
+ else
67
+ make_sampling_decision ( traces_sample_rate )
68
+ end
48
69
end
49
70
end
50
71
@@ -121,6 +142,72 @@ if Code.ensure_loaded?(:otel_sampler) do
121
142
end
122
143
end
123
144
145
+ defp build_sampling_context ( parent_sampled , span_name , _span_kind , attributes , trace_id ) do
146
+ transaction_context = % {
147
+ name: span_name ,
148
+ op: span_name ,
149
+ trace_id: trace_id ,
150
+ attributes: attributes
151
+ }
152
+
153
+ sampling_context = % SamplingContext {
154
+ transaction_context: transaction_context ,
155
+ parent_sampled: parent_sampled
156
+ }
157
+
158
+ if attributes && map_size ( attributes ) > 0 do
159
+ Map . merge ( sampling_context , attributes )
160
+ else
161
+ sampling_context
162
+ end
163
+ end
164
+
165
+ defp make_sampler_decision ( traces_sampler , sampling_context , _existing_tracestate ) do
166
+ try do
167
+ result = call_traces_sampler ( traces_sampler , sampling_context )
168
+ sample_rate = normalize_sampler_result ( result )
169
+
170
+ cond do
171
+ sample_rate == 0.0 ->
172
+ tracestate = build_tracestate ( 0.0 , 1.0 , false )
173
+ { :drop , [ ] , tracestate }
174
+
175
+ sample_rate == 1.0 ->
176
+ tracestate = build_tracestate ( 1.0 , 0.0 , true )
177
+ { :record_and_sample , [ ] , tracestate }
178
+
179
+ is_float ( sample_rate ) and sample_rate > 0.0 and sample_rate < 1.0 ->
180
+ random_value = :rand . uniform ( )
181
+ sampled = random_value < sample_rate
182
+ tracestate = build_tracestate ( sample_rate , random_value , sampled )
183
+ decision = if sampled , do: :record_and_sample , else: :drop
184
+ { decision , [ ] , tracestate }
185
+
186
+ true ->
187
+ tracestate = build_tracestate ( 0.0 , 1.0 , false )
188
+ { :drop , [ ] , tracestate }
189
+ end
190
+ rescue
191
+ error ->
192
+ require Logger
193
+ Logger . warning ( "traces_sampler function failed: #{ inspect ( error ) } " )
194
+ tracestate = build_tracestate ( 0.0 , 1.0 , false )
195
+ { :drop , [ ] , tracestate }
196
+ end
197
+ end
198
+
199
+ defp call_traces_sampler ( fun , sampling_context ) when is_function ( fun , 1 ) do
200
+ fun . ( sampling_context )
201
+ end
202
+
203
+ defp call_traces_sampler ( { module , function } , sampling_context ) do
204
+ apply ( module , function , [ sampling_context ] )
205
+ end
206
+
207
+ defp normalize_sampler_result ( true ) , do: 1.0
208
+ defp normalize_sampler_result ( false ) , do: 0.0
209
+ defp normalize_sampler_result ( rate ) when is_float ( rate ) , do: rate
210
+
124
211
defp record_discarded_transaction ( ) do
125
212
ClientReport.Sender . record_discarded_events ( :sample_rate , "transaction" )
126
213
end
0 commit comments