splitclient-rb 2.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.txt +12 -0
  3. data/NEWS +4 -0
  4. data/README.md +45 -11
  5. data/lib/cache/adapters/adapter.rb +23 -0
  6. data/lib/cache/adapters/memory_adapter.rb +46 -0
  7. data/lib/cache/repositories/repository.rb +25 -0
  8. data/lib/cache/repositories/segments_repository.rb +52 -0
  9. data/lib/cache/repositories/splits_repository.rb +51 -0
  10. data/lib/cache/stores/sdk_blocker.rb +47 -0
  11. data/lib/cache/stores/segment_store.rb +71 -0
  12. data/lib/cache/stores/split_store.rb +64 -0
  13. data/lib/engine/api/client.rb +29 -0
  14. data/lib/engine/api/segments.rb +60 -0
  15. data/lib/engine/api/splits.rb +58 -0
  16. data/lib/{splitclient-engine → engine}/evaluator/splitter.rb +0 -0
  17. data/lib/{splitclient-engine → engine}/impressions/impressions.rb +0 -0
  18. data/lib/{splitclient-engine → engine}/matchers/all_keys_matcher.rb +0 -0
  19. data/lib/{splitclient-engine → engine}/matchers/between_matcher.rb +2 -0
  20. data/lib/{splitclient-engine → engine}/matchers/combiners.rb +0 -0
  21. data/lib/{splitclient-engine → engine}/matchers/combining_matcher.rb +1 -1
  22. data/lib/{splitclient-engine → engine}/matchers/equal_to_matcher.rb +0 -0
  23. data/lib/{splitclient-engine → engine}/matchers/greater_than_or_equal_to_matcher.rb +0 -0
  24. data/lib/{splitclient-engine → engine}/matchers/less_than_or_equal_to_matcher.rb +0 -0
  25. data/lib/{splitclient-engine → engine}/matchers/negation_matcher.rb +0 -0
  26. data/lib/{splitclient-engine → engine}/matchers/user_defined_segment_matcher.rb +4 -21
  27. data/lib/{splitclient-engine → engine}/matchers/whitelist_matcher.rb +0 -0
  28. data/lib/{splitclient-engine → engine}/metrics/binary_search_latency_tracker.rb +0 -0
  29. data/lib/{splitclient-engine → engine}/metrics/metrics.rb +0 -0
  30. data/lib/{splitclient-engine → engine}/parser/condition.rb +5 -7
  31. data/lib/{splitclient-engine → engine}/parser/partition.rb +0 -0
  32. data/lib/{splitclient-engine → engine}/parser/split.rb +11 -3
  33. data/lib/{splitclient-engine → engine}/parser/split_adapter.rb +20 -184
  34. data/lib/engine/parser/split_treatment.rb +65 -0
  35. data/lib/{splitclient-engine → engine}/partitions/treatments.rb +0 -0
  36. data/lib/exceptions/sdk_blocker_timeout_expired_exception.rb +4 -0
  37. data/lib/splitclient-rb.rb +31 -23
  38. data/lib/splitclient-rb/split_config.rb +41 -4
  39. data/lib/splitclient-rb/split_factory.rb +50 -20
  40. data/lib/splitclient-rb/version.rb +1 -1
  41. data/splitclient-rb.gemspec +2 -0
  42. metadata +62 -25
  43. data/lib/splitclient-cache/local_store.rb +0 -45
  44. data/lib/splitclient-engine/parser/segment.rb +0 -84
  45. data/lib/splitclient-engine/parser/segment_parser.rb +0 -46
  46. data/lib/splitclient-engine/parser/split_parser.rb +0 -122
