kameleoon-client-ruby 1.0.0 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0d398647ef17fa8d33046f2f591973a57a00fde17fef994d955f23ea474538d
4
- data.tar.gz: fc466cc6b762e1b4759dee2de2914c33ce27274b90bfe00394db5a80017f186e
3
+ metadata.gz: e0deee13cb73acd60d605f479ab0e2ebf374e38e7516d9bea0590b0adbdd7f53
4
+ data.tar.gz: 7c06c8d843f6f291d946375d495a3d573e31f932942c5b6edb2f86abf4d9183f
5
5
  SHA512:
6
- metadata.gz: ad96e42e9c7b75436dca8a6529d2118693b94be8edc7a6d7ee35bfa5cd0909235885f383a313b306912bb79a43aac6b8aee0c6e44d55135c79cca158113fba50
7
- data.tar.gz: d2e75d812cf12088420984120337be790c7b3c60574181572d995f9ac613cf5b884820fddc4e7e2b4938ed3444f27d298e883f1560da34d83150d4b71207077a
6
+ metadata.gz: 8d14ce02c0a2577988a0161292683e9a455c9532dda0fd69e5428d0f0a2bd08bb38114cf8b161d4a123921e08429cf1db126f7b3033d43a0889c4f6eea2d064b
7
+ data.tar.gz: de09c74c6587cbd9f53f44a6673b1d3e2832d3aa135376405d0e7eaef9933bc0891243cc34cb039d2eb72b8b8fa5eeb5045b9e4c69b4a4979aabcae154e8361b
data/README.md CHANGED
@@ -6,7 +6,7 @@ This is the repository for the Kameleoon Ruby SDK.
6
6
  #### Prerequisite:
7
7
  * [Install ruby](https://www.ruby-lang.org/en/documentation/installation)
8
8
 
9
- #### Build and install:
9
+ #### Build and install the gem:
10
10
  * Run `./buildAndInstallGem.sh`
11
11
 
12
12
  ### How to run tests
@@ -14,5 +14,9 @@ This is the repository for the Kameleoon Ruby SDK.
14
14
  * Build and install Kameleoon Gem locally (infos above).
15
15
  * Install rake: `gem install rake`
16
16
 
17
- #### Test:
18
- * Run `rake test`
17
+ #### Run Tests:
18
+ ##### Unit
19
+ * Run `./test.sh -u`
20
+ ##### Integration
21
+ Make sure you kill manually the server test app after the tests are done.
22
+ * Run `./test.sh -i`
data/lib/kameleoon.rb CHANGED
@@ -2,4 +2,4 @@
2
2
  # Kameleoon Ruby Client SDK
3
3
  #
4
4
  require "kameleoon/factory"
5
- require "kameleoon/client"
5
+ require "kameleoon/client"
@@ -19,16 +19,18 @@ module Kameleoon
19
19
 
20
20
  ##
21
21
  # You should create Client with the Client Factory only.
22
+ #
22
23
  def initialize(site_code, path_config_file, blocking, interval, default_timeout, client_id = nil, client_secret = nil)
23
24
  config = YAML.load_file(path_config_file)
24
25
  @site_code = site_code
25
26
  @blocking = blocking
26
- @default_timeout = config['default_timeout'] || default_timeout
27
- @interval = config['actions_configuration_refresh_interval'] || interval
27
+ @default_timeout = config['default_timeout'] || default_timeout # in ms
28
+ @interval = config['actions_configuration_refresh_interval'].to_s + 'm' || interval
28
29
  @tracking_url = config['tracking_url'] || "https://api-ssx.kameleoon.com"
29
30
  @client_id = client_id || config['client_id']
30
31
  @client_secret = client_secret || config['client_secret']
31
- @data_maximum_size = config['visitor_data_maximum_size'] || 500
32
+ @data_maximum_size = config['visitor_data_maximum_size'] || 500 # mb
33
+ @verbose_mode = config['verbose_mode'] || false
32
34
  @experiments = []
33
35
  @feature_flags = []
34
36
  @data = {}
@@ -37,7 +39,6 @@ module Kameleoon
37
39
  ##
38
40
  # Obtain a visitor code.
39
41
  #
40
- #
41
42
  # This method should be called to obtain the Kameleoon visitor_code for the current visitor.
42
43
  # This is especially important when using Kameleoon in a mixed front-end and back-end environment,
43
44
  # where user identification consistency must be guaranteed.
@@ -51,10 +52,9 @@ module Kameleoon
51
52
  # In any case, the server-side (via HTTP header) kameleoonVisitorCode cookie is set with the value. Then this
52
53
  # identifier value is finally returned by the method.
53
54
  #
54
- #
55
55
  # @param [Hash] cookies Cookies of the request.
56
56
  # @param [String] top_level_domain Top level domain of your website, settled while writing cookie.
57
- # @param [String] default_visitor_vode - Optional - Define your default visitor_code (maximum length 100 chars).
57
+ # @param [String] default_visitor_code - Optional - Define your default visitor_code (maximum length 100 chars).
58
58
  #
59
59
  # @return [String] visitor code
60
60
  #
@@ -68,6 +68,7 @@ module Kameleoon
68
68
 
69
69
  ##
70
70
  # Trigger an experiment.
71
+ #
71
72
  # If such a visitor_code has never been associated with any variation, the SDK returns a randomly selected variation.
72
73
  # If a user with a given visitor_code is already registered with a variation, it will detect the previously
73
74
  # registered variation and return the variation_id.
@@ -77,29 +78,33 @@ module Kameleoon
77
78
  # @param [String] visitor_code Visitor code
78
79
  # @param [Integer] experiment_id Id of the experiment you want to trigger.
79
80
  #
80
- # @return [Integer] Variation id
81
+ # @return [Integer] Id of the variation
81
82
  #
82
- # @raise [Kameleoon::Exception::ExperimentNotFound] Raise when experiment configuration is not found
83
+ # @raise [Kameleoon::Exception::ExperimentConfigurationNotFound] Raise when experiment configuration is not found
83
84
  # @raise [Kameleoon::Exception::NotActivated] The visitor triggered the experiment, but did not activate it. Usually, this happens because the user has been associated with excluded traffic
84
85
  # @raise [Kameleoon::Exception::NotTargeted] The visitor is not targeted by the experiment, as the associated targeting segment conditions were not fulfilled. He should see the reference variation
86
+ #
85
87
  def trigger_experiment(visitor_code, experiment_id, timeout = @default_timeout)
86
88
  experiment = @experiments.find { |experiment| experiment['id'].to_s == experiment_id.to_s }
87
89
  if experiment.nil?
88
- raise Exception::ExperimentNotFound.new(experiment_id)
90
+ raise Exception::ExperimentConfigurationNotFound.new(experiment_id)
89
91
  end
90
92
  if @blocking
91
93
  variation_id = nil
92
94
  EM.synchrony do
93
- connexion_options = { :connect_timeout => timeout }
95
+ connexion_options = { :connect_timeout => (timeout.to_f / 1000.0) }
94
96
  body = @data.values.flatten.select { |data| !data.sent }.map { |data| data.obtain_full_post_text_line }
95
97
  .join("\n") || ""
96
98
  path = get_experiment_register_url(visitor_code, experiment_id)
97
99
  request_options = { :path => path, :body => body }
100
+ log "Trigger experiment request: " + request_options.inspect
101
+ log "Trigger experiment connexion:" + connexion_options.inspect
98
102
  request = EM::Synchrony.sync post(request_options, @tracking_url, connexion_options)
99
103
  if is_successful(request)
100
104
  variation_id = request.response
101
105
  else
102
- raise Exception::ExperimentNotFound.new(experiment_id) if variation_id.nil?
106
+ log "Failed to trigger experiment: " + request.inspect
107
+ raise Exception::ExperimentConfigurationNotFound.new(experiment_id) if variation_id.nil?
103
108
  end
104
109
  EM.stop
105
110
  end
@@ -111,16 +116,16 @@ module Kameleoon
111
116
  variation_id.to_i
112
117
  else
113
118
  visitor_data = @data.select { |key, value| key.to_s == visitor_code }.values.flatten! || []
114
- if experiment['targetingSegment'].check_tree(visitor_data)
119
+ if experiment['targetingSegment'].nil? || experiment['targetingSegment'].check_tree(visitor_data)
115
120
  threshold = obtain_hash_double(visitor_code, experiment['respoolTime'], experiment['id'])
116
121
  experiment['deviations'].each do |key, value|
117
122
  threshold -= value
118
123
  if threshold < 0
119
- post_beacon("experimentTracking", visitor_code, experiment_id, key)
124
+ track_experiment(visitor_code, experiment_id, key)
120
125
  return key.to_s.to_i
121
126
  end
122
127
  end
123
- post_beacon("experimentTracking", visitor_code, experiment_id, REFERENCE, true)
128
+ track_experiment(visitor_code, experiment_id, REFERENCE, true)
124
129
  raise Exception::NotActivated.new(visitor_code)
125
130
  end
126
131
  raise Exception::NotTargeted.new(visitor_code)
@@ -128,7 +133,9 @@ module Kameleoon
128
133
  end
129
134
 
130
135
  ##
131
- # Associate various data to a visitor. Note that this method doesn't return any value and doesn't interact with the
136
+ # Associate various data to a visitor.
137
+ #
138
+ # Note that this method doesn't return any value and doesn't interact with the
132
139
  # Kameleoon back-end servers by itself. Instead, the declared data is saved for future sending via the flush method.
133
140
  # This reduces the number of server calls made, as data is usually grouped into a single server call triggered by
134
141
  # the execution of the flush method.
@@ -151,13 +158,14 @@ module Kameleoon
151
158
 
152
159
  ##
153
160
  # Track conversions on a particular goal
161
+ #
154
162
  # This method requires visitor_code and goal_id to track conversion on this particular goal.
155
163
  # In addition, this method also accepts revenue as a third optional argument to track revenue. The visitor_code usually is identical to the one that was used when triggering the experiment.
156
164
  # The track_conversion method doesn't return any value. This method is non-blocking as the server call is made asynchronously.
157
165
  #
158
166
  # @param [String] visitor_code Visitor code
159
167
  # @param [Integer] goal_id Id of the goal
160
- # @param [Float] revenue Revenue of the conversion. This field is optional
168
+ # @param [Float] revenue Optional - Revenue of the conversion.
161
169
  #
162
170
  def track_conversion(visitor_code, goal_id, revenue = 0.0)
163
171
  add_data(visitor_code, Conversion.new(goal_id, revenue))
@@ -166,6 +174,7 @@ module Kameleoon
166
174
 
167
175
  ##
168
176
  # Flush the associated data.
177
+ #
169
178
  # The data added with the method add_data, is not directly sent to the kameleoon servers.
170
179
  # It's stored and accumulated until it is sent automatically by the trigger_experiment or track_conversion methods.
171
180
  # With this method you can manually send it.
@@ -173,11 +182,12 @@ module Kameleoon
173
182
  # @param [String] visitor_code Optional field - Visitor code, without visitor code it flush all of the data
174
183
  #
175
184
  def flush(visitor_code = nil)
176
- post_beacon("dataTracking", visitor_code)
185
+ track_data(visitor_code)
177
186
  end
178
187
 
179
188
  ##
180
189
  # Obtain variation associated data.
190
+ #
181
191
  # To retrieve JSON data associated with a variation, call the obtain_variation_associated_data method of our SDK.
182
192
  # The JSON data usually represents some metadata of the variation, and can be configured on our web application
183
193
  # interface or via our Automation API.
@@ -186,20 +196,21 @@ module Kameleoon
186
196
  #
187
197
  # @param [Integer] variation_id
188
198
  #
189
- # @return [String] json string of the variation data.
199
+ # @return [Hash] Hash object of the json object.
190
200
  #
191
201
  # @raise [Kameleoon::Exception::VariationNotFound] Raise exception if the variation is not found.
202
+ #
192
203
  def obtain_variation_associated_data(variation_id)
193
204
  variation = @experiments.map { |experiment| experiment['variations'] }.flatten.select { |variation| variation['id'].to_i == variation_id.to_i }.first
194
205
  if variation.nil?
195
206
  raise Exception::VariationNotFound.new(variation_id)
196
207
  else
197
- variation['customJson'].to_json
208
+ variation['customJson']
198
209
  end
199
210
  end
200
211
 
201
212
  #
202
- # Method to activate a feature toggle.
213
+ # Activate a feature toggle.
203
214
  #
204
215
  # This method takes a visitor_code and feature_key (or feature_id) as mandatory arguments to check if the specified feature will be active for a given user.
205
216
  # If such a user has never been associated with this feature flag, the SDK returns a boolean value randomly (true if the user should have this feature or false if not). If a user with a given visitorCode is already registered with this feature flag, it will detect the previous featureFlag value.
@@ -208,26 +219,31 @@ module Kameleoon
208
219
  # @param [String] visitor_code
209
220
  # @param [String | Integer] feature_key
210
221
  #
211
- # @raise [Kameleoon::Exception::FeatureFlagNotFound]
222
+ # @raise [Kameleoon::Exception::FeatureConfigurationNotFound]
212
223
  # @raise [Kameleoon::Exception::NotTargeted]
224
+ #
213
225
  def activate_feature(visitor_code, feature_key, timeout = @default_timeout)
214
226
  feature_flag = get_feature_flag(feature_key)
215
227
  id = feature_flag['id']
216
228
  if @blocking
217
229
  result = nil
218
230
  EM.synchrony do
219
- connexion_options = { :connect_timeout => timeout }
231
+ connexion_options = { :connect_timeout => (timeout.to_f / 1000.0) }
220
232
  request_options = {
221
233
  :path => get_experiment_register_url(visitor_code, id),
222
- :body => (select_data_to_sent(visitor_code).values.map { |data| data.obtain_full_post_text_line }.join("\n") || "").encode("UTF-8")
234
+ :body => (data_not_sent(visitor_code).values.map { |data| data.obtain_full_post_text_line }.join("\n") || "").encode("UTF-8")
223
235
  }
236
+ log "Activate feature request: " + request_options.inspect
237
+ log "Activate feature connexion:" + connexion_options.inspect
224
238
  request = EM::Synchrony.sync post(request_options, @tracking_url, connexion_options)
225
239
  if is_successful(request)
226
240
  result = request.response
241
+ else
242
+ log "Failed to get activation:" + result.inspect
227
243
  end
228
244
  EM.stop
229
245
  end
230
- raise Exception::FeatureFlagNotFound.new(id) if result.nil?
246
+ raise Exception::FeatureConfigurationNotFound.new(id) if result.nil?
231
247
  result.to_s != "null"
232
248
 
233
249
  else
@@ -235,10 +251,10 @@ module Kameleoon
235
251
  if feature_flag['targetingSegment'].nil? || feature_flag['targetingSegment'].check_tree(visitor_data)
236
252
  threshold = obtain_hash_double(visitor_code, {}, id)
237
253
  if threshold <= feature_flag['expositionRate']
238
- post_beacon("experimentTracking", visitor_code, id, feature_flag["variationsId"].first)
254
+ track_experiment(visitor_code, id, feature_flag["variationsId"].first)
239
255
  return true
240
256
  else
241
- post_beacon("experimentTracking", visitor_code, id, REFERENCE, true)
257
+ track_experiment(visitor_code, id, REFERENCE, true)
242
258
  return false
243
259
  end
244
260
  else
@@ -248,17 +264,21 @@ module Kameleoon
248
264
  end
249
265
 
250
266
  ##
251
- # Method To retrieve a feature variable. A feature variable can be changed easily via our web application.
267
+ # Retrieve a feature variable.
268
+ #
269
+ # A feature variable can be changed easily via our web application.
252
270
  #
253
271
  # @param [String | Integer] feature_key
254
272
  # @param [String ] variable_key
255
273
  #
256
- # @raise [Kameleoon::Exception::FeatureFlagNotFound]
274
+ # @raise [Kameleoon::Exception::FeatureConfigurationNotFound]
275
+ # @raise [Kameleoon::Exception::FeatureVariableNotFound]
276
+ #
257
277
  def obtain_feature_variable(feature_key, variable_key)
258
278
  feature_flag = get_feature_flag(feature_key)
259
279
  custom_json = feature_flag["variations"].first['customJson'][variable_key.to_s]
260
280
  if custom_json.nil?
261
- raise Exception::FeatureFlagNotFound.new("Feature variable not found")
281
+ raise Exception::FeatureVariableNotFound.new("Feature variable not found")
262
282
  end
263
283
  case custom_json['type']
264
284
  when "Boolean"
@@ -268,9 +288,9 @@ module Kameleoon
268
288
  when "Number"
269
289
  return custom_json['value'].to_f
270
290
  when "Json"
271
- return custom_json['value'].to_json
291
+ return custom_json['value']
272
292
  else
273
- raise Exception::FeatureFlagNotFound.new("Unknown type for feature variable")
293
+ raise TypeError.new("Unknown type for feature variable")
274
294
  end
275
295
  end
276
296
 
@@ -278,15 +298,16 @@ module Kameleoon
278
298
  API_SSX_URL = "https://api-ssx.kameleoon.com"
279
299
  REFERENCE = 0
280
300
  attr :site_code, :client_id, :client_secret, :access_token, :experiments, :feature_flags, :scheduler, :data,
281
- :blocking, :tracking_url, :default_timeout, :interval, :memory_limit
301
+ :blocking, :tracking_url, :default_timeout, :interval, :memory_limit, :verbose_mode
282
302
 
283
303
  def fetch_configuration
284
- print "=> Starting Scheduler"
285
304
  @scheduler = Rufus::Scheduler.singleton
286
305
  @scheduler.every @interval do
306
+ log("Scheduled job to fetch configuration is starting.")
287
307
  fetch_configuration_job
288
308
  end
289
309
  @scheduler.schedule '0s' do
310
+ log("Start-up, fetching is starting")
290
311
  fetch_configuration_job
291
312
  end
292
313
  end
@@ -300,8 +321,8 @@ module Kameleoon
300
321
  @feature_flags ||= []
301
322
  else
302
323
  site_id = site.first['id']
303
- @experiments = obtain_tests(site_id)
304
- @feature_flags = obtain_feature_flags(site_id)
324
+ @experiments = obtain_tests(site_id) || @experiments
325
+ @feature_flags = obtain_feature_flags(site_id) || @feature_flags
305
326
  end
306
327
  EM.stop
307
328
  end
@@ -322,15 +343,19 @@ module Kameleoon
322
343
  end
323
344
 
324
345
  def obtain_site
346
+ log "Fetching site"
325
347
  query_params = { 'perPage' => 1 }
326
348
  filters = [hash_filter('code', 'EQUAL', [@site_code])]
327
349
  request = fetch_one('sites', query_params, filters)
328
350
  if request != false
329
- JSON.parse(request.response)
351
+ sites = JSON.parse(request.response)
352
+ log "Sites are fetched: " + sites.inspect
353
+ sites
330
354
  end
331
355
  end
332
356
 
333
357
  def obtain_access_token
358
+ log "Fetching bearer token"
334
359
  body = {
335
360
  'grant_type' => 'client_credentials',
336
361
  'client_id' => @client_id,
@@ -341,6 +366,9 @@ module Kameleoon
341
366
  request = EM::Synchrony.sync post({ :path => '/oauth/token', :body => body, :head => header })
342
367
  if is_successful(request)
343
368
  @access_token = JSON.parse(request.response)['access_token']
369
+ log "Bearer Token is fetched: " + @access_token.to_s
370
+ else
371
+ log "Failed to fetch bearer token: " + request.inspect
344
372
  end
345
373
  end
346
374
 
@@ -369,26 +397,32 @@ module Kameleoon
369
397
  end
370
398
 
371
399
  def obtain_tests(site_id, per_page = -1)
400
+ log "Fetching experiments"
372
401
  query_values = { 'perPage' => per_page }
373
402
  filters = [
374
403
  hash_filter('siteId', 'EQUAL', [site_id]),
375
404
  hash_filter('status', 'EQUAL', ['ACTIVE']),
376
405
  hash_filter('type', 'IN', ['SERVER_SIDE', 'HYBRID'])
377
406
  ]
378
- fetch_all('experiments', query_values, filters).map { |it| JSON.parse(it.response) }.flatten.map do |test|
407
+ experiments = fetch_all('experiments', query_values, filters).map { |it| JSON.parse(it.response) }.flatten.map do |test|
379
408
  complete_experiment(test)
380
409
  end
410
+ log "Experiment are fetched: " + experiments.inspect
411
+ experiments
381
412
  end
382
413
 
383
414
  def obtain_feature_flags(site_id, per_page = -1)
415
+ log "Fetching feature flags"
384
416
  query_values = { 'perPage' => per_page }
385
417
  filters = [
386
418
  hash_filter('siteId', 'EQUAL', [site_id]),
387
419
  hash_filter('status', 'EQUAL', ['ACTIVE'])
388
420
  ]
389
- fetch_all('feature-flags', query_values, filters).map { |it| JSON.parse(it.response) }.flatten.map do |ff|
421
+ feature_flags = fetch_all('feature-flags', query_values, filters).map { |it| JSON.parse(it.response) }.flatten.map do |ff|
390
422
  complete_experiment(ff)
391
423
  end
424
+ log "Feature flags are fetched: " + feature_flags.inspect
425
+ feature_flags
392
426
  end
393
427
 
394
428
  def fetch_all(path, query_values = {}, filters = [])
@@ -411,6 +445,7 @@ module Kameleoon
411
445
  end
412
446
  request = EM::Synchrony.sync get({ :path => path, :query => query_values, :head => hash_headers })
413
447
  unless is_successful(request)
448
+ log "Failed to fetch" + request.inspect
414
449
  return false
415
450
  end
416
451
  request
@@ -437,6 +472,10 @@ module Kameleoon
437
472
  url
438
473
  end
439
474
 
475
+ def get_data_register_url(visitor_code)
476
+ "/dataTracking?" + URI.encode_www_form(get_common_ssx_parameters(visitor_code))
477
+ end
478
+
440
479
  def get_feature_flag(feature_key)
441
480
  if feature_key.is_a?(String)
442
481
  feature_flag = @feature_flags.select { |ff| ff['identificationKey'] == feature_key}.first
@@ -446,24 +485,53 @@ module Kameleoon
446
485
  raise TypeError.new("Feature key should be a String or an Integer.")
447
486
  end
448
487
  if feature_flag.nil?
449
- raise Exception::FeatureFlagNotFound.new(feature_key)
488
+ raise Exception::FeatureConfigurationNotFound.new(feature_key)
450
489
  end
451
490
  feature_flag
452
491
  end
453
492
 
454
- def post_beacon(type = "dataTracking", visitor_code = nil, experiment_id = nil, variation_id = nil, none_variation = false)
493
+ def track_experiment(visitor_code, experiment_id, variation_id = nil, none_variation = false)
494
+ data_not_sent = data_not_sent(visitor_code)
495
+ options = {
496
+ :path => get_experiment_register_url(visitor_code, experiment_id, variation_id, none_variation),
497
+ :body => ((data_not_sent.values[0] || []).map{ |it| it.obtain_full_post_text_line }.join("\n") || "").encode("UTF-8"),
498
+ :head => { "Content-Type" => "text/plain"}
499
+ }
500
+ trial = 0
501
+ log "Start post tracking experiment: " + data_not_sent.inspect
502
+ Thread.new do
503
+ EM.synchrony do
504
+ while trial < 10
505
+ request = EM::Synchrony.sync post(options, @tracking_url)
506
+ log "Request " + request.inspect
507
+ if is_successful(request)
508
+ (data_not_sent.values[0] || []).each { |it| it.sent = true }
509
+ EM.stop
510
+ end
511
+ trial += 1
512
+ end
513
+ EM.stop
514
+ end
515
+ log "Post to experiment tracking is done after " + trial.to_s + " trials"
516
+ Thread.exit
517
+ end
518
+ end
519
+
520
+ def track_data(visitor_code = nil)
455
521
  Thread.new do
456
522
  EM.synchrony do
457
- entries = select_data_to_sent(visitor_code)
458
523
  trials = 10
459
524
  concurrency = 1
460
- while !entries.empty? && trials > 0
461
- EM::Synchrony::Iterator.new(entries, concurrency).map do |entry, iter|
525
+ data_not_sent = data_not_sent(visitor_code)
526
+ log "Start post tracking data: " + data_not_sent.inspect
527
+ while trials > 0 && !data_not_sent.empty?
528
+ EM::Synchrony::Iterator.new(data_not_sent, concurrency).map do |entry, iter|
462
529
  options = {
463
- :path => build_beacon_path(type, entry.first || visitor_code, experiment_id, variation_id, none_variation),
530
+ :path => get_data_register_url(entry.first),
464
531
  :body => (entry.last.map { |data| data.obtain_full_post_text_line }.join("\n") || "").encode("UTF-8"),
465
532
  :head => { "Content-Type" => "text/plain" }
466
533
  }
534
+ log "Post tracking data for visitor_code: " + entry.first + " with options: " + options.inspect
467
535
  request = post(options, @tracking_url)
468
536
  request.callback {
469
537
  if is_successful(request)
@@ -473,16 +541,17 @@ module Kameleoon
473
541
  }
474
542
  request.errback { iter.return(request) }
475
543
  end
476
- entries = select_data_to_sent(visitor_code)
544
+ data_not_sent = data_not_sent(visitor_code)
477
545
  trials -= 1
478
546
  end
547
+ log "Post to data tracking is done."
479
548
  EM.stop
480
549
  end
481
550
  Thread.exit
482
551
  end
483
552
  end
484
553
 
485
- def select_data_to_sent(visitor_code)
554
+ def data_not_sent(visitor_code = nil)
486
555
  if visitor_code.nil?
487
556
  @data.select {|key, values| values.any? {|data| !data.sent}}
488
557
  else
@@ -490,13 +559,9 @@ module Kameleoon
490
559
  end
491
560
  end
492
561
 
493
- def build_beacon_path(type, visitor_code, experiment_id = nil, variation_id = nil, none_variation = nil)
494
- if type == "dataTracking"
495
- return "/dataTracking?" + URI.encode_www_form(get_common_ssx_parameters(visitor_code))
496
- elsif type == "experimentTracking"
497
- return get_experiment_register_url(visitor_code, experiment_id, variation_id, none_variation)
498
- else
499
- raise TypeError("Unknown type for post_beacon: " + type.to_s)
562
+ def log(text)
563
+ if @verbose_mode
564
+ print "Kameleoon Log: " + text.to_s + "\n"
500
565
  end
501
566
  end
502
567
  end
@@ -15,16 +15,21 @@ module Kameleoon
15
15
  super("Variation " + id.to_s)
16
16
  end
17
17
  end
18
- class ExperimentNotFound < NotFound
18
+ class ExperimentConfigurationNotFound < NotFound
19
19
  def initialize(id = "")
20
20
  super("Experiment " + id.to_s)
21
21
  end
22
22
  end
23
- class FeatureFlagNotFound < NotFound
23
+ class FeatureConfigurationNotFound < NotFound
24
24
  def initialize(id = "")
25
25
  super("Feature flag " + id.to_s)
26
26
  end
27
27
  end
28
+ class FeatureVariableNotFound < NotFound
29
+ def initialize(key = "")
30
+ super("Feature variable " + key.to_s)
31
+ end
32
+ end
28
33
  class CredentialsNotFound < NotFound
29
34
  def initialize
30
35
  super("Credentials")
@@ -2,9 +2,9 @@ require 'kameleoon/client'
2
2
 
3
3
  module Kameleoon
4
4
  module ClientFactory
5
- CONFIGURATION_UPDATE_INTERVAL= "60m"
5
+ CONFIGURATION_UPDATE_INTERVAL = '60m'
6
6
  CONFIG_PATH = "/etc/kameleoon/client-ruby.yaml"
7
- DEFAULT_TIMEOUT = 2 #seconds
7
+ DEFAULT_TIMEOUT = 2000 #milli-seconds
8
8
 
9
9
  ##
10
10
  # Create a kameleoon client object, each call create a new client.
@@ -17,6 +17,8 @@ module Kameleoon
17
17
  #
18
18
  def self.create(site_code, blocking = false, config_path = CONFIG_PATH, client_id = nil, client_secret = nil)
19
19
  client = Client.new(site_code, config_path, blocking, CONFIGURATION_UPDATE_INTERVAL, DEFAULT_TIMEOUT, client_id, client_secret)
20
+ client.send(:log, "Warning: you are using the blocking mode") if blocking
21
+ client.send(:log, "Client created with site code: " + site_code.to_s)
20
22
  client.send(:fetch_configuration)
21
23
  client
22
24
  end
@@ -1,4 +1,5 @@
1
1
  require "em-synchrony/em-http"
2
+ require "kameleoon/version"
2
3
 
3
4
  module Kameleoon
4
5
  # @api private
@@ -22,7 +23,8 @@ module Kameleoon
22
23
  private
23
24
 
24
25
  def request(method, request_options, url, connexion_options)
25
- request_options[:tls] = {verify_peer: true}
26
+ connexion_options[:tls] = {verify_peer: false}
27
+ add_user_agent(request_options)
26
28
  case method
27
29
  when Method::POST then
28
30
  return EventMachine::HttpRequest.new(url, connexion_options).apost request_options
@@ -37,6 +39,14 @@ module Kameleoon
37
39
  def is_successful(request)
38
40
  !request.nil? && request != false && /20\d/.match(request.response_header.status.to_s)
39
41
  end
42
+
43
+ def add_user_agent(request_options)
44
+ if request_options[:head].nil?
45
+ request_options[:head] = {'Kameleoon-Client' => 'sdk/ruby/' + Kameleoon::VERSION}
46
+ else
47
+ request_options[:head].store('Kameleoon-Client', 'sdk/ruby/' + Kameleoon::VERSION)
48
+ end
49
+ end
40
50
  end
41
51
  end
42
52
 
@@ -0,0 +1,3 @@
1
+ module Kameleoon
2
+ VERSION = '1.0.5'
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kameleoon-client-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kameleoon - Guillaume Grandjean
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-14 00:00:00.000000000 Z
11
+ date: 2021-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -73,6 +73,7 @@ files:
73
73
  - lib/kameleoon/targeting/models.rb
74
74
  - lib/kameleoon/targeting/tree_builder.rb
75
75
  - lib/kameleoon/utils.rb
76
+ - lib/kameleoon/version.rb
76
77
  homepage: https://developers.kameleoon.com/ruby-sdk.html
77
78
  licenses:
78
79
  - GPL-3.0