solarwinds_apm 7.1.0 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '082c952e4514335f3f4b5371745bc77c371592d8f4473b65149bdcd2613281a2'
|
|
4
|
+
data.tar.gz: 9ee34f536ac6580862f9b97cfed9942d36b235a533e0f75c55181de30a80d69f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz: '
|
|
6
|
+
metadata.gz: b35526de0b456a81e53feb19ec84a48d592f48077cb52cdef3f9ca2e0cfa8cc341bbc41904255de6550c5484bb4da85ca555ada74f48461cd9817858bf4c6ac2
|
|
7
|
+
data.tar.gz: '0549ec00da3f0f6940baec1049072c6a5ef96b7ac9c90c2f7a3078ed52f51ff50eeee93e5fe6b12a2ce08cd8f71b39341ed6ffa2b5cf249762d5d9477ac9462b'
|
|
@@ -192,29 +192,14 @@ module SolarWindsAPM
|
|
|
192
192
|
case key
|
|
193
193
|
when :sampling_rate
|
|
194
194
|
SolarWindsAPM.logger.warn do
|
|
195
|
-
|
|
195
|
+
'[Deprecated] sampling_rate is not a supported setting for SolarWindsAPM::Config.'
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
when :sample_rate
|
|
199
|
-
|
|
200
|
-
SolarWindsAPM.
|
|
201
|
-
"[#{name}/#{__method__}] :sample_rate must be a number between 0 and 1000000 (1m) (provided: #{value}), corrected to 0"
|
|
202
|
-
end
|
|
203
|
-
value = 0
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
# Validate :sample_rate value
|
|
207
|
-
unless value.between?(0, 1e6)
|
|
208
|
-
new_value = value.negative? ? 0 : 1_000_000
|
|
209
|
-
SolarWindsAPM.logger.warn do
|
|
210
|
-
"[#{name}/#{__method__}] :sample_rate must be between 0 and 1000000 (1m) (provided: #{value}), corrected to #{new_value}"
|
|
211
|
-
end
|
|
199
|
+
SolarWindsAPM.logger.warn do
|
|
200
|
+
'[Deprecated] sample_rate is not a supported setting for SolarWindsAPM::Config.'
|
|
212
201
|
end
|
|
213
202
|
|
|
214
|
-
# Assure value is an integer
|
|
215
|
-
@@config[key.to_sym] = new_value.to_i
|
|
216
|
-
SolarWindsAPM.sample_rate(new_value)
|
|
217
|
-
|
|
218
203
|
when :transaction_settings
|
|
219
204
|
compile_settings(value)
|
|
220
205
|
|
|
@@ -18,7 +18,6 @@ module SolarWindsAPM
|
|
|
18
18
|
TRIGGERED_TRACE_ATTRIBUTE = 'TriggeredTrace'
|
|
19
19
|
|
|
20
20
|
TRACESTATE_REGEXP = /^[0-9a-f]{16}-[0-9a-f]{2}$/
|
|
21
|
-
BUCKET_INTERVAL = 1000
|
|
22
21
|
DICE_SCALE = 1_000_000
|
|
23
22
|
|
|
24
23
|
OTEL_SAMPLING_DECISION = ::OpenTelemetry::SDK::Trace::Samplers::Decision
|
|
@@ -30,16 +29,14 @@ module SolarWindsAPM
|
|
|
30
29
|
@counters = SolarWindsAPM::Metrics::Counter.new
|
|
31
30
|
@buckets = {
|
|
32
31
|
SolarWindsAPM::BucketType::DEFAULT =>
|
|
33
|
-
SolarWindsAPM::TokenBucket.new(SolarWindsAPM::TokenBucketSettings.new(nil, nil,
|
|
32
|
+
SolarWindsAPM::TokenBucket.new(SolarWindsAPM::TokenBucketSettings.new(nil, nil, 'DEFUALT')),
|
|
34
33
|
SolarWindsAPM::BucketType::TRIGGER_RELAXED =>
|
|
35
|
-
SolarWindsAPM::TokenBucket.new(SolarWindsAPM::TokenBucketSettings.new(nil, nil,
|
|
34
|
+
SolarWindsAPM::TokenBucket.new(SolarWindsAPM::TokenBucketSettings.new(nil, nil, 'TRIGGER_RELAXED')),
|
|
36
35
|
SolarWindsAPM::BucketType::TRIGGER_STRICT =>
|
|
37
|
-
SolarWindsAPM::TokenBucket.new(SolarWindsAPM::TokenBucketSettings.new(nil, nil,
|
|
36
|
+
SolarWindsAPM::TokenBucket.new(SolarWindsAPM::TokenBucketSettings.new(nil, nil, 'TRIGGER_STRICT'))
|
|
38
37
|
}
|
|
39
38
|
@settings = {} # parsed setting from swo backend
|
|
40
39
|
@settings_mutex = ::Mutex.new
|
|
41
|
-
|
|
42
|
-
@buckets.each_value(&:start)
|
|
43
40
|
end
|
|
44
41
|
|
|
45
42
|
# return sampling result
|
|
@@ -289,9 +286,9 @@ module SolarWindsAPM
|
|
|
289
286
|
end
|
|
290
287
|
|
|
291
288
|
def update_settings(settings)
|
|
292
|
-
return unless settings[:timestamp] > (@settings[:timestamp] || 0)
|
|
293
|
-
|
|
294
289
|
@settings_mutex.synchronize do
|
|
290
|
+
return unless settings[:timestamp] > (@settings[:timestamp] || 0)
|
|
291
|
+
|
|
295
292
|
@settings = settings
|
|
296
293
|
@buckets.each do |type, bucket|
|
|
297
294
|
bucket.update(@settings[:buckets][type]) if @settings[:buckets][type]
|
|
@@ -324,18 +321,20 @@ module SolarWindsAPM
|
|
|
324
321
|
end
|
|
325
322
|
|
|
326
323
|
def get_settings(params)
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
324
|
+
@settings_mutex.synchronize do
|
|
325
|
+
return if @settings.empty?
|
|
326
|
+
|
|
327
|
+
expiry = (@settings[:timestamp] + @settings[:ttl]) * 1000
|
|
328
|
+
time_now = Time.now.to_i * 1000
|
|
329
|
+
if time_now > expiry
|
|
330
|
+
@logger.debug { "[#{self.class}/#{__method__}] settings expired, removing" }
|
|
331
|
+
@settings = {}
|
|
332
|
+
return
|
|
333
|
+
end
|
|
334
|
+
sampling_setting = SolarWindsAPM::SamplingSettings.merge(@settings, local_settings(params))
|
|
335
|
+
@logger.debug { "[#{self.class}/#{__method__}] sampling_setting: #{sampling_setting.inspect}" }
|
|
336
|
+
sampling_setting
|
|
335
337
|
end
|
|
336
|
-
sampling_setting = SolarWindsAPM::SamplingSettings.merge(@settings, local_settings(params))
|
|
337
|
-
@logger.debug { "[#{self.class}/#{__method__}] sampling_setting: #{sampling_setting.inspect}" }
|
|
338
|
-
sampling_setting
|
|
339
338
|
end
|
|
340
339
|
end
|
|
341
340
|
end
|
|
@@ -10,126 +10,88 @@
|
|
|
10
10
|
# capacity is updated through update_settings
|
|
11
11
|
module SolarWindsAPM
|
|
12
12
|
class TokenBucket
|
|
13
|
-
|
|
14
|
-
MAX_INTERVAL = (2**31) - 1
|
|
15
|
-
|
|
16
|
-
attr_reader :capacity, :rate, :interval, :tokens, :type
|
|
13
|
+
attr_reader :type
|
|
17
14
|
|
|
18
15
|
def initialize(token_bucket_settings)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
@capacity = token_bucket_settings.capacity || 0
|
|
17
|
+
@rate = token_bucket_settings.rate || 0
|
|
18
|
+
@tokens = @capacity
|
|
19
|
+
@last_update_time = Time.now.to_f
|
|
23
20
|
@type = token_bucket_settings.type
|
|
24
|
-
@
|
|
21
|
+
@lock = ::Mutex.new
|
|
25
22
|
end
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def update(settings)
|
|
30
|
-
settings.instance_of?(Hash) ? update_from_hash(settings) : update_from_token_bucket_settings(settings)
|
|
24
|
+
def capacity
|
|
25
|
+
@lock.synchronize { @capacity }
|
|
31
26
|
end
|
|
32
27
|
|
|
33
|
-
def
|
|
34
|
-
|
|
35
|
-
difference = settings[:capacity] - @capacity
|
|
36
|
-
self.capacity = settings[:capacity]
|
|
37
|
-
self.tokens = @tokens + difference
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
self.rate = settings[:rate] if settings[:rate]
|
|
41
|
-
|
|
42
|
-
return unless settings[:interval]
|
|
43
|
-
|
|
44
|
-
self.interval = settings[:interval]
|
|
45
|
-
return unless running
|
|
46
|
-
|
|
47
|
-
stop
|
|
48
|
-
start
|
|
28
|
+
def rate
|
|
29
|
+
@lock.synchronize { @rate }
|
|
49
30
|
end
|
|
50
31
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
self.tokens = @tokens + difference
|
|
32
|
+
def tokens
|
|
33
|
+
@lock.synchronize do
|
|
34
|
+
calculate_tokens
|
|
35
|
+
@tokens
|
|
56
36
|
end
|
|
57
|
-
|
|
58
|
-
self.rate = settings.rate if settings.rate
|
|
59
|
-
|
|
60
|
-
return unless settings.interval
|
|
61
|
-
|
|
62
|
-
self.interval = settings.interval
|
|
63
|
-
return unless running
|
|
64
|
-
|
|
65
|
-
stop
|
|
66
|
-
start
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def capacity=(capacity)
|
|
70
|
-
@capacity = [0, capacity].max
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def rate=(rate)
|
|
74
|
-
@rate = [0, rate].max
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# self.interval= sets the @interval and @sleep_interval
|
|
78
|
-
# @sleep_interval is used in the timer thread to sleep between replenishing the bucket
|
|
79
|
-
def interval=(interval)
|
|
80
|
-
@interval = interval.clamp(0, MAX_INTERVAL)
|
|
81
|
-
@sleep_interval = @interval / 1000.0
|
|
82
37
|
end
|
|
83
38
|
|
|
84
|
-
|
|
85
|
-
|
|
39
|
+
# oboe sampler update_settings will update the token
|
|
40
|
+
def update(settings)
|
|
41
|
+
settings.instance_of?(Hash) ? update_from_hash(settings) : update_from_hash(tb_to_hash(settings))
|
|
86
42
|
end
|
|
87
43
|
|
|
88
44
|
# Attempts to consume tokens from the bucket
|
|
89
|
-
# @param
|
|
45
|
+
# @param token [Integer] Number of tokens to consume
|
|
90
46
|
# @return [Boolean] Whether there were enough tokens
|
|
91
|
-
# TODO: we need to include thread-safety here since sampler is shared across threads
|
|
92
|
-
# and we may have multiple threads trying to consume tokens at the same time
|
|
93
47
|
def consume(token = 1)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
# Starts replenishing the bucket
|
|
105
|
-
def start
|
|
106
|
-
return if running
|
|
107
|
-
|
|
108
|
-
@timer = Thread.new do
|
|
109
|
-
loop do
|
|
110
|
-
task
|
|
111
|
-
sleep(@sleep_interval)
|
|
48
|
+
@lock.synchronize do
|
|
49
|
+
calculate_tokens
|
|
50
|
+
if @tokens >= token
|
|
51
|
+
@tokens -= token
|
|
52
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] #{@type} Consumed #{token} (#{(@tokens.to_f / @capacity * 100).round(1)}% remaining)" }
|
|
53
|
+
true
|
|
54
|
+
else
|
|
55
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] #{@type} Token consumption failed: requested=#{token}, available=#{@tokens}, capacity=#{@capacity}" }
|
|
56
|
+
false
|
|
112
57
|
end
|
|
113
58
|
end
|
|
114
59
|
end
|
|
115
60
|
|
|
116
|
-
|
|
117
|
-
def stop
|
|
118
|
-
return unless running
|
|
61
|
+
private
|
|
119
62
|
|
|
120
|
-
|
|
121
|
-
|
|
63
|
+
def calculate_tokens
|
|
64
|
+
now = Time.now.to_f
|
|
65
|
+
elapsed = now - @last_update_time
|
|
66
|
+
@last_update_time = now
|
|
67
|
+
@tokens += elapsed * @rate
|
|
68
|
+
@tokens = [@tokens, @capacity].min
|
|
122
69
|
end
|
|
123
70
|
|
|
124
|
-
#
|
|
125
|
-
def
|
|
126
|
-
|
|
127
|
-
|
|
71
|
+
# settings is from json sampler
|
|
72
|
+
def update_from_hash(settings)
|
|
73
|
+
@lock.synchronize do
|
|
74
|
+
calculate_tokens
|
|
75
|
+
|
|
76
|
+
if settings[:capacity]
|
|
77
|
+
new_capacity = [0, settings[:capacity]].max
|
|
78
|
+
difference = new_capacity - @capacity
|
|
79
|
+
@capacity = new_capacity
|
|
80
|
+
@tokens += difference
|
|
81
|
+
@tokens = [0, @tokens].max
|
|
82
|
+
end
|
|
128
83
|
|
|
129
|
-
|
|
84
|
+
@rate = [0, settings[:rate]].max if settings[:rate]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
130
87
|
|
|
131
|
-
|
|
132
|
-
|
|
88
|
+
# settings is from http sampler
|
|
89
|
+
def tb_to_hash(settings)
|
|
90
|
+
tb_hash = {}
|
|
91
|
+
tb_hash[:capacity] = settings.capacity if settings.respond_to?(:capacity)
|
|
92
|
+
tb_hash[:rate] = settings.rate if settings.respond_to?(:rate)
|
|
93
|
+
tb_hash[:type] = settings.type if settings.respond_to?(:type)
|
|
94
|
+
tb_hash
|
|
133
95
|
end
|
|
134
96
|
end
|
|
135
97
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solarwinds_apm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.1.
|
|
4
|
+
version: 7.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maia Engeli
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2026-01-20 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: opentelemetry-exporter-otlp
|