@@ -0,0 +1,29 @@
1
+ module SplitIoClient
2
+ module Api
3
+ class Client
4
+ def call_api(path, config, api_key, params = {})
5
+ api_client.get(config.base_uri + path, params) do |req|
6
+ req.headers['Authorization'] = 'Bearer ' + api_key
7
+ req.headers['SplitSDKVersion'] = SplitIoClient::SplitFactory.sdk_version
8
+ req.headers['SplitSDKMachineName'] = config.machine_name
9
+ req.headers['SplitSDKMachineIP'] = config.machine_ip
10
+ req.headers['Accept-Encoding'] = 'gzip'
11
+
12
+ req.options.open_timeout = config.connection_timeout
13
+ req.options.timeout = config.read_timeout
14
+
15
+ config.logger.debug("GET #{config.base_uri + path}") if config.debug_enabled
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def api_client
22
+ @api_client ||= Faraday.new do |builder|
23
+ builder.use FaradayMiddleware::Gzip
24
+ builder.adapter :net_http_persistent
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,60 @@
1
+ module SplitIoClient
2
+ module Api
3
+ class Segments < Client
4
+ def initialize(api_key, config, metrics, segments_repository)
5
+ @config = config
6
+ @metrics = metrics
7
+ @api_key = api_key
8
+ @segments_repository = segments_repository
9
+ end
10
+
11
+ def store_segments_by_names(names)
12
+ start = Time.now
13
+ prefix = 'segmentChangeFetcher'
14
+
15
+ return if names.nil? || names.empty?
16
+
17
+ names.each do |name|
18
+ since = @segments_repository.get_change_number(name)
19
+ while true
20
+ fetch_segments(name, prefix, since).each { |segment| @segments_repository.add_to_segment(segment) }
21
+ @config.logger.debug("Segment #{name} fetched before: #{since}, till: #{@segments_repository.get_change_number(name)}") if @config.debug_enabled
22
+
23
+ break if (since.to_i >= @segments_repository.get_change_number(name).to_i)
24
+ since = @segments_repository.get_change_number(name)
25
+ end
26
+ end
27
+
28
+ latency = (Time.now - start) * 1000.0
29
+ @metrics.time(prefix + '.time', latency)
30
+ end
31
+
32
+ private
33
+
34
+ def fetch_segments(name, prefix, since)
35
+ segments = []
36
+ segment = call_api('/segmentChanges/' + name, @config, @api_key, { since: since })
37
+
38
+ if segment.status / 100 == 2
39
+ segment_content = JSON.parse(segment.body, symbolize_names: true)
40
+ @segments_repository.set_change_number(name, segment_content[:till])
41
+ @metrics.count(prefix + '.status.' + segment.status.to_s, 1)
42
+
43
+ if @config.debug_enabled
44
+ @config.logger.debug("\'#{segment_content[:name]}\' segment retrieved.")
45
+ @config.logger.debug("\'#{segment_content[:name]}\' #{segment_content[:added].size} added keys") if segment_content[:added].size > 0
46
+ @config.logger.debug("\'#{segment_content[:name]}\' #{segment_content[:removed].size} removed keys") if segment_content[:removed].size > 0
47
+ end
48
+ @config.logger.debug("#{segment_content}") if @config.transport_debug_enabled
49
+
50
+ segments << segment_content
51
+ else
52
+ @config.logger.error('Unexpected result from API call')
53
+ @metrics.count(prefix + '.status.' + segment.status.to_s, 1)
54
+ end
55
+
56
+ segments
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,58 @@
1
+ module SplitIoClient
2
+ module Api
3
+ class Splits < Client
4
+ def initialize(api_key, config, metrics)
5
+ @api_key = api_key
6
+ @config = config
7
+ @metrics = metrics
8
+ end
9
+
10
+ def since(since)
11
+ start = Time.now
12
+ prefix = 'splitChangeFetcher'
13
+ splits = call_api('/splitChanges', @config, @api_key, {:since => since})
14
+
15
+ if splits.status / 100 == 2
16
+ result = splits_with_segment_names(splits.body)
17
+
18
+ @metrics.count(prefix + '.status.' + splits.status.to_s, 1)
19
+
20
+ @config.logger.debug("#{result[:splits].length} splits retrieved. since=#{since}") if @config.debug_enabled and result[:splits].length > 0
21
+ @config.logger.debug("#{result}") if @config.transport_debug_enabled
22
+ else
23
+ @metrics.count(prefix + '.status.' + splits.status.to_s, 1)
24
+
25
+ @config.logger.error('Unexpected result from API call')
26
+ end
27
+
28
+ latency = (Time.now - start) * 1000.0
29
+ @metrics.time(prefix + '.time', latency)
30
+
31
+ result
32
+ end
33
+
34
+ private
35
+
36
+ def splits_with_segment_names(splits_json)
37
+ parsed_splits = JSON.parse(splits_json, symbolize_names: true)
38
+
39
+ parsed_splits[:segment_names] =
40
+ parsed_splits[:splits].each_with_object(Set.new) do |split, splits|
41
+ splits << segment_names(split)
42
+ end.flatten
43
+
44
+ parsed_splits
45
+ end
46
+
47
+ def segment_names(split)
48
+ split[:conditions].each_with_object(Set.new) do |condition, names|
49
+ condition[:matcherGroup][:matchers].each do |matcher|
50
+ next if matcher[:userDefinedSegmentMatcherData].nil?
51
+
52
+ names << matcher[:userDefinedSegmentMatcherData][:segmentName]
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -18,6 +18,8 @@ module SplitIoClient
18
18
  param_value = get_formatted_value(attributes[@attribute.to_sym])
