ff-ruby-server-sdk 1.2.1 → 1.3.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/api.yaml +319 -30
  3. data/lib/ff/ruby/server/generated/lib/openapi_client/api/client_api.rb +27 -0
  4. data/lib/ff/ruby/server/generated/lib/openapi_client/api/metrics_api.rb +13 -10
  5. data/lib/ff/ruby/server/generated/lib/openapi_client/api/proxy_api.rb +159 -0
  6. data/lib/ff/ruby/server/generated/lib/openapi_client/configuration.rb +7 -0
  7. data/lib/ff/ruby/server/generated/lib/openapi_client/models/clause.rb +6 -5
  8. data/lib/ff/ruby/server/generated/lib/openapi_client/models/distribution.rb +3 -0
  9. data/lib/ff/ruby/server/generated/lib/openapi_client/models/error.rb +16 -4
  10. data/lib/ff/ruby/server/generated/lib/openapi_client/models/group_serving_rule.rb +257 -0
  11. data/lib/ff/ruby/server/generated/lib/openapi_client/models/inline_object.rb +223 -0
  12. data/lib/ff/ruby/server/generated/lib/openapi_client/models/pagination.rb +5 -0
  13. data/lib/ff/ruby/server/generated/lib/openapi_client/models/prerequisite.rb +3 -0
  14. data/lib/ff/ruby/server/generated/lib/openapi_client/models/proxy_config.rb +299 -0
  15. data/lib/ff/ruby/server/generated/lib/openapi_client/models/proxy_config_all_of.rb +220 -0
  16. data/lib/ff/ruby/server/generated/lib/openapi_client/models/proxy_config_all_of_environments.rb +251 -0
  17. data/lib/ff/ruby/server/generated/lib/openapi_client/models/segment.rb +23 -4
  18. data/lib/ff/ruby/server/generated/lib/openapi_client/models/serve.rb +1 -0
  19. data/lib/ff/ruby/server/generated/lib/openapi_client/models/serving_rule.rb +4 -5
  20. data/lib/ff/ruby/server/generated/lib/openapi_client/models/tag.rb +15 -8
  21. data/lib/ff/ruby/server/generated/lib/openapi_client/models/target.rb +11 -0
  22. data/lib/ff/ruby/server/generated/lib/openapi_client/models/target_map.rb +8 -0
  23. data/lib/ff/ruby/server/generated/lib/openapi_client/models/variation.rb +5 -0
  24. data/lib/ff/ruby/server/generated/lib/openapi_client/models/variation_map.rb +4 -0
  25. data/lib/ff/ruby/server/generated/lib/openapi_client/models/weighted_variation.rb +3 -0
  26. data/lib/ff/ruby/server/generated/lib/openapi_client.rb +6 -0
  27. data/lib/ff/ruby/server/sdk/api/config.rb +1 -1
  28. data/lib/ff/ruby/server/sdk/api/evaluator.rb +32 -78
  29. data/lib/ff/ruby/server/sdk/api/metrics_processor.rb +95 -50
  30. data/lib/ff/ruby/server/sdk/api/storage_repository.rb +14 -0
  31. data/lib/ff/ruby/server/sdk/common/sdk_codes.rb +9 -0
  32. data/lib/ff/ruby/server/sdk/connector/harness_connector.rb +12 -3
  33. data/lib/ff/ruby/server/sdk/version.rb +1 -1
  34. data/scripts/sdk_specs.sh +1 -1
  35. metadata +9 -3
@@ -10,15 +10,12 @@ class Evaluator < Evaluation
10
10
  def initialize(repository, logger = nil)
11
11
 
12
12
  unless repository.kind_of?(Repository)
13
-
14
13
  raise "The 'repository' parameter must be of '" + Repository.to_s + "' data type"
15
14
  end
16
15
 
17
16
  if logger != nil
18
-
19
17
  @logger = logger
20
18
  else
21
-
22
19
  @logger = Logger.new(STDOUT)
23
20
  end
24
21
 
@@ -30,7 +27,6 @@ class Evaluator < Evaluation
30
27
  variation = evaluate(identifier, target, "boolean", callback)
