ff-ruby-server-sdk 1.2.1 → 1.3.0
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 +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