19
19
  matches = param_value.is_a?(Integer) ? ((param_value >= @start_value) && (param_value <= @end_value)) : false
20
20
  end
21
+
22
+ matches
21
23
  end
22
24
 
23
25
  def equals?(obj)
@@ -1,4 +1,4 @@
1
- require 'splitclient-engine/matchers/combiners'
1
+ require 'engine/matchers/combiners'
2
2
 
3
3
  module SplitIoClient
4
4
  #
@@ -7,13 +7,10 @@ module SplitIoClient
7
7
 
8
8
  attr_reader :matcher_type
9
9
 
10
- @segment = nil
11
-
12
- def initialize(segment)
10
+ def initialize(segments_repository, segment_name)
13
11
  @matcher_type = "IN_SEGMENT"
14
- unless segment.nil?
15
- @segment = segment
16
- end
12
+ @segments_repository = segments_repository
13
+ @segment_name = segment_name
17
14
  end
18
15
 
19
16
  #
@@ -23,11 +20,7 @@ module SplitIoClient
23
20
  #
24
21
  # @return [boolean] evaluation of the key against the segment
25
22
  def match?(key, attributes)
26
- matches = false
27
- unless @segment.users.nil?
28
- matches = @segment.users.include?(key)
29
- end
30
- matches
23
+ @segments_repository.in_segment?(@segment_name, key)
31
24
  end
32
25
 
33
26
  #
@@ -47,15 +40,5 @@ module SplitIoClient
47
40
  false
48
41
  end
49
42
  end
50
-
51
- #
52
- # function to print string value for this matcher
53
- #
54
- # @reutrn [string] string value of this matcher
55
- def to_s
56
- 'in segment ' + @segment.name
57
- end
58
-
59
43
  end
60
-
61
44
  end
@@ -45,9 +45,9 @@ module SplitIoClient
45
45
  #returns UserDefinedSegmentMatcher[object]
46
46
  def matcher_in_segment params
47
47
  matcher = params[:matcher]
48
- segments = params[:segments]
49
- segment = segments.get_segment(matcher[:userDefinedSegmentMatcherData][:segmentName])
50
- segment.is_empty? ? UserDefinedSegmentMatcher.new(nil) : UserDefinedSegmentMatcher.new(segment)
48
+ segment_name = matcher[:userDefinedSegmentMatcherData] && matcher[:userDefinedSegmentMatcherData][:segmentName]
49
+
50
+ UserDefinedSegmentMatcher.new(params[:segments_repository], segment_name)
51
51
  end
52
52
 
53
53
  #returns WhitelistMatcher[object] the whitelist for this condition in case it has a whitelist matcher
@@ -125,10 +125,8 @@ module SplitIoClient
125
125
 
126
126
  #
127
127
  # @return [boolean] true if the condition is empty false otherwise
128
- def is_empty?
129
- @data.empty? ? true : false
128
+ def empty?
129
+ @data.empty?
130
130
  end
131
-
132
131
  end
133
-
134
132
  end
@@ -46,8 +46,8 @@ module SplitIoClient
46
46
 
47
47
  #
48
48
  # @return [boolean] true if the condition is empty false otherwise
49
- def is_empty?
50
- @data.empty? ? true : false
49
+ def empty?
50
+ @data.empty?
51
51
  end
52
52
 
53
53
  #
@@ -63,6 +63,14 @@ module SplitIoClient
63
63
  conditions_list
