ff-ruby-server-sdk 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/api.yaml +319 -30
- data/lib/ff/ruby/server/generated/lib/openapi_client/api/client_api.rb +27 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/api/metrics_api.rb +13 -10
- data/lib/ff/ruby/server/generated/lib/openapi_client/api/proxy_api.rb +159 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/configuration.rb +7 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/clause.rb +6 -5
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/distribution.rb +3 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/error.rb +16 -4
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/group_serving_rule.rb +257 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/inline_object.rb +223 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/pagination.rb +5 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/prerequisite.rb +3 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/proxy_config.rb +299 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/proxy_config_all_of.rb +220 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/proxy_config_all_of_environments.rb +251 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/segment.rb +23 -4
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/serve.rb +1 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/serving_rule.rb +4 -5
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/tag.rb +15 -8
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/target.rb +11 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/target_map.rb +8 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/variation.rb +5 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/variation_map.rb +4 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client/models/weighted_variation.rb +3 -0
- data/lib/ff/ruby/server/generated/lib/openapi_client.rb +6 -0
- data/lib/ff/ruby/server/sdk/api/config.rb +1 -1
- data/lib/ff/ruby/server/sdk/api/evaluator.rb +32 -73
- data/lib/ff/ruby/server/sdk/api/metrics_processor.rb +95 -50
- data/lib/ff/ruby/server/sdk/common/sdk_codes.rb +9 -0
- data/lib/ff/ruby/server/sdk/connector/harness_connector.rb +12 -3
- data/lib/ff/ruby/server/sdk/version.rb +1 -1
- data/scripts/sdk_specs.sh +1 -1
- 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,35 @@ 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
|
-
|
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
|
342
313
|
|
343
|
-
|
344
|
-
|
345
|
-
|
314
|
+
new_serving_rules.sort_by!(&:priority)
|
315
|
+
new_serving_rules.each do |serving_rule|
|
316
|
+
if evaluate_clauses_v2(serving_rule.clauses, target)
|
317
|
+
return true
|
318
|
+
end
|
319
|
+
end
|
346
320
|
|
347
|
-
|
321
|
+
else
|
322
|
+
# Fall back to old rules
|
323
|
+
rules = segment.rules
|
324
|
+
if rules != nil && !rules.empty? && evaluate_clauses(rules, target)
|
325
|
+
@logger.debug "Target " + target.name.to_s + " included in segment " + segment.name.to_s + " via rules"
|
326
|
+
return true
|
327
|
+
end
|
348
328
|
end
|
329
|
+
|
349
330
|
end
|
350
331
|
end
|
351
332
|
|
@@ -355,26 +336,21 @@ class Evaluator < Evaluation
|
|
355
336
|
def evaluate_rules(serving_rules, target)
|
356
337
|
|
357
338
|
if target == nil || serving_rules == nil
|
358
|
-
|
359
339
|
return nil
|
360
340
|
end
|
361
341
|
|
362
342
|
sorted = serving_rules.sort do |a, b|
|
363
|
-
|
364
343
|
b.priority <=> a.priority
|
365
344
|
end
|
366
345
|
|
367
346
|
sorted.each do |rule|
|
368
|
-
|
369
347
|
next unless evaluate_rule(rule, target)
|
370
348
|
|
371
349
|
if rule.serve.distribution != nil
|
372
|
-
|
373
350
|
return evaluate_distribution(rule.serve.distribution, target)
|
374
351
|
end
|
375
352
|
|
376
353
|
if rule.serve.variation != nil
|
377
|
-
|
378
354
|
return rule.serve.variation
|
379
355
|
end
|
380
356
|
end
|
@@ -383,14 +359,12 @@ class Evaluator < Evaluation
|
|
383
359
|
end
|
384
360
|
|
385
361
|
def evaluate_rule(serving_rule, target)
|
386
|
-
|
387
362
|
evaluate_clauses(serving_rule.clauses, target)
|
388
363
|
end
|
389
364
|
|
390
365
|
def evaluate_variation_map(variation_maps, target)
|
391
366
|
|
392
367
|
if target == nil
|
393
|
-
|
394
368
|
return nil
|
395
369
|
end
|
396
370
|
|
@@ -399,20 +373,15 @@ class Evaluator < Evaluation
|
|
399
373
|
targets = variation_map.targets
|
400
374
|
|
401
375
|
if targets != nil
|
402
|
-
|
403
376
|
found = nil
|
404
|
-
|
405
377
|
targets.each do |t|
|
406
|
-
|
407
378
|
if t.identifier != nil && t.identifier == target.identifier
|
408
|
-
|
409
379
|
found = t
|
410
380
|
break
|
411
381
|
end
|
412
382
|
end
|
413
383
|
|
414
384
|
if found != nil
|
415
|
-
|
416
385
|
return variation_map.variation
|
417
386
|
end
|
418
387
|
end
|
@@ -420,7 +389,6 @@ class Evaluator < Evaluation
|
|
420
389
|
segment_identifiers = variation_map.target_segments
|
421
390
|
|
422
391
|
if segment_identifiers != nil && is_target_included_or_excluded_in_segment(segment_identifiers, target)
|
423
|
-
|
424
392
|
return variation_map.variation
|
425
393
|
end
|
426
394
|
end
|
@@ -433,32 +401,26 @@ class Evaluator < Evaluation
|
|
433
401
|
variation = feature_config.off_variation
|
434
402
|
|
435
403
|
if feature_config.state == OpenapiClient::FeatureState::ON
|
436
|
-
|
437
404
|
variation = nil
|
438
405
|
|
439
406
|
if feature_config.variation_to_target_map != nil
|
440
|
-
|
441
407
|
variation = evaluate_variation_map(feature_config.variation_to_target_map, target)
|
442
408
|
end
|
443
409
|
|
444
410
|
if variation == nil
|
445
|
-
|
446
411
|
variation = evaluate_rules(feature_config.rules, target)
|
447
412
|
end
|
448
413
|
|
449
414
|
if variation == nil
|
450
|
-
|
451
415
|
variation = evaluate_distribution(feature_config.default_serve.distribution, target)
|
452
416
|
end
|
453
417
|
|
454
418
|
if variation == nil
|
455
|
-
|
456
419
|
variation = feature_config.default_serve.variation
|
457
420
|
end
|
458
421
|
end
|
459
422
|
|
460
423
|
if variation != nil
|
461
|
-
|
462
424
|
return find_variation(feature_config.variations, variation)
|
463
425
|
end
|
464
426
|
|
@@ -519,11 +481,8 @@ class Evaluator < Evaluation
|
|
519
481
|
def is_target_in_list(target, list_of_targets)
|
520
482
|
|
521
483
|
if list_of_targets != nil
|
522
|
-
|
523
484
|
list_of_targets.each do |included_target|
|
524
|
-
|
525
485
|
if included_target.identifier.include?(target.identifier)
|
526
|
-
|
527
486
|
return true
|
528
487
|
end
|
529
488
|
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;
|
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
|
-
@
|
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
|
-
@
|
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
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
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,
|
111
|
-
@
|
128
|
+
event = MetricsEvent.new(feature_config, @global_target, variation)
|
129
|
+
@evaluation_metrics.increment event
|
112
130
|
end
|
113
131
|
|
114
|
-
|
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 @
|
155
|
+
send_data_and_reset_cache(@evaluation_metrics, @target_metrics)
|
118
156
|
|
119
|
-
@config.logger.debug "metrics: frequency map 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(
|
123
|
-
|
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
|
-
|
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(
|
186
|
+
def prepare_summary_metrics_body(evaluation_metrics_map, target_metrics_map)
|
140
187
|
metrics = OpenapiClient::Metrics.new({ :target_data => [], :metrics_data => [] })
|
141
|
-
|
142
|
-
freq_map.each_key do |key|
|
143
|
-
add_target_data(metrics, key.target)
|
144
|
-
end
|
188
|
+
|
145
189
|
total_count = 0
|
146
|
-
|
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 => @
|
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 #{
|
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
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
226
|
+
key_value = OpenapiClient::KeyValue.new({ :key => k, :value => v.to_s })
|
189
227
|
end
|
190
|
-
|
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
|
-
@
|
266
|
+
@evaluation_metrics
|
222
267
|
end
|
223
268
|
|
224
269
|
end
|
@@ -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 = "")
|
@@ -74,11 +74,10 @@ class HarnessConnector < Connector
|
|
74
74
|
def get_segments
|
75
75
|
|
76
76
|
begin
|
77
|
-
|
78
77
|
return @api.get_all_segments(
|
79
78
|
|
80
79
|
environment_uuid = @environment,
|
81
|
-
opts =
|
80
|
+
opts = get_segment_query_params
|
82
81
|
)
|
83
82
|
|
84
83
|
rescue OpenapiClient::ApiError => e
|
@@ -104,7 +103,7 @@ class HarnessConnector < Connector
|
|
104
103
|
|
105
104
|
identifier = identifier,
|
106
105
|
environment_uuid = @environment,
|
107
|
-
opts =
|
106
|
+
opts = get_segment_query_params
|
108
107
|
)
|
109
108
|
end
|
110
109
|
|
@@ -247,6 +246,16 @@ class HarnessConnector < Connector
|
|
247
246
|
}
|
248
247
|
end
|
249
248
|
|
249
|
+
def get_segment_query_params
|
250
|
+
{
|
251
|
+
:'query_params' => {
|
252
|
+
|
253
|
+
:'cluster' => @cluster,
|
254
|
+
:'rules' => 'v2'
|
255
|
+
}
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
250
259
|
def log_error(prefix, e)
|
251
260
|
|
252
261
|
if e.code == 0
|
data/scripts/sdk_specs.sh
CHANGED