31
28
 
32
29
  if variation != nil
33
-
34
30
  return variation.value == "true"
35
31
  end
36
32
 
@@ -43,7 +39,6 @@ class Evaluator < Evaluation
43
39
  variation = evaluate(identifier, target, "string", callback)
44
40
 
45
41
  if variation != nil
46
-
47
42
  return variation.value
48
43
  end
49
44
 
@@ -56,7 +51,6 @@ class Evaluator < Evaluation
56
51
  variation = evaluate(identifier, target, "int", callback)
57
52
 
58
53
  if variation != nil
59
-
60
54
  return variation.value.to_i
61
55
  end
62
56
 
@@ -68,7 +62,6 @@ class Evaluator < Evaluation
68
62
  variation = evaluate(identifier, target, "int", callback)
69
63
 
70
64
  if variation != nil
71
-
72
65
  return variation.value.to_f
73
66
  end
74
67
 
@@ -81,7 +74,6 @@ class Evaluator < Evaluation
81
74
  variation = evaluate(identifier, target, "json", callback)
82
75
 
83
76
  if variation != nil
84
-
85
77
  return JSON.parse(variation.value)
86
78
  end
87
79
 
@@ -92,9 +84,7 @@ class Evaluator < Evaluation
92
84
  def evaluate(identifier, target, expected, callback)
93
85
 
94
86
  if callback != nil
95
-
96
87
  unless callback.kind_of?(FlagEvaluateCallback)
97
-
98
88
  raise "The 'callback' parameter must be of '" + FlagEvaluateCallback.to_s + "' data type"
99
89
  end
100
90
  end
@@ -102,13 +92,9 @@ class Evaluator < Evaluation
102
92
  flag = @repository.get_flag(identifier)
103
93
 
104
94
  if flag != nil && flag.kind == expected
105
-
106
95
  unless flag.prerequisites.empty?
107
-
108
96
  pre_req = check_pre_requisite(flag, target)
109
-
110
97
  unless pre_req
111
-
112
98
  return find_variation(flag.variations, flag.off_variation)
113
99
  end
114
100
  end
@@ -116,12 +102,9 @@ class Evaluator < Evaluation
116
102
  variation = evaluate_flag(flag, target)
117
103
 
118
104
  if variation != nil
119
-
120
105
  if callback != nil
121
-
122
106
  callback.process_evaluation(flag, target, variation)
123
107
  end
124
-
125
108
  return variation
126
109
  end
127
110
  end
@@ -134,24 +117,16 @@ class Evaluator < Evaluation
134
117
  def get_attr_value(target, attribute)
135
118
 
136
119
  if attribute != nil && !attribute.empty?
137
-
138
120
  if target.respond_to?(attribute, :include_private)
139
-
140
121
  @logger.debug "The attribute " + attribute.to_s + " exists (1)"
141
-
142
122
  return target.send(attribute)
143
123
  else
144
124
 
145
125
  @logger.debug "target attrs: " + target.attributes.to_s
146
-
147
126
  result = target.attributes[attribute.to_sym]
148
-
149
127
  if result == nil
150
-
151
128
  @logger.debug "The attribute " + attribute.to_s + " does not exist"
152
-
153
129
  else
154
-
155
130
  @logger.debug "The attribute " + attribute.to_s + " exists (2)"
156
131
  end
157
132
 
@@ -167,11 +142,8 @@ class Evaluator < Evaluation
167
142
  def find_variation(variations, identifier)
168
143
 
169
144
  if identifier != nil && !identifier.empty?
170
-
171
145
  variations.each do |v|
172
-
173
146
  if v.identifier == identifier
174
-
175
147
  return v
176
148
  end
177
149
  end
@@ -225,12 +197,26 @@ class Evaluator < Evaluation
225
197
  nil
226
198
  end
227
199
 
200
+
201
+ def evaluate_clauses_v2(clauses, target)
202
+ if clauses.empty?
203
+ return false
204
+ end
205
+
206
+ # New style rules require that all clauses are true
207
+ clauses.each do |clause|
208
+ if !evaluate_clause(clause, target)
209
+ return false
210
+ end
211
+ end
212
+ true
213
+ end
214
+
228
215
  def evaluate_clauses(clauses, target)