64
64
  end
65
65
 
66
+ def to_h
67
+ {
68
+ name: name,
69
+ seed: seed,
70
+ status: status,
71
+ killed: killed?,
72
+ conditions: conditions
73
+ }
74
+ end
66
75
  end
67
-
68
76
  end
@@ -31,21 +31,26 @@ module SplitIoClient
31
31
 
32
32
  attr_reader :impressions_producer
33
33
 
34
+ attr_reader :splits_repository, :segments_repository
35
+
34
36
  #
35
37
  # Creates a new split api adapter instance that consumes split api endpoints
36
38
  #
37
39
  # @param api_key [String] the API key for your split account
38
40
  #
39
41
  # @return [SplitIoClient] split.io client instance
40
- def initialize(api_key, config)
42
+ def initialize(api_key, config, splits_repository, segments_repository, sdk_blocker)
41
43
 
42
44
  @api_key = api_key
43
45
  @config = config
44
- @parsed_splits = SplitParser.new(@config.logger)
45
- @parsed_segments = SegmentParser.new(@config.logger)
46
46
  @impressions = Impressions.new(100)
47
47
  @metrics = Metrics.new(100)
48
48
 
49
+ @splits_repository = splits_repository
50
+ @segments_repository = segments_repository
51
+
52
+ @sdk_blocker = sdk_blocker
53
+
49
54
  @api_client = Faraday.new do |builder|
50
55
  builder.use FaradayMiddleware::Gzip
51
56
  builder.adapter :net_http_persistent
@@ -55,6 +60,7 @@ module SplitIoClient
55
60
  @segments_consumer = create_segments_api_consumer
56
61
  @metrics_producer = create_metrics_api_producer
57
62
  @impressions_producer = create_impressions_api_producer
63
+
58
64
  end
59
65
 
60
66
  #
@@ -64,78 +70,11 @@ module SplitIoClient
64
70
  #
65
71
  # @return [void]
66
72
  def create_splits_api_consumer
67
- Thread.new do
68
- loop do
69
- begin
70
- #splits fetcher
71
- splits_arr = []
72
- data = get_splits(@parsed_splits.since)
73
- if data
74
- data[:splits].each do |split|
75
- splits_arr << SplitIoClient::Split.new(split)
76
- end
77
- end
78
-
79
- if @parsed_splits.is_empty?
80
- @parsed_splits.splits = splits_arr
81
- else
82
- refresh_splits(splits_arr)
83
- end
84
- @parsed_splits.since = data[:till]
85
-
86
- random_interval = randomize_interval @config.features_refresh_rate
87
- sleep(random_interval)
88
- rescue StandardError => error
89
- @config.log_found_exception(__method__.to_s, error)
90
- end
91
- end
92
- end
73
+ SplitIoClient::Cache::Stores::SplitStore.new(@splits_repository, @config, @api_key, @metrics, @sdk_blocker).call
93
74
  end
94
75
 
95
76
  def create_segments_api_consumer
96
- Thread.new do
97
- loop do
98
- begin
99
- #segments fetcher
100
- segments_arr = []
101
- segment_data = get_segments(@parsed_splits.get_used_segments)
102
- segment_data.each do |segment|
103
- segments_arr << SplitIoClient::Segment.new(segment)
104
- end
105
- if @parsed_segments.is_empty?
106
- @parsed_segments.segments = segments_arr
107
- @parsed_segments.segments.map { |s| s.refresh_users(s.added, s.removed) }
108
- else
109
- refresh_segments(segments_arr)
110
- end
111
-
112
- random_interval = randomize_interval @config.segments_refresh_rate
113
- sleep(random_interval)
114
- rescue StandardError => error
115
- @config.log_found_exception(__method__.to_s, error)
116
- end
117
- end
118
- end
119
- end
120
-
121
- #
122
- # helper method to execute a get request to the provided endpoint
123
- #
124
- # @param path [string] api endpoint path
125
- # @param params [object] hash of params that will be added to the request
126
- #
127
- # @return [object] response to the request
128
- def call_api(path, params = {})
129
- @api_client.get @config.base_uri + path, params do |req|
130
- req.headers['Authorization'] = 'Bearer ' + @api_key
131
- req.headers['SplitSDKVersion'] = SplitIoClient::SplitFactory.sdk_version
132
- req.headers['SplitSDKMachineName'] = @config.machine_name
133
- req.headers['SplitSDKMachineIP'] = @config.machine_ip
134
- req.headers['Accept-Encoding'] = 'gzip'
135
- req.options.open_timeout = @config.connection_timeout
136
- req.options.timeout = @config.read_timeout
137
- @config.logger.debug("GET #{@config.base_uri + path}") if @config.debug_enabled
138
- end
77
+ SplitIoClient::Cache::Stores::SegmentStore.new(@segments_repository, @config, @api_key, @metrics, @sdk_blocker).call
139
78
  end
140
79
 
141
80
  #
@@ -159,105 +98,6 @@ module SplitIoClient
159
98
  end
160
99
  end
161
100
 
162
- #
163
- # helper method to fetch splits by using the appropriate api endpoint
164
- #
165
- # @param since [int] since value for the last fetch
166
- #
167
- # @return splits [object] splits structure in json format
168
- def get_splits(since)
169
- result = nil
170
- start = Time.now
171
- prefix = 'splitChangeFetcher'
172
-
173
- splits = call_api('/splitChanges', {:since => since})
174
-
175
- if splits.status / 100 == 2
176
- result = JSON.parse(splits.body, symbolize_names: true)
177
- @metrics.count(prefix + '.status.' + splits.status.to_s, 1)
178
- @config.logger.info("#{result[:splits].length} splits retrieved.")
179
- @config.logger.debug("#{result}") if @config.debug_enabled
180
- else
181
- @config.logger.error('Unexpected result from API call')
182
- @metrics.count(prefix + '.status.' + splits.status.to_s, 1)
183
- end
184
-
185
- latency = (Time.now - start) * 1000.0
186
- @metrics.time(prefix + '.time', latency)
187
-
188
- result
189
- end
190
-
191
- #
192
- # helper method to refresh splits values after a new fetch with changes
193
- #
194
- # @param splits_arr [object] array of splits to refresh
195
- #
196
- # @return [void]
197
- def refresh_splits(splits_arr)
198
- feature_names = splits_arr.map { |s| s.name }
199
- @parsed_splits.splits.delete_if { |sp| feature_names.include?(sp.name) }
200
- @parsed_splits.splits += splits_arr
201
- end
202
-
203
- #
204
- # helper method to fetch segments by using the appropriate api endpoint
205
- #
206
- # @param names [object] array of segment names that must be fetched
207
- #
208
- # @return segments [object] segments structure in json format
209
- def get_segments(names)
210
- segments = []
211
- start = Time.now
212
- prefix = 'segmentChangeFetcher'
213
-
214
- names.each do |name|
215
- curr_segment = @parsed_segments.get_segment(name)
216
- since = curr_segment.nil? ? -1 : curr_segment.till
217
-
218
- while true
219
- segment = call_api('/segmentChanges/' + name, {:since => since})
220
-
221
- if segment.status / 100 == 2
222
- segment_content = JSON.parse(segment.body, symbolize_names: true)
223
- @parsed_segments.since = segment_content[:till]
224
- @metrics.count(prefix + '.status.' + segment.status.to_s, 1)
225
- @config.logger.info("\'#{segment_content[:name]}\' segment retrieved.")
226
- @config.logger.debug("#{segment_content}") if @config.debug_enabled
227
- segments << segment_content
228
- else
229
- @config.logger.error('Unexpected result from API call')
230
- @metrics.count(prefix + '.status.' + segment.status.to_s, 1)
231
- end
232
- break if (since.to_i >= @parsed_segments.since.to_i)
233
- since = @parsed_segments.since
234
- end
235
- end
236
-
237
- latency = (Time.now - start) * 1000.0
238
- @metrics.time(prefix + '.time', latency)
239
-
240
- segments
241
- end
242
-
243
- #
244
- # helper method to refresh segments values after a new fetch with changes
245
- #
246
- # @param segments_arr [object] array of segments to refresh
247
- #
248
- # @return [void]
249
- def refresh_segments(segments_arr)
250
- segment_names = @parsed_segments.segments.map { |s| s.name }
251
- segments_arr.each do |s|
252
- if segment_names.include?(s.name)
253
- segment_to_update = @parsed_segments.get_segment(s.name)
254
- segment_to_update.refresh_users(s.added, s.removed)
255
- else
256
- @parsed_segments.segments << s
257
- end
258
- end
259
- end
260
-
261
101
  #
262
102
  # @return parsed_splits [object] parsed splits for this adapter
263
103
  def parsed_splits
@@ -315,7 +155,7 @@ module SplitIoClient
315
155
  # @return [void]
316
156
  def post_impressions
317
157
  if @impressions.queue.empty?
318
- @config.logger.info('No impressions to report.')
158
+ @config.logger.debug('No impressions to report.') if @config.debug_enabled
319
159
  else
320
160
  popped_impressions = @impressions.clear
321
161
  test_impression_array = []
@@ -333,7 +173,7 @@ module SplitIoClient
333
173
  end
334
174
 
335
175
  if filtered.empty?
336
- @config.logger.info('No impressions to report post filtering.')
176
+ @config.logger.debug('No impressions to report post filtering.') if @config.debug_enabled
337
177
  else
338
178
  test_impression = {}
339
179
  key_impressions = []
@@ -351,8 +191,7 @@ module SplitIoClient
351
191
  if res.status / 100 != 2
352
192
  @config.logger.error("Unexpected status code while posting impressions: #{res.status}")
353
193
  else
354
- @config.logger.info("Impressions reported.")
355
- @config.logger.debug("#{test_impression_array}")if @config.debug_enabled
194
+ @config.logger.debug("Impressions reported: #{test_impression_array}") if @config.debug_enabled
356
195
  end
357
196
  end
358
197
  end
@@ -365,7 +204,7 @@ module SplitIoClient
365
204
  # @return [void]
366
205
  def post_metrics
367
206
  if @metrics.latencies.empty?
368
- @config.logger.info('No latencies to report.')
207
+ @config.logger.debug('No latencies to report.') if @config.debug_enabled
369
208
  else
370
209
  @metrics.latencies.each do |l|
371
210
  metrics_time = {}
@@ -374,15 +213,14 @@ module SplitIoClient
374
213
  if res.status / 100 != 2
375
214
  @config.logger.error("Unexpected status code while posting time metrics: #{res.status}")
376
215
  else
377
- @config.logger.info("Metric time reported.")
378
- @config.logger.debug("#{metrics_time}") if @config.debug_enabled
216
+ @config.logger.debug("Metric time reported: #{metrics_time}") if @config.debug_enabled
379
217
  end
380
218
  end
381
219
  end
382
220
  @metrics.latencies.clear
383
221
 
384
222
  if @metrics.counts.empty?
385
- @config.logger.info('No counts to report.')
223
+ @config.logger.debug('No counts to report.') if @config.debug_enabled
386
224
  else
387
225
  @metrics.counts.each do |c|
388
226
  metrics_count = {}
@@ -391,15 +229,14 @@ module SplitIoClient
391
229
  if res.status / 100 != 2
392
230
  @config.logger.error("Unexpected status code while posting count metrics: #{res.status}")
393
231
  else
394
- @config.logger.info("Metric counts reported.")
395
- @config.logger.debug("#{metrics_count}") if @config.debug_enabled
232
+ @config.logger.debug("Metric counts reported: #{metrics_count}") if @config.debug_enabled
396
233
  end
397
234
  end
398
235
  end
399
236
  @metrics.counts.clear
400
237
 
401
238
  if @metrics.gauges.empty?
402
- @config.logger.info('No gauges to report.')
239
+ @config.logger.debug('No gauges to report.') if @config.debug_enabled
403
240
  else
404
241
  @metrics.gauges.each do |g|
405
242
  metrics_gauge = {}
@@ -408,8 +245,7 @@ module SplitIoClient
408
245
  if res.status / 100 != 2
409
246
  @config.logger.error("Unexpected status code while posting gauge metrics: #{res.status}")
410
247
  else
411
- @config.logger.info("Metric gauge reported.")
412
- @config.logger.debug("#{metrics_gauge}") if @config.debug_enabled
248
+ @config.logger.debug("Metric gauge reported: #{metrics_gauge}") if @config.debug_enabled
413
249
  end
414
250
  end
415
251
  end