kameleoon-client-ruby 1.0.0 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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