229
216
 
230
217
  clauses.each do |clause|
231
218
 
232
219
  if evaluate_clause(clause, target)
233
-
234
220
  return true
235
221
  end
236
222
  end
@@ -241,24 +227,20 @@ class Evaluator < Evaluation
241
227
  def evaluate_clause(clause, target)
242
228
 
243
229
  if clause == nil
244
-
245
230
  return false
246
231
  end
247
232
 
248
233
  operator = clause.op
249
234
 
250
235
  if operator == nil || operator.empty?
251
-
252
236
  return false
253
237
  end
254
238
 
255
239
  if operator == "segmentMatch"
256
-
257
240
  return is_target_included_or_excluded_in_segment(clause.values, target)
258
241
  end
259
242
 
260
243
  if clause.values.empty?
261
-
262
244
  return false
263
245
  end
264
246
 
@@ -266,50 +248,41 @@ class Evaluator < Evaluation
266
248
  attr_value = get_attr_value(target, clause.attribute)
267
249
 
268
250
  if attr_value == nil
269
-
270
251
  return false
271
252
  end
272
253
 
273
254
  object = attr_value.to_s
274
255
 
275
256
  if operator == "starts_with"
276
-
277
257
  return object.start_with?(value)
278
258
  end
279
259
 
280
260
  if operator == "ends_with"
281
-
282
261
  return object.end_with?(value)
283
262
  end
284
263
 
285
264
  if operator == "match"
286
-
287
265
  match = object.match?(value)
288
266
  return match != nil && !match.empty?
289
267
  end
290
268
 
291
269
  if operator == "contains"
292
-
293
270
  return object.include?(value)
294
271
  end
295
272
 
296
273
  if operator == "equal"
297
-
298
274
  return object.casecmp?(value)
299
275
  end
300
276
 
301
277
  if operator == "equal_sensitive"
302
-
303
278
  return object == value
304
279
  end
305
280
 
306
281
  if operator == "in"
307
-
308
282
  return clause.values.include?(object)
309
283
  end
310
284
 
311
285
  if operator == "segmentMatch"
312
-
313
286
  return is_target_included_or_excluded_in_segment(clause.values, target)
314
287
  end
315
288
 
@@ -325,27 +298,34 @@ class Evaluator < Evaluation
325
298
  if segment != nil
326
299
 
327
300
  if is_target_in_list(target, segment.excluded)
328
-
329
301
  @logger.debug "Target " + target.name.to_s + " excluded from segment " + segment.name.to_s + " via exclude list"
330
-
331
302
  return false
332
303
  end
333
304
 
334
305
  if is_target_in_list(target, segment.included)
335
-
336
306
  @logger.debug "Target " + target.name.to_s + " included in segment " + segment.name.to_s + " via include list"
337
-
338
307
  return true
339
308
  end
340
309
 
341
- rules = segment.rules
342
-
343
- if rules != nil && !rules.empty? && evaluate_clauses(rules, target)
310
+ new_serving_rules = segment.serving_rules
311
+ if new_serving_rules != nil && !new_serving_rules.empty?
312
+ # Use enhanced rules first if they're available
344
313
 
345
- @logger.debug "Target " + target.name.to_s + " included in segment " + segment.name.to_s + " via rules"
314
+ new_serving_rules.each do |serving_rule|
315
+ if evaluate_clauses_v2(serving_rule.clauses, target)
316
+ return true
317
+ end
318
+ end
346
319
 
347
- return true
320
+ else
321
+ # Fall back to old rules
322
+ rules = segment.rules
323
+ if rules != nil && !rules.empty? && evaluate_clauses(rules, target)
324
+ @logger.debug "Target " + target.name.to_s + " included in segment " + segment.name.to_s + " via rules"
325
+ return true
326
+ end
348
327
  end
328
+
349
329
  end
350
330
  end
351
331
 
@@ -355,26 +335,17 @@ class Evaluator < Evaluation
355
335
  def evaluate_rules(serving_rules, target)
356
336
 
357
337
  if target == nil || serving_rules == nil
358
-
359
338
  return nil
360
339
  end
361
340
 
362
- sorted = serving_rules.sort do |a, b|
363
-
364
- b.priority <=> a.priority
365
- end
366
-
367
- sorted.each do |rule|
368
-
341
+ serving_rules.each do |rule|
369
342
  next unless evaluate_rule(rule, target)
370
343
 
371
344
  if rule.serve.distribution != nil
372
-
373
345
  return evaluate_distribution(rule.serve.distribution, target)
374
346
  end
375
347
 
376
348
  if rule.serve.variation != nil
377
-
378
349
  return rule.serve.variation
379
350
  end
380
351
  end
@@ -383,14 +354,12 @@ class Evaluator < Evaluation
383
354
  end
384
355
 
385
356
  def evaluate_rule(serving_rule, target)
386
-
387
357
  evaluate_clauses(serving_rule.clauses, target)
388
358
  end
389
359
 
390
360
  def evaluate_variation_map(variation_maps, target)
391
361
 
392
362
  if target == nil
393
-
394
363
  return nil
395
364
  end
396
365
 
@@ -399,20 +368,15 @@ class Evaluator < Evaluation
399
368
  targets = variation_map.targets
400
369
 
401
370
  if targets != nil
402
-
403
371
  found = nil
404
-
405
372
  targets.each do |t|
406
-
407
373
  if t.identifier != nil && t.identifier == target.identifier
408
-
409
374
  found = t
410
375
  break
411
376
  end
412
377
  end
413
378
 
414
379
  if found != nil
415
-
416
380
  return variation_map.variation
417
381
  end
418
382
  end
@@ -420,7 +384,6 @@ class Evaluator < Evaluation
420
384
  segment_identifiers = variation_map.target_segments
421
385
 
422
386
  if segment_identifiers != nil && is_target_included_or_excluded_in_segment(segment_identifiers, target)
423
-
424
387
  return variation_map.variation
425
388
  end
426
389
  end
@@ -433,32 +396,26 @@ class Evaluator < Evaluation
433
396
  variation = feature_config.off_variation
434
397
 
435
398
  if feature_config.state == OpenapiClient::FeatureState::ON
436
-
437
399
  variation = nil
438
400
 
439
401
  if feature_config.variation_to_target_map != nil
440
-
441
402
  variation = evaluate_variation_map(feature_config.variation_to_target_map, target)
442
403
  end
443
404
 
444
405
  if variation == nil
445
-
446
406
  variation = evaluate_rules(feature_config.rules, target)
447
407
  end
448
408
 
449
409
  if variation == nil
450
-
451
410
  variation = evaluate_distribution(feature_config.default_serve.distribution, target)
452
411
  end
453
412
 
454
413
  if variation == nil
455
-
456
414
  variation = feature_config.default_serve.variation
457
415
  end
458
416
  end
459
417
 
460
418
  if variation != nil
461
-
462
419
  return find_variation(feature_config.variations, variation)
463
420
  end
464
421
 
@@ -519,11 +476,8 @@ class Evaluator < Evaluation
519
476
  def is_target_in_list(target, list_of_targets)
520
477
 
521
478
  if list_of_targets != nil
522
-
523
479
  list_of_targets.each do |included_target|
524
-
525
480
  if included_target.identifier.include?(target.identifier)
526
-
527
481
  return true
528
482
  end
529
483
  end
@@ -17,7 +17,11 @@ class MetricsProcessor < Closeable
17
17
 
18
18
  def increment(key)
19
19
  compute(key) do |old_value|
20
- if old_value == nil; 1 else old_value + 1 end
20
+ if old_value == nil;
21
+ 1
22
+ else
23
+ old_value + 1
24
+ end
21
25
  end
22
26
  end
23
27
 
@@ -39,7 +43,6 @@ class MetricsProcessor < Closeable
39
43
  end
40
44
  end
41
45
 
42
-
43
46
  def init(connector, config, callback)
44
47
 
45
48
  unless connector.kind_of?(Connector)
@@ -59,14 +62,12 @@ class MetricsProcessor < Closeable
59
62
  @connector = connector
60
63
 
61
64
  @sdk_type = "SDK_TYPE"
62
- @global_target_set = Set[]
63
- @staging_target_set = Set[]
64
65
  @target_attribute = "target"
65
- @global_target = "__global__cf_target" # <--- This target identifier is used to aggregate and send data for all
66
+ @global_target_identifier = "__global__cf_target" # <--- This target identifier is used to aggregate and send data for all
66
67
  # targets as a summary
67
-
68
+ @global_target = Target.new("RubySDK1", identifier = @global_target_identifier, name = @global_target_name)
68
69
  @ready = false
69
- @jar_version = ""
70
+ @jar_version = Ff::Ruby::Server::Sdk::VERSION
70
71
  @server = "server"
71
72
  @sdk_version = "SDK_VERSION"
72
73
  @sdk_language = "SDK_LANGUAGE"
@@ -76,10 +77,20 @@ class MetricsProcessor < Closeable
76
77
 
77
78
  @executor = Concurrent::FixedThreadPool.new(10)
78
79
 
79
- @frequency_map = FrequencyMap.new
80
+ @evaluation_metrics = FrequencyMap.new
81
+ @target_metrics = Concurrent::Map.new
82
+
83
+ # Keep track of targets that have already been sent to avoid sending them again
84
+ @seen_targets = Concurrent::Map.new
80
85
 
81
86
  @max_buffer_size = config.buffer_size - 1
82
87
 
88
+ # Max 100k targets per interval
89
+ @max_targets_buffer_size = 100000
90
+
91
+ @evaluation_warning_issued = Concurrent::AtomicBoolean.new
92
+ @target_warning_issued = Concurrent::AtomicBoolean.new
93
+
83
94
  @callback.on_metrics_ready
84
95
  end
85
96
 
@@ -99,30 +110,70 @@ class MetricsProcessor < Closeable
99
110
  end
100
111
 
101
112
  def register_evaluation(target, feature_config, variation)
113
+ register_evaluation_metric(feature_config, variation)
114
+ register_target_metric(target)
115
+ end
102
116
 
103
- if @frequency_map.size > @max_buffer_size
104
- @config.logger.warn "metrics buffer is full #{@frequency_map.size} - flushing metrics"
105
- @executor.post do
106
- run_one_iteration
117
+ private
118
+
119
+ def register_evaluation_metric(feature_config, variation)
120
+ if @evaluation_metrics.size > @max_buffer_size
121
+ unless @evaluation_warning_issued.true?
122
+ SdkCodes.warn_metrics_evaluations_max_size_exceeded(@config.logger)
123
+ @evaluation_warning_issued.make_true
107
124
  end
125
+ return
108
126
  end
109
127
 
110
- event = MetricsEvent.new(feature_config, target, variation)
111
- @frequency_map.increment event
128
+ event = MetricsEvent.new(feature_config, @global_target, variation)
129
+ @evaluation_metrics.increment event
112
130
  end
113
131
 
114
- private
132
+ def register_target_metric(target)
133
+ if @target_metrics.size > @max_targets_buffer_size
134
+ unless @target_warning_issued.true?
135
+ SdkCodes.warn_metrics_targets_max_size_exceeded(@config.logger)
136
+ @target_warning_issued.make_true
137
+ end
138
+ return
139
+ end
140
+
141
+ if target.is_private
142
+ return
143
+ end
144
+
145
+ already_seen = @seen_targets.put_if_absent(target.identifier, true)
146
+
147
+ if already_seen
148
+ return
149
+ end
150
+
151
+ @target_metrics.put(target.identifier, target)
152
+ end
115
153
 
116
154
  def run_one_iteration
117
- send_data_and_reset_cache @frequency_map.drain_to_map
155
+ send_data_and_reset_cache(@evaluation_metrics, @target_metrics)
118
156
 
119
- @config.logger.debug "metrics: frequency map size #{@frequency_map.size}. global target size #{@global_target_set.size}"
157
+ @config.logger.debug "metrics: frequency map size #{@evaluation_metrics.size}. targets map size #{@target_metrics.size} global target size #{@seen_targets.size}"
120
158
  end
121
159
 
122
- def send_data_and_reset_cache(map)
123
- metrics = prepare_summary_metrics_body(map)
160
+ def send_data_and_reset_cache(evaluation_metrics_map, target_metrics_map)
161
+ evaluation_metrics_map_clone = evaluation_metrics_map.drain_to_map
162
+
163
+ target_metrics_map_clone = Concurrent::Map.new
164
+
165
+ target_metrics_map.each_pair do |key, value|
166
+ target_metrics_map_clone[key] = value
167
+ end
168
+
169
+ target_metrics_map.clear
170
+
171
+ @evaluation_warning_issued.make_false
172
+ @target_warning_issued.make_false
173
+
174
+ metrics = prepare_summary_metrics_body(evaluation_metrics_map_clone, target_metrics_map_clone)
124
175
 
125
- if !metrics.metrics_data.empty? && !metrics.target_data.empty?
176
+ unless metrics.metrics_data.empty?
126
177
  start_time = (Time.now.to_f * 1000).to_i
127
178
  @connector.post_metrics(metrics)
128
179
  end_time = (Time.now.to_f * 1000).to_i
@@ -130,20 +181,13 @@ class MetricsProcessor < Closeable
130
181
  @config.logger.debug "Metrics service API duration=[" + (end_time - start_time).to_s + "]"
131
182
  end
132
183
  end
133
-
134
- @global_target_set.merge(@staging_target_set)
135
- @staging_target_set.clear
136
-
137
184
  end
138
185
 
139
- def prepare_summary_metrics_body(freq_map)
186
+ def prepare_summary_metrics_body(evaluation_metrics_map, target_metrics_map)
140
187
  metrics = OpenapiClient::Metrics.new({ :target_data => [], :metrics_data => [] })
141
- add_target_data(metrics, Target.new(name = @global_target_name, identifier = @global_target))
142
- freq_map.each_key do |key|
143
- add_target_data(metrics, key.target)
144
- end
188
+
145
189
  total_count = 0
146
- freq_map.each do |key, value|
190
+ evaluation_metrics_map.each do |key, value|
147
191
  total_count += value
148
192
  metrics_data = OpenapiClient::MetricsData.new({ :attributes => [] })
149
193
  metrics_data.timestamp = (Time.now.to_f * 1000).to_i
@@ -151,13 +195,17 @@ class MetricsProcessor < Closeable
151
195
  metrics_data.metrics_type = "FFMETRICS"
152
196
  metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @feature_name_attribute, :value => key.feature_config.feature }))
153
197
  metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @variation_identifier_attribute, :value => key.variation.identifier }))
154
- metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @target_attribute, :value => @global_target }))
198
+ metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @target_attribute, :value => @global_target_identifier }))
155
199
  metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @sdk_type, :value => @server }))
156
200
  metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @sdk_language, :value => "ruby" }))
157
201
  metrics_data.attributes.push(OpenapiClient::KeyValue.new({ :key => @sdk_version, :value => @jar_version }))
158
202
  metrics.metrics_data.push(metrics_data)
159
203
  end
160
- @config.logger.debug "Pushed #{total_count} metric evaluations to server. metrics_data count is #{freq_map.size}"
204
+ @config.logger.debug "Pushed #{total_count} metric evaluations to server. metrics_data count is #{evaluation_metrics_map.size}. target_data count is #{target_metrics_map.size}"
205
+
206
+ target_metrics_map.each_pair do |_, value|
207
+ add_target_data(metrics, value)
208
+ end
161
209
 
162
210
  metrics
163
211
  end
@@ -167,28 +215,25 @@ class MetricsProcessor < Closeable
167
215
  target_data = OpenapiClient::TargetData.new({ :attributes => [] })
168
216
  private_attributes = target.private_attributes
169
217
 
170
- if !@staging_target_set.include?(target) && !@global_target_set.include?(target) && !target.is_private
171
- @staging_target_set.add(target)
172
- attributes = target.attributes
173
- attributes.each do |k, v|
174
- key_value = OpenapiClient::KeyValue.new
175
- if !private_attributes.empty?
176
- unless private_attributes.include?(k)
177
- key_value = OpenapiClient::KeyValue.new({ :key => k, :value => v.to_s })
178
- end
179
- else
218
+ attributes = target.attributes
219
+ attributes.each do |k, v|
220
+ key_value = OpenapiClient::KeyValue.new
221
+ if !private_attributes.empty?
222
+ unless private_attributes.include?(k)
180
223
  key_value = OpenapiClient::KeyValue.new({ :key => k, :value => v.to_s })
181
224
  end
182
- target_data.attributes.push(key_value)
183
- end
184
- target_data.identifier = target.identifier
185
- if target.name == nil || target.name == ""
186
- target_data.name = target.identifier
187
225
  else
188
- target_data.name = target.name
226
+ key_value = OpenapiClient::KeyValue.new({ :key => k, :value => v.to_s })
189
227
  end
190
- metrics.target_data.push(target_data)
228
+ target_data.attributes.push(key_value)
229
+ end
230
+ target_data.identifier = target.identifier
231
+ if target.name == nil || target.name == ""
232
+ target_data.name = target.identifier
233
+ else
234
+ target_data.name = target.name
191
235
  end
236
+ metrics.target_data.push(target_data)
192
237
  end
193
238
 
194
239
  def start_async
@@ -218,7 +263,7 @@ class MetricsProcessor < Closeable
218
263
  end
219
264
 
220
265
  def get_frequency_map
221
- @frequency_map
266
+ @evaluation_metrics
222
267
  end
223
268
 
224
269
  end
@@ -107,6 +107,7 @@ class StorageRepository < Repository
107
107
  return
108
108
  end
109
109
 
110
+ sort_flag_rules(feature_config)
110
111
  flag_key = format_flag_key(identifier)
111
112
 
112
113
  if @store != nil
@@ -141,6 +142,7 @@ class StorageRepository < Repository
141
142
  return
142
143
  end
143
144
 
145
+ sort_segment_serving_rules(segment)
144
146
  segment_key = format_segment_key(identifier)
145
147
 
146
148
  if @store != nil
@@ -240,6 +242,18 @@ class StorageRepository < Repository
240
242
  false
241
243
  end
242
244
 
245
+ def sort_flag_rules(flag)
246
+ if flag.rules && flag.rules.length > 1
247
+ flag.rules.sort_by!(&:priority)
248
+ end
249
+ end
250
+
251
+ def sort_segment_serving_rules(segment)
252
+ if segment.serving_rules && segment.serving_rules.length > 1
253
+ segment.serving_rules.sort_by!(&:priority)
254
+ end
255
+ end
256
+
243
257
  def is_segment_outdated(identifier, new_segment)
244
258
 
245
259
  segment = get_segment(identifier, false)
@@ -34,6 +34,13 @@ class SdkCodes
34
34
  logger.info SdkCodes.sdk_err_msg(7000)
35
35
  end
36
36
 
37
+ def self.warn_metrics_targets_max_size_exceeded(logger)
38
+ logger.warn SdkCodes.sdk_err_msg(7004)
39
+ end
40
+
41
+ def self.warn_metrics_evaluations_max_size_exceeded(logger)
42
+ logger.warn SdkCodes.sdk_err_msg(7007)
43
+ end
37
44
  def self.warn_auth_failed_srv_defaults(logger)
38
45
  logger.warn SdkCodes.sdk_err_msg(2001)
39
46
  end
@@ -89,6 +96,8 @@ class SdkCodes
89
96
  7000 => "Metrics thread started",
90
97
  7001 => "Metrics thread exited",
91
98
  7002 => "Posting metrics failed, reason:",
99
+ 7004 => "Target metrics exceeded max size, remaining targets for this analytics interval will not be sent",
100
+ 7007 => "Evaluation metrics exceeded max size, remaining evaluations for this analytics interval will not be sent"
92
101
  }
93
102
 
94
103
  def self.sdk_err_msg(error_code, append_text = "")