ff-ruby-server-sdk 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/example/getting_started/getting_started.rb +1 -0
- data/lib/ff/ruby/server/sdk/api/auth_service.rb +3 -3
- data/lib/ff/ruby/server/sdk/api/evaluator.rb +30 -37
- data/lib/ff/ruby/server/sdk/api/inner_client.rb +10 -20
- data/lib/ff/ruby/server/sdk/api/metrics_processor.rb +5 -4
- data/lib/ff/ruby/server/sdk/api/polling_processor.rb +10 -11
- data/lib/ff/ruby/server/sdk/api/update_processor.rb +1 -3
- data/lib/ff/ruby/server/sdk/common/sdk_codes.rb +102 -0
- data/lib/ff/ruby/server/sdk/connector/events.rb +13 -13
- data/lib/ff/ruby/server/sdk/connector/harness_connector.rb +9 -10
- data/lib/ff/ruby/server/sdk/version.rb +1 -1
- data/scripts/sdk_specs.sh +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab04a74816651d46324faf27b7aac91d4d6ef5941c01eee61a674fb36cf54bd1
|
4
|
+
data.tar.gz: f52922e05d01426ba12f63e07b5f6e25fbfe477f83c44d13cba72038b35932dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d4038c666ffe22ce8170e17fd8bec516068c0e4fbb5034b706e5efafd3e612d06a4b9cd2b03e63d70bbb9b7b13f8e26360f5f5b26684bcb40904228afa449d7
|
7
|
+
data.tar.gz: 9164338df82c7c97cd2620d302e6d7b8f43299b2a5580988288ddf4ad6bf5b3469519d8ece420333b2c28ea908de27076d5e43905ebe8045b3c722f4909dbc69
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# [1.1.0]
|
2
|
+
|
3
|
+
- [FFM-7285] - Remove Metrics queue and implement Map for better memory usage
|
4
|
+
- [FFM-7325] - Improve authentication retry logic
|
5
|
+
- [FFM-6926] - Add basic Ruby on Rails example
|
6
|
+
- [FFM-6965] - Fixes analytics_enabled(false) which didn't fully turn off metrics
|
7
|
+
- [FFM-7005] - Add TLS support custom CAs and remove sse-client
|
8
|
+
- [FFM-7292] - Add HTTP headers for diagnostics
|
9
|
+
|
1
10
|
# [1.0.6]
|
2
11
|
|
3
12
|
- [FFM-3715] - Updates open api dependency issue
|
@@ -36,7 +36,7 @@ class AuthService < Closeable
|
|
36
36
|
@logger.warn "Got HTTP code #{http_code} while authenticating on attempt #{attempt}, will retry in #{delay_ms} ms"
|
37
37
|
sleep(delay_ms/1000)
|
38
38
|
attempt += 1
|
39
|
-
@logger
|
39
|
+
SdkCodes::warn_auth_retying @logger, attempt
|
40
40
|
else
|
41
41
|
@logger.warn "Auth Service got HTTP code #{http_code} while authenticating, will not attempt to reconnect"
|
42
42
|
@callback.on_auth_failed
|
@@ -67,10 +67,10 @@ class AuthService < Closeable
|
|
67
67
|
|
68
68
|
def stop_async
|
69
69
|
if @thread != nil
|
70
|
-
@logger.
|
70
|
+
@logger.debug "Stopping Auth service, status=#{@thread.status}"
|
71
71
|
@thread.exit
|
72
72
|
@thread = nil
|
73
|
-
@logger.
|
73
|
+
@logger.debug "Stopping Auth service done"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -3,6 +3,7 @@ require "murmurhash3"
|
|
3
3
|
|
4
4
|
require_relative "evaluation"
|
5
5
|
require_relative "../common/repository"
|
6
|
+
require_relative "../common/sdk_codes"
|
6
7
|
|
7
8
|
class Evaluator < Evaluation
|
8
9
|
|
@@ -33,6 +34,7 @@ class Evaluator < Evaluation
|
|
33
34
|
return variation.value == "true"
|
34
35
|
end
|
35
36
|
|
37
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
36
38
|
default_value
|
37
39
|
end
|
38
40
|
|
@@ -45,6 +47,7 @@ class Evaluator < Evaluation
|
|
45
47
|
return variation.value
|
46
48
|
end
|
47
49
|
|
50
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
48
51
|
default_value
|
49
52
|
end
|
50
53
|
|
@@ -57,6 +60,7 @@ class Evaluator < Evaluation
|
|
57
60
|
return variation.value.to_i
|
58
61
|
end
|
59
62
|
|
63
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
60
64
|
default_value
|
61
65
|
end
|
62
66
|
|
@@ -68,6 +72,7 @@ class Evaluator < Evaluation
|
|
68
72
|
return variation.value.to_f
|
69
73
|
end
|
70
74
|
|
75
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
71
76
|
default_value
|
72
77
|
end
|
73
78
|
|
@@ -80,6 +85,7 @@ class Evaluator < Evaluation
|
|
80
85
|
return JSON.parse(variation.value)
|
81
86
|
end
|
82
87
|
|
88
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
83
89
|
default_value
|
84
90
|
end
|
85
91
|
|
@@ -219,13 +225,13 @@ class Evaluator < Evaluation
|
|
219
225
|
|
220
226
|
clauses.each do |clause|
|
221
227
|
|
222
|
-
|
228
|
+
if evaluate_clause(clause, target)
|
223
229
|
|
224
|
-
return
|
230
|
+
return true
|
225
231
|
end
|
226
232
|
end
|
227
233
|
|
228
|
-
|
234
|
+
false
|
229
235
|
end
|
230
236
|
|
231
237
|
def evaluate_clause(clause, target)
|
@@ -295,7 +301,7 @@ class Evaluator < Evaluation
|
|
295
301
|
|
296
302
|
if operator == "in"
|
297
303
|
|
298
|
-
return
|
304
|
+
return clause.values.include?(object)
|
299
305
|
end
|
300
306
|
|
301
307
|
if operator == "segmentMatch"
|
@@ -460,60 +466,47 @@ class Evaluator < Evaluation
|
|
460
466
|
prerequisites = parent_feature_config.prerequisites
|
461
467
|
|
462
468
|
if prerequisites != nil && !prerequisites.empty?
|
469
|
+
@logger.debug "Checking prerequisite #{prerequisites.to_s} of flag #{parent_feature_config.feature}"
|
463
470
|
|
464
|
-
|
465
|
-
|
466
|
-
prerequisites.each do |pqs|
|
467
|
-
|
468
|
-
pre_req_feature = pqs.feature
|
469
|
-
|
470
|
-
pre_req_feature_config = @repository.get_flag(pre_req_feature)
|
471
|
-
|
472
|
-
if pre_req_feature_config == nil
|
473
|
-
|
474
|
-
@logger.debug "Could not retrieve the pre requisite details of feature flag: " + pre_req_feature.to_s
|
471
|
+
prerequisites.each do |pre_req|
|
472
|
+
pre_req_flag = @repository.get_flag(pre_req.feature)
|
475
473
|
|
474
|
+
if pre_req_flag == nil
|
475
|
+
@logger.debug "Could not retrieve the pre requisite details of feature flag: #{pre_req.feature}"
|
476
476
|
return true
|
477
477
|
end
|
478
478
|
|
479
|
-
|
480
|
-
|
481
|
-
if pre_req_evaluated_variation == nil
|
482
|
-
|
483
|
-
@logger.debug "Could not evaluate the prerequisite details of feature flag: " + pre_req_feature.to_s
|
479
|
+
evaluated_pre_req = evaluate_flag(pre_req_flag, target)
|
484
480
|
|
481
|
+
if evaluated_pre_req == nil
|
482
|
+
@logger.debug "Could not evaluate the prerequisite details of feature flag: #{pre_req.feature}"
|
485
483
|
return true
|
486
484
|
end
|
487
485
|
|
488
|
-
@logger.debug "Pre requisite flag " + pre_req_feature_config.feature + " has variation " +
|
489
|
-
pre_req_evaluated_variation.to_s + " for target " + target.to_s
|
490
|
-
|
491
|
-
valid_pre_req_variations = pqs.variations
|
492
|
-
|
493
|
-
@logger.debug "Pre requisite flag " + pre_req_feature_config.to_s + " should have the variations " +
|
494
|
-
valid_pre_req_variations.to_s
|
495
|
-
|
496
486
|
none_match = true
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
if element.include?(pre_req_evaluated_variation.identifier)
|
501
|
-
|
487
|
+
pre_req.variations.each do |next_variation|
|
488
|
+
if next_variation.include?(evaluated_pre_req.identifier)
|
502
489
|
none_match = false
|
503
490
|
break
|
504
491
|
end
|
505
492
|
end
|
506
493
|
|
507
494
|
if none_match
|
508
|
-
|
495
|
+
@logger.debug "Prerequisite flag #{pre_req_flag.feature} has no matching variations for flag #{parent_feature_config.feature}"
|
509
496
|
return false
|
510
497
|
else
|
511
|
-
|
512
|
-
|
498
|
+
unless check_pre_requisite(pre_req_flag, target)
|
499
|
+
@logger.debug "Prerequisite flag #{pre_req_flag.feature} is switched off for flag #{parent_feature_config.feature}"
|
500
|
+
return false
|
501
|
+
end
|
513
502
|
end
|
514
|
-
end
|
503
|
+
end # prerequisites.each
|
504
|
+
|
505
|
+
@logger.debug "All prerequisite flags are switched on for flag #{parent_feature_config.feature}"
|
506
|
+
return true
|
515
507
|
end
|
516
508
|
|
509
|
+
@logger.debug "No prerequisite flags present for flag #{parent_feature_config.feature}, skipped"
|
517
510
|
true
|
518
511
|
end
|
519
512
|
|
@@ -12,14 +12,14 @@ require_relative "inner_client_repository_callback"
|
|
12
12
|
require_relative "inner_client_flag_evaluate_callback"
|
13
13
|
|
14
14
|
require_relative "../connector/harness_connector"
|
15
|
+
require_relative "../common/sdk_codes"
|
15
16
|
|
16
17
|
class InnerClient < ClientCallback
|
17
18
|
|
18
19
|
def initialize(api_key = nil, config = nil, connector = nil)
|
19
20
|
|
20
21
|
if api_key == nil || api_key == ""
|
21
|
-
|
22
|
-
raise "SDK key is not provided"
|
22
|
+
SdkCodes::raise_missing_sdk_key config.logger
|
23
23
|
end
|
24
24
|
|
25
25
|
if config == nil
|
@@ -87,7 +87,7 @@ class InnerClient < ClientCallback
|
|
87
87
|
|
88
88
|
def on_auth_success
|
89
89
|
|
90
|
-
@config.logger
|
90
|
+
SdkCodes::info_sdk_auth_ok @config.logger
|
91
91
|
|
92
92
|
if @closing
|
93
93
|
|
@@ -107,9 +107,8 @@ class InnerClient < ClientCallback
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def on_auth_failed
|
110
|
-
@config.logger
|
110
|
+
SdkCodes::warn_auth_failed_srv_defaults @config.logger
|
111
111
|
@initialized = true
|
112
|
-
|
113
112
|
end
|
114
113
|
|
115
114
|
def close
|
@@ -205,19 +204,19 @@ class InnerClient < ClientCallback
|
|
205
204
|
if processor == @poll_processor
|
206
205
|
|
207
206
|
@poller_ready = true
|
208
|
-
@config.logger.
|
207
|
+
@config.logger.debug "PollingProcessor ready"
|
209
208
|
end
|
210
209
|
|
211
210
|
if processor == @update_processor
|
212
211
|
|
213
212
|
@stream_ready = true
|
214
|
-
@config.logger.
|
213
|
+
@config.logger.debug "Updater ready"
|
215
214
|
end
|
216
215
|
|
217
216
|
if processor == @metrics_processor
|
218
217
|
|
219
218
|
@metrics_ready = true
|
220
|
-
@config.logger.
|
219
|
+
@config.logger.debug "Metrics ready"
|
221
220
|
end
|
222
221
|
|
223
222
|
if (@config.stream_enabled && !@stream_ready) ||
|
@@ -227,21 +226,16 @@ class InnerClient < ClientCallback
|
|
227
226
|
return
|
228
227
|
end
|
229
228
|
|
230
|
-
@config.logger
|
229
|
+
SdkCodes.info_sdk_init_ok @config.logger
|
231
230
|
|
232
231
|
@initialized = true
|
233
|
-
|
234
|
-
# TODO: notify - Reactivity support
|
235
|
-
# TODO: notify_consumers - Reactivity support
|
236
|
-
|
237
|
-
@config.logger.info "Initialization is completed"
|
238
232
|
end
|
239
233
|
|
240
234
|
def wait_for_initialization
|
241
235
|
|
242
236
|
synchronize do
|
243
237
|
|
244
|
-
@config.logger.
|
238
|
+
@config.logger.debug "Waiting for initialization to finish"
|
245
239
|
|
246
240
|
until @initialized
|
247
241
|
|
@@ -253,7 +247,7 @@ class InnerClient < ClientCallback
|
|
253
247
|
raise "Initialization failed"
|
254
248
|
end
|
255
249
|
|
256
|
-
@config.logger.
|
250
|
+
@config.logger.debug "Waiting for initialization has completed"
|
257
251
|
end
|
258
252
|
end
|
259
253
|
|
@@ -261,10 +255,6 @@ class InnerClient < ClientCallback
|
|
261
255
|
|
262
256
|
def setup
|
263
257
|
|
264
|
-
@config.logger.info "SDK is not initialized yet! If store is used then values will be loaded from store" +
|
265
|
-
" otherwise default values will be used in meantime. You can use waitForInitialization method for SDK" +
|
266
|
-
" to be ready."
|
267
|
-
|
268
258
|
@repository = StorageRepository.new(@config.cache, @repository_callback, @config.store, @config.logger)
|
269
259
|
|
270
260
|
@metrics_callback = InnerClientMetricsCallback.new(self, @config.logger)
|
@@ -4,6 +4,7 @@ require "concurrent-ruby"
|
|
4
4
|
require_relative "../dto/target"
|
5
5
|
require_relative "../../sdk/version"
|
6
6
|
require_relative "../common/closeable"
|
7
|
+
require_relative "../common/sdk_codes"
|
7
8
|
require_relative "../api/metrics_event"
|
8
9
|
require_relative "../api/summary_metrics"
|
9
10
|
|
@@ -83,18 +84,18 @@ class MetricsProcessor < Closeable
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def start
|
86
|
-
@config.logger.
|
87
|
+
@config.logger.debug "Starting metrics processor with request interval: " + @config.frequency.to_s
|
87
88
|
start_async
|
88
89
|
end
|
89
90
|
|
90
91
|
def stop
|
91
|
-
@config.logger.
|
92
|
+
@config.logger.debug "Stopping metrics processor"
|
92
93
|
stop_async
|
93
94
|
end
|
94
95
|
|
95
96
|
def close
|
96
97
|
stop
|
97
|
-
@config.logger.
|
98
|
+
@config.logger.debug "Closing metrics processor"
|
98
99
|
end
|
99
100
|
|
100
101
|
def register_evaluation(target, feature_config, variation)
|
@@ -198,7 +199,7 @@ class MetricsProcessor < Closeable
|
|
198
199
|
while @ready do
|
199
200
|
unless @initialized
|
200
201
|
@initialized = true
|
201
|
-
@config.logger
|
202
|
+
SdkCodes::info_metrics_thread_started @config.logger
|
202
203
|
end
|
203
204
|
sleep(@config.frequency)
|
204
205
|
run_one_iteration
|
@@ -29,13 +29,13 @@ class PollingProcessor < Closeable
|
|
29
29
|
|
30
30
|
flags = []
|
31
31
|
|
32
|
-
@logger.
|
32
|
+
@logger.debug "Fetching flags started"
|
33
33
|
|
34
34
|
result = @connector.get_flags
|
35
35
|
|
36
36
|
if result != nil
|
37
37
|
|
38
|
-
@logger.
|
38
|
+
@logger.debug "Flags are fetched"
|
39
39
|
|
40
40
|
result.each { |fc|
|
41
41
|
|
@@ -47,7 +47,7 @@ class PollingProcessor < Closeable
|
|
47
47
|
}
|
48
48
|
end
|
49
49
|
|
50
|
-
@logger.
|
50
|
+
@logger.debug "Fetching flags finished"
|
51
51
|
|
52
52
|
flags
|
53
53
|
end
|
@@ -56,13 +56,13 @@ class PollingProcessor < Closeable
|
|
56
56
|
|
57
57
|
segments = []
|
58
58
|
|
59
|
-
@logger.
|
59
|
+
@logger.debug "Fetching segments started"
|
60
60
|
|
61
61
|
result = @connector.get_segments
|
62
62
|
|
63
63
|
if result != nil
|
64
64
|
|
65
|
-
@logger.
|
65
|
+
@logger.debug "Segments are fetched"
|
66
66
|
|
67
67
|
result.each { |s|
|
68
68
|
|
@@ -74,7 +74,7 @@ class PollingProcessor < Closeable
|
|
74
74
|
}
|
75
75
|
end
|
76
76
|
|
77
|
-
@logger.
|
77
|
+
@logger.debug "Fetching segments finished"
|
78
78
|
|
79
79
|
segments
|
80
80
|
end
|
@@ -106,7 +106,7 @@ class PollingProcessor < Closeable
|
|
106
106
|
unless @initialized
|
107
107
|
|
108
108
|
@initialized = true
|
109
|
-
@logger
|
109
|
+
SdkCodes::info_poll_started(@logger, @poll_interval_in_sec)
|
110
110
|
|
111
111
|
if @callback != nil
|
112
112
|
|
@@ -137,17 +137,16 @@ class PollingProcessor < Closeable
|
|
137
137
|
|
138
138
|
def start
|
139
139
|
|
140
|
-
@logger.
|
140
|
+
@logger.debug "Starting PollingProcessor with request interval: " + @poll_interval_in_sec.to_s
|
141
141
|
start_async
|
142
142
|
end
|
143
143
|
|
144
144
|
def stop
|
145
145
|
|
146
|
-
@logger.
|
146
|
+
@logger.debug "Stopping PollingProcessor"
|
147
147
|
stop_async
|
148
148
|
unless @ready
|
149
|
-
|
150
|
-
@logger.info "PollingProcessor stopped"
|
149
|
+
SdkCodes::info_polling_stopped @logger
|
151
150
|
end
|
152
151
|
end
|
153
152
|
|
@@ -28,7 +28,7 @@ class UpdateProcessor < Closeable
|
|
28
28
|
|
29
29
|
def start
|
30
30
|
|
31
|
-
@logger.
|
31
|
+
@logger.debug "Starting updater (EventSource)"
|
32
32
|
|
33
33
|
if @updater != nil
|
34
34
|
|
@@ -105,8 +105,6 @@ class UpdateProcessor < Closeable
|
|
105
105
|
|
106
106
|
def process_flag(message)
|
107
107
|
|
108
|
-
@logger.info "Processing flag message: " + message.to_s
|
109
|
-
|
110
108
|
config = @connector.get_flag(message["identifier"])
|
111
109
|
|
112
110
|
if config != nil
|
@@ -0,0 +1,102 @@
|
|
1
|
+
|
2
|
+
class SdkCodes
|
3
|
+
def self.raise_missing_sdk_key(logger)
|
4
|
+
msg = SdkCodes.sdk_err_msg(1002)
|
5
|
+
logger.error msg
|
6
|
+
raise msg
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.info_poll_started(logger, durationSec)
|
10
|
+
logger.info SdkCodes.sdk_err_msg(4000, durationSec*1000)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.info_sdk_init_ok(logger)
|
14
|
+
logger.info SdkCodes.sdk_err_msg(1000)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.info_sdk_auth_ok(logger)
|
18
|
+
logger.info SdkCodes.sdk_err_msg(2000)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.info_polling_stopped(logger)
|
22
|
+
logger.info SdkCodes.sdk_err_msg(4001)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.info_stream_connected(logger)
|
26
|
+
logger.info SdkCodes.sdk_err_msg(5000)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.info_stream_event_received(logger, event_json)
|
30
|
+
logger.info SdkCodes.sdk_err_msg(5002, event_json)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.info_metrics_thread_started(logger)
|
34
|
+
logger.info SdkCodes.sdk_err_msg(7000)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.warn_auth_failed_srv_defaults(logger)
|
38
|
+
logger.warn SdkCodes.sdk_err_msg(2001)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.warn_auth_retying(logger, attempt)
|
42
|
+
logger.warn SdkCodes.sdk_err_msg(2003, ", attempt #{attempt}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.warn_stream_disconnected(logger, reason)
|
46
|
+
logger.warn SdkCodes.sdk_err_msg(5001, reason)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.warn_post_metrics_failed(logger, reason)
|
50
|
+
logger.warn SdkCodes.sdk_err_msg(7002, reason)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.warn_default_variation_served(logger, identifier, target, default)
|
54
|
+
logger.warn SdkCodes.sdk_err_msg(6001, "identifier=%s, target=%s, default=%s" % [identifier, target.identifier, default])
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
@map =
|
60
|
+
{
|
61
|
+
# SDK_INIT_1xxx
|
62
|
+
1000 => "The SDK has successfully initialized",
|
63
|
+
1001 => "The SDK has failed to initialize due to the following authentication error:",
|
64
|
+
1002 => "The SDK has failed to initialize due to a missing or empty API key",
|
65
|
+
# SDK_AUTH_2xxx
|
66
|
+
2000 => "Authenticated ok",
|
67
|
+
2001 => "Authentication failed with a non-recoverable error - defaults will be served",
|
68
|
+
2003 => "Retrying to authenticate",
|
69
|
+
# SDK_POLL_4xxx
|
70
|
+
4000 => "Polling started, intervalMs:",
|
71
|
+
4001 => "Polling stopped",
|
72
|
+
# SDK_STREAM_5xxx
|
73
|
+
5000 => "SSE stream connected ok",
|
74
|
+
5001 => "SSE stream disconnected, reason:",
|
75
|
+
5002 => "SSE event received: ",
|
76
|
+
5003 => "SSE retrying to connect in",
|
77
|
+
# SDK_EVAL_6xxx
|
78
|
+
6000 => "Evaluated variation successfully",
|
79
|
+
6001 => "Default variation was served",
|
80
|
+
# SDK_METRICS_7xxx
|
81
|
+
7000 => "Metrics thread started",
|
82
|
+
7001 => "Metrics thread exited",
|
83
|
+
7002 => "Posting metrics failed, reason:",
|
84
|
+
}
|
85
|
+
|
86
|
+
def self.sdk_err_msg(error_code, append_text = "")
|
87
|
+
"SDKCODE(%s:%s): %s %s" % [(get_err_class error_code), error_code, @map[error_code], append_text]
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.get_err_class(error_code)
|
91
|
+
if error_code >= 1000 and error_code <= 1999
|
92
|
+
return "init"
|
93
|
+
elsif error_code >= 2000 and error_code <= 2999 then return "auth"
|
94
|
+
elsif error_code >= 4000 and error_code <= 4999 then return "poll"
|
95
|
+
elsif error_code >= 5000 and error_code <= 5999 then return "stream"
|
96
|
+
elsif error_code >= 6000 and error_code <= 6999 then return "eval"
|
97
|
+
elsif error_code >= 7000 and error_code <= 7999 then return "metric"
|
98
|
+
end
|
99
|
+
""
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -2,7 +2,7 @@ require "json"
|
|
2
2
|
require 'restclient'
|
3
3
|
|
4
4
|
require_relative './service'
|
5
|
-
|
5
|
+
require_relative "../common/sdk_codes"
|
6
6
|
class Events < Service
|
7
7
|
|
8
8
|
def initialize(
|
@@ -35,7 +35,7 @@ class Events < Service
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def start
|
38
|
-
@logger.
|
38
|
+
@logger.debug "Starting EventSource service"
|
39
39
|
begin
|
40
40
|
conn = RestClient::Request.execute(method: :get,
|
41
41
|
url: @url,
|
@@ -46,15 +46,13 @@ class Events < Service
|
|
46
46
|
read_timeout: 60,
|
47
47
|
ssl_ca_file: @config.ssl_ca_cert)
|
48
48
|
|
49
|
-
|
50
49
|
rescue => e
|
51
|
-
|
52
|
-
on_error
|
50
|
+
on_error e.message
|
53
51
|
end
|
54
52
|
end
|
55
53
|
|
56
54
|
def stop
|
57
|
-
@logger.
|
55
|
+
@logger.debug "Stopping EventSource service"
|
58
56
|
on_closed
|
59
57
|
end
|
60
58
|
|
@@ -63,23 +61,24 @@ class Events < Service
|
|
63
61
|
end
|
64
62
|
|
65
63
|
def on_open
|
66
|
-
@logger
|
64
|
+
SdkCodes::info_stream_connected @logger
|
67
65
|
@updater.on_connected
|
68
66
|
end
|
69
67
|
|
70
|
-
def on_error
|
71
|
-
@logger
|
68
|
+
def on_error(reason="")
|
69
|
+
SdkCodes::warn_stream_disconnected @logger, reason
|
72
70
|
@updater.on_error
|
73
71
|
stop
|
74
72
|
end
|
75
73
|
|
76
74
|
def on_closed
|
77
|
-
@logger
|
75
|
+
SdkCodes::warn_stream_disconnected @logger, "on_closed called"
|
78
76
|
@updater.on_disconnected
|
79
77
|
end
|
80
78
|
|
81
79
|
def on_message(message)
|
82
|
-
@logger
|
80
|
+
SdkCodes::info_stream_event_received @logger, message.to_s
|
81
|
+
|
83
82
|
msg = JSON.parse(message)
|
84
83
|
@updater.update(msg)
|
85
84
|
end
|
@@ -106,8 +105,9 @@ class Events < Service
|
|
106
105
|
end
|
107
106
|
close
|
108
107
|
else
|
109
|
-
|
110
|
-
|
108
|
+
msg = "SSE ERROR: http_code=%d body=%d" % [response.code, response.body]
|
109
|
+
@logger.warn msg
|
110
|
+
on_error msg
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -35,7 +35,7 @@ class HarnessConnector < Connector
|
|
35
35
|
response = @api.authenticate(opts = options)
|
36
36
|
@token = response.auth_token
|
37
37
|
|
38
|
-
@config.logger.
|
38
|
+
@config.logger.debug "Token has been obtained"
|
39
39
|
process_token
|
40
40
|
return 200
|
41
41
|
|
@@ -49,7 +49,7 @@ class HarnessConnector < Connector
|
|
49
49
|
return -1
|
50
50
|
end
|
51
51
|
|
52
|
-
log_error(e)
|
52
|
+
log_error("auth", e)
|
53
53
|
return e.code
|
54
54
|
end
|
55
55
|
end
|
@@ -66,7 +66,7 @@ class HarnessConnector < Connector
|
|
66
66
|
|
67
67
|
rescue OpenapiClient::ApiError => e
|
68
68
|
|
69
|
-
log_error(e)
|
69
|
+
log_error("get_feature_config", e)
|
70
70
|
return nil
|
71
71
|
end
|
72
72
|
end
|
@@ -83,7 +83,7 @@ class HarnessConnector < Connector
|
|
83
83
|
|
84
84
|
rescue OpenapiClient::ApiError => e
|
85
85
|
|
86
|
-
log_error(e)
|
86
|
+
log_error("get_all_segments", e)
|
87
87
|
return nil
|
88
88
|
end
|
89
89
|
end
|
@@ -127,12 +127,11 @@ class HarnessConnector < Connector
|
|
127
127
|
opts = options
|
128
128
|
)
|
129
129
|
|
130
|
-
@config.logger.
|
130
|
+
@config.logger.debug "Successfully sent analytics data to the server"
|
131
131
|
|
132
132
|
rescue OpenapiClient::ApiError => e
|
133
|
-
|
134
|
-
|
135
|
-
@config.logger.error "Exception while posting metrics to the event server"
|
133
|
+
log_error("post_metrics", e)
|
134
|
+
SdkCodes.warn_post_metrics_failed @config.logger, e.message
|
136
135
|
end
|
137
136
|
end
|
138
137
|
|
@@ -248,7 +247,7 @@ class HarnessConnector < Connector
|
|
248
247
|
}
|
249
248
|
end
|
250
249
|
|
251
|
-
def log_error(e)
|
250
|
+
def log_error(prefix, e)
|
252
251
|
|
253
252
|
if e.code == 0
|
254
253
|
type = "typhoeus/libcurl"
|
@@ -256,6 +255,6 @@ class HarnessConnector < Connector
|
|
256
255
|
type = "HTTP code #{e.code}"
|
257
256
|
end
|
258
257
|
|
259
|
-
@config.logger.warn "OpenapiClient::ApiError (
|
258
|
+
@config.logger.warn "%s: OpenapiClient::ApiError (%s) [\n\n%s\n]" % [prefix, type, e.to_s]
|
260
259
|
end
|
261
260
|
end
|
data/scripts/sdk_specs.sh
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ff-ruby-server-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 'Miloš Vasić, cyr.: Милош Васић'
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -262,6 +262,7 @@ files:
|
|
262
262
|
- lib/ff/ruby/server/sdk/common/closeable.rb
|
263
263
|
- lib/ff/ruby/server/sdk/common/destroyable.rb
|
264
264
|
- lib/ff/ruby/server/sdk/common/repository.rb
|
265
|
+
- lib/ff/ruby/server/sdk/common/sdk_codes.rb
|
265
266
|
- lib/ff/ruby/server/sdk/common/storage.rb
|
266
267
|
- lib/ff/ruby/server/sdk/connector/connector.rb
|
267
268
|
- lib/ff/ruby/server/sdk/connector/events.rb
|