kameleoon-client-ruby 3.3.0 → 3.5.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kameleoon/configuration/custom_data_info.rb +16 -8
  3. data/lib/kameleoon/configuration/data_file.rb +52 -16
  4. data/lib/kameleoon/configuration/feature_flag.rb +11 -1
  5. data/lib/kameleoon/configuration/rule.rb +4 -0
  6. data/lib/kameleoon/configuration/settings.rb +13 -8
  7. data/lib/kameleoon/configuration/variation_exposition.rb +4 -0
  8. data/lib/kameleoon/data/browser.rb +4 -0
  9. data/lib/kameleoon/data/conversion.rb +4 -0
  10. data/lib/kameleoon/data/cookie.rb +4 -0
  11. data/lib/kameleoon/data/custom_data.rb +11 -3
  12. data/lib/kameleoon/data/data.rb +30 -4
  13. data/lib/kameleoon/data/device.rb +4 -0
  14. data/lib/kameleoon/data/geolocation.rb +5 -0
  15. data/lib/kameleoon/data/kcs_heat.rb +4 -0
  16. data/lib/kameleoon/data/manager/assigned_variation.rb +8 -1
  17. data/lib/kameleoon/data/manager/data_array_storage.rb +7 -0
  18. data/lib/kameleoon/data/manager/data_map_storage.rb +7 -0
  19. data/lib/kameleoon/data/manager/page_view_visit.rb +4 -0
  20. data/lib/kameleoon/data/manager/visitor.rb +197 -73
  21. data/lib/kameleoon/data/manager/visitor_manager.rb +54 -17
  22. data/lib/kameleoon/data/mapping_identifier.rb +33 -0
  23. data/lib/kameleoon/data/operating_system.rb +4 -0
  24. data/lib/kameleoon/data/page_view.rb +6 -1
  25. data/lib/kameleoon/data/unique_identifier.rb +11 -0
  26. data/lib/kameleoon/data/user_agent.rb +4 -0
  27. data/lib/kameleoon/data/visitor_visits.rb +4 -0
  28. data/lib/kameleoon/hybrid/manager.rb +19 -7
  29. data/lib/kameleoon/kameleoon_client.rb +477 -178
  30. data/lib/kameleoon/kameleoon_client_config.rb +65 -18
  31. data/lib/kameleoon/kameleoon_client_factory.rb +15 -2
  32. data/lib/kameleoon/logging/default_logger.rb +20 -0
  33. data/lib/kameleoon/logging/kameleoon_logger.rb +77 -0
  34. data/lib/kameleoon/logging/logger.rb +12 -0
  35. data/lib/kameleoon/managers/data/data_manager.rb +36 -0
  36. data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +32 -15
  37. data/lib/kameleoon/managers/tracking/tracking_builder.rb +149 -0
  38. data/lib/kameleoon/managers/tracking/tracking_manager.rb +98 -0
  39. data/lib/kameleoon/managers/tracking/visitor_tracking_registry.rb +94 -0
  40. data/lib/kameleoon/managers/warehouse/warehouse_manager.rb +22 -5
  41. data/lib/kameleoon/network/access_token_source.rb +46 -14
  42. data/lib/kameleoon/network/cookie/cookie_manager.rb +46 -7
  43. data/lib/kameleoon/network/net_provider.rb +2 -3
  44. data/lib/kameleoon/network/network_manager.rb +17 -21
  45. data/lib/kameleoon/network/request.rb +14 -3
  46. data/lib/kameleoon/network/response.rb +4 -0
  47. data/lib/kameleoon/network/url_provider.rb +3 -3
  48. data/lib/kameleoon/real_time/real_time_configuration_service.rb +10 -11
  49. data/lib/kameleoon/sdk_version.rb +31 -0
  50. data/lib/kameleoon/targeting/condition.rb +4 -2
  51. data/lib/kameleoon/targeting/conditions/browser_condition.rb +3 -3
  52. data/lib/kameleoon/targeting/conditions/cookie_condition.rb +10 -10
  53. data/lib/kameleoon/targeting/conditions/geolocation_condition.rb +0 -1
  54. data/lib/kameleoon/targeting/conditions/number_condition.rb +4 -4
  55. data/lib/kameleoon/targeting/conditions/operating_system_condition.rb +1 -2
  56. data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +2 -1
  57. data/lib/kameleoon/targeting/conditions/segment_condition.rb +3 -3
  58. data/lib/kameleoon/targeting/conditions/string_value_condition.rb +2 -1
  59. data/lib/kameleoon/targeting/models.rb +0 -14
  60. data/lib/kameleoon/targeting/targeting_manager.rb +35 -7
  61. data/lib/kameleoon/targeting/tree_builder.rb +10 -5
  62. data/lib/kameleoon/types/remote_visitor_data_filter.rb +13 -0
  63. data/lib/kameleoon/types/variable.rb +4 -0
  64. data/lib/kameleoon/types/variation.rb +8 -0
  65. data/lib/kameleoon/utils.rb +49 -0
  66. data/lib/kameleoon/version.rb +1 -27
  67. metadata +12 -2
@@ -37,13 +37,13 @@ module Kameleoon
37
37
  @data_api_domain = domain if domain.is_a?(String)
38
38
  end
39
39
 
40
- def make_tracking_url(visitor_code, is_unique_identifier = false)
40
+ def make_tracking_url
41
41
  params = {
42
42
  sdkName: SDK_NAME,
43
43
  sdkVersion: SDK_VERSION,
44
- siteCode: @site_code
44
+ siteCode: @site_code,
45
+ bodyUa: true
45
46
  }
46
- params[is_unique_identifier ? :mappingValue : :visitorCode] = visitor_code
47
47
  "https://#{@data_api_domain}#{TRACKING_PATH}?#{UriHelper.encode_query(params)}"
48
48
  end
49
49
 
@@ -3,6 +3,7 @@
3
3
  # Kameleoon Real Time Configuration Service
4
4
 
5
5
  require 'json'
6
+ require 'kameleoon/logging/kameleoon_logger'
6
7
  require 'kameleoon/real_time/real_time_event'
7
8
  require 'kameleoon/real_time/sse_request'
8
9
  require 'kameleoon/real_time/sse_client'
@@ -21,8 +22,7 @@ module Kameleoon
21
22
  # @param url [String]
22
23
  # @param update_handler [Callable[Kameleoon::RealTime::RealTimeEvent] | NilClass] Handler which
23
24
  # is synchronously called for gotten RealTimeEvent objects.
24
- # @param log_func [Callable[String] | NilClass] Callable object which synchronously called to log.
25
- def initialize(url, update_handler, log_func, sse_request_source = nil)
25
+ def initialize(url, update_handler, sse_request_source = nil)
26
26
  @url = url
27
27
  @update_handler = update_handler
28
28
  @need_close = false
@@ -31,7 +31,6 @@ module Kameleoon
31
31
  'Cache-Control': 'no-cache',
32
32
  'Connection': 'Keep-Alive'
33
33
  }
34
- @log_func = log_func
35
34
  @sse_request_source = sse_request_source
36
35
  @sse_thread = nil
37
36
  @sse_client = nil
@@ -43,13 +42,13 @@ module Kameleoon
43
42
  def close
44
43
  return if @need_close
45
44
 
46
- @log_func&.call('Real-time configuration service is shutting down')
45
+ Logging::KameleoonLogger.info('Real-time configuration service is shutting down')
47
46
  @need_close = true
48
47
  return if @sse_thread.nil?
49
48
 
50
49
  @sse_thread.kill
51
50
  @sse_thread = nil
52
- @sse_client.call_close_handler
51
+ @sse_client&.call_close_handler
53
52
  end
54
53
 
55
54
  private
@@ -60,7 +59,7 @@ module Kameleoon
60
59
 
61
60
  def init_sse_client
62
61
  message_handler = proc do |message|
63
- @log_func&.call("Got SSE event: #{message.event}")
62
+ Logging::KameleoonLogger.debug("Got SSE event: #{message.event}")
64
63
  if message.event == CONFIGURATION_UPDATE_EVENT
65
64
  event_dict = JSON.parse(message.data)
66
65
  @update_handler&.call(RealTimeEvent.new(event_dict))
@@ -68,14 +67,14 @@ module Kameleoon
68
67
  end
69
68
  sse_request = make_sse_request
70
69
  @sse_client = SseClient.new(sse_request, message_handler)
71
- @log_func&.call('Created SSE client')
70
+ Logging::KameleoonLogger.info('Created SSE client')
72
71
  end
73
72
 
74
73
  def make_sse_request
75
- open_handler = proc { @log_func&.call('SSE connection open') }
76
- close_handler = proc { @log_func&.call('SSE connection closed') }
74
+ open_handler = proc { Logging::KameleoonLogger.info('SSE connection open') }
75
+ close_handler = proc { Logging::KameleoonLogger.info('SSE connection closed') }
77
76
  unexpected_status_code_handler =
78
- proc { |resp| @log_func&.call("Unexpected status code of SSE response: #{resp.code}") }
77
+ proc { |resp| Logging::KameleoonLogger.error("Unexpected status code of SSE response: #{resp.code}") }
79
78
  if @sse_request_source.nil?
80
79
  return SseRequest.new(@url, @headers, open_handler, close_handler, unexpected_status_code_handler)
81
80
  end
@@ -89,7 +88,7 @@ module Kameleoon
89
88
  begin
90
89
  @sse_client.start
91
90
  rescue StandardError => e
92
- @log_func&.call("Error occurred within SSE client: #{e}")
91
+ Logging::KameleoonLogger.error("Error occurred within SSE client: #{e}")
93
92
  end
94
93
  end
95
94
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/logging/kameleoon_logger'
4
+
5
+ module Kameleoon
6
+ # SdkManager is a helper method for fetching / obtaining version of SDK from string
7
+ class SdkVersion
8
+ def self.get_version_components(version_string)
9
+ versions = [0, 0, 0]
10
+
11
+ version_parts = version_string.split('.')
12
+ version_parts.each_with_index do |part, i|
13
+ versions[i] = Integer(part)
14
+ rescue ArgumentError
15
+ Logging::KameleoonLogger.error('Invalid version component, index: %s, value: %s', i, part)
16
+ return nil
17
+ end
18
+ versions
19
+ end
20
+
21
+ def self.get_float_version(version_string)
22
+ version_components = get_version_components(version_string)
23
+
24
+ return Float::NAN if version_components.nil?
25
+
26
+ major = version_components[0]
27
+ minor = version_components[1]
28
+ "#{major}.#{minor}".to_f
29
+ end
30
+ end
31
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/exceptions'
4
+ require 'kameleoon/logging/kameleoon_logger'
4
5
 
5
6
  module Kameleoon
6
7
  # @api private
@@ -47,12 +48,13 @@ module Kameleoon
47
48
 
48
49
  # Base class for all targeting conditions
49
50
  class Condition
50
- attr_reader :type, :include
51
+ attr_reader :type, :include, :id
51
52
 
52
53
  def initialize(json_condition)
53
54
  raise Exception::NotFound.new('targetingType'), 'targetingType missed' if json_condition['targetingType'].nil?
54
55
 
55
56
  @type = json_condition['targetingType']
57
+ @id = json_condition['id']
56
58
  @include = json_condition['isInclude'].nil? ? true : json_condition['isInclude']
57
59
  end
58
60
 
@@ -70,7 +72,7 @@ module Kameleoon
70
72
  begin
71
73
  return pattern.match? value
72
74
  rescue StandardError => e
73
- log "Failed to match with regex (targeting): #{e}"
75
+ Logging::KameleoonLogger.error("Failed to match with regex (targeting): #{e}")
74
76
  end
75
77
  false
76
78
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/data/browser'
4
- require 'kameleoon/version'
4
+ require 'kameleoon/logging/kameleoon_logger'
5
+ require 'kameleoon/sdk_version'
5
6
 
6
7
  module Kameleoon
7
8
  # @api private
8
9
  module Targeting
9
-
10
10
  CHROME = 'CHROME'
11
11
  INTERNET_EXPLORER = 'IE'
12
12
  FIREFOX = 'FIREFOX'
@@ -44,7 +44,7 @@ module Kameleoon
44
44
  when Operator::LOWER
45
45
  browser.version < version_number
46
46
  else
47
- puts "Unexpected comparing operation for Browser condition: #{@version_match_type}"
47
+ Logging::KameleoonLogger.error("Unexpected comparing operation for 'Browser' condition: '#{@version_match_type}'")
48
48
  false
49
49
  end
50
50
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/data/cookie'
4
+ require 'kameleoon/logging/kameleoon_logger'
4
5
  require 'kameleoon/version'
5
6
 
6
7
  module Kameleoon
7
8
  # @api private
8
9
  module Targeting
9
-
10
10
  class CookieCondition < Condition
11
11
  def initialize(json_condition)
12
12
  super(json_condition)
@@ -26,13 +26,13 @@ module Kameleoon
26
26
  case @name_match_type
27
27
  when Kameleoon::Targeting::Operator::EXACT
28
28
  value = cookie.cookies[@condition_name]
29
- return value != nil ? [value] : []
29
+ return !value.nil? ? [value] : []
30
30
  when Kameleoon::Targeting::Operator::CONTAINS
31
- return cookie.cookies.select{|key| key.include? @condition_name}.values()
31
+ return cookie.cookies.select { |key| key.include? @condition_name }.values
32
32
  when Kameleoon::Targeting::Operator::REGULAR_EXPRESSION
33
- return cookie.cookies.select{|key| is_regex_match(@condition_name, key)}.values()
33
+ return cookie.cookies.select { |key| is_regex_match(@condition_name, key) }.values
34
34
  else
35
- log "Unexpected comparing operation for Cookie condition (name): #{@name_match_type}"
35
+ Logging::KameleoonLogger.error("Unexpected comparing operation for 'Cookie' condition (name): '#{@name_match_type}'")
36
36
  end
37
37
  []
38
38
  end
@@ -40,14 +40,14 @@ module Kameleoon
40
40
  def check_values(values)
41
41
  case @value_match_type
42
42
  when Kameleoon::Targeting::Operator::EXACT
43
- return values.any? {|value| value == @condition_value}
43
+ values.any? { |value| value == @condition_value }
44
44
  when Kameleoon::Targeting::Operator::CONTAINS
45
- return values.any? {|value| value.include? @condition_value}
45
+ values.any? { |value| value.include? @condition_value }
46
46
  when Kameleoon::Targeting::Operator::REGULAR_EXPRESSION
47
- return values.any? {|value| is_regex_match(@condition_value, value)}
47
+ values.any? { |value| is_regex_match(@condition_value, value) }
48
48
  else
49
- log "Unexpected comparing operation for Cookie condition (name): #{@name_match_type}"
50
- return false
49
+ Logging::KameleoonLogger.error("Unexpected comparing operation for 'Cookie' condition (name): '#{@name_match_type}'")
50
+ false
51
51
  end
52
52
  end
53
53
  end
@@ -6,7 +6,6 @@ require 'kameleoon/version'
6
6
  module Kameleoon
7
7
  # @api private
8
8
  module Targeting
9
-
10
9
  class GeolocationCondition < Condition
11
10
  def initialize(json_condition)
12
11
  super(json_condition)
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/data/cookie'
4
+ require 'kameleoon/logging/kameleoon_logger'
4
5
  require 'kameleoon/version'
5
6
 
6
7
  module Kameleoon
7
8
  # @api private
8
9
  module Targeting
9
-
10
10
  class NumberCondition < Condition
11
11
  def initialize(json_condition, value)
12
12
  super(json_condition)
@@ -25,11 +25,11 @@ module Kameleoon
25
25
  when Kameleoon::Targeting::Operator::EQUAL
26
26
  return value == @condition_value
27
27
  when Kameleoon::Targeting::Operator::GREATER
28
- return @condition_value != nil && value > @condition_value
28
+ return !@condition_value.nil? && value > @condition_value
29
29
  when Kameleoon::Targeting::Operator::LOWER
30
- return @condition_value != nil && value < @condition_value
30
+ return !@condition_value.nil? && value < @condition_value
31
31
  else
32
- log "Unexpected comparing operation for #{type} condition: #{@match_type}"
32
+ Logging::KameleoonLogger.error("Unexpected comparing operation for '#{@type}' condition: '#{@match_type}'")
33
33
  end
34
34
  false
35
35
  end
@@ -6,7 +6,6 @@ require 'kameleoon/version'
6
6
  module Kameleoon
7
7
  # @api private
8
8
  module Targeting
9
-
10
9
  class OperatingSystemCondition < Condition
11
10
  def initialize(json_condition)
12
11
  super(json_condition)
@@ -20,7 +19,7 @@ module Kameleoon
20
19
  private
21
20
 
22
21
  def check_targeting(operating_system)
23
- @os_type != nil && operating_system.os_type == @os_type
22
+ !@os_type.nil? && operating_system.os_type == @os_type
24
23
  end
25
24
  end
26
25
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/data/data'
4
+ require 'kameleoon/logging/kameleoon_logger'
4
5
  require 'kameleoon/version'
5
6
 
6
7
  module Kameleoon
@@ -56,7 +57,7 @@ module Kameleoon
56
57
  (major_sdk == major_condition && minor_sdk < minor_condition) ||
57
58
  (major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk < patch_condition)
58
59
  else
59
- puts "Unexpected comparing operation for SdkLanguage condition: #{@operator}"
60
+ Logging::KameleoonLogger.error("Unexpected comparing operation for 'SdkLanguage' condition: '#{@operator}'")
60
61
  false
61
62
  end
62
63
  end
@@ -6,11 +6,10 @@ require 'kameleoon/version'
6
6
  module Kameleoon
7
7
  # @api private
8
8
  module Targeting
9
-
10
9
  class SegmentCondition < Condition
11
10
  def initialize(json_condition)
12
11
  super(json_condition)
13
- @segment_id = json_condition["segmentId"]
12
+ @segment_id = json_condition['segmentId']
14
13
  end
15
14
 
16
15
  def check(data)
@@ -22,7 +21,8 @@ module Kameleoon
22
21
  def check_targeting(segment_info)
23
22
  rule = segment_info.data_file.rule_by_segment_id[@segment_id]
24
23
  return false unless rule.is_a?(Kameleoon::Configuration::Rule)
25
- rule.targeting_segment.check_tree(->(type) {segment_info.condition_data(type)})
24
+
25
+ rule.targeting_segment.check_tree(->(type) { segment_info.condition_data(type) })
26
26
  end
27
27
  end
28
28
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'kameleoon/logging/kameleoon_logger'
3
4
  require 'kameleoon/targeting/condition'
4
5
 
5
6
  module Kameleoon
@@ -33,7 +34,7 @@ module Kameleoon
33
34
  pattern = Regexp.new(@condition_value)
34
35
  pattern.match?(value)
35
36
  else
36
- puts "Unexpected comparing operation for #{@type} condition: #{@operator}"
37
+ Logging::KameleoonLogger.error("Unexpected comparing operation for '#{@type}' condition: '#{@operator}'")
37
38
  false
38
39
  end
39
40
  end
@@ -10,7 +10,6 @@ module Kameleoon
10
10
  include TreeBuilder
11
11
  attr_accessor :id, :tree
12
12
  def to_s
13
- print("\nSegment id: #{@id}\n")
14
13
  @tree.to_s
15
14
  end
16
15
 
@@ -49,19 +48,6 @@ module Kameleoon
49
48
  class Tree
50
49
  attr_accessor :or_operator, :left_child, :right_child, :condition
51
50
 
52
- def to_s
53
- print("or_operator: #{@or_operator}\n")
54
- print("condition: #{@condition}")
55
- unless @left_child.nil?
56
- print('\nLeft child:\n ')
57
- @left_child.to_s
58
- end
59
- unless @right_child.nil?
60
- print('\nright child:\n ')
61
- @right_child.to_s
62
- end
63
- end
64
-
65
51
  def initialize(or_operator = nil, left_child = nil, right_child = nil, condition = nil)
66
52
  @or_operator = Marshal.load(Marshal.dump(or_operator))
67
53
  @left_child = left_child
@@ -1,25 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'kameleoon/logging/kameleoon_logger'
3
4
  require 'kameleoon/targeting/conditions/segment_condition'
4
5
 
5
6
  module Kameleoon
6
7
  # @api private
7
8
  module Targeting
8
9
  class TargetingManager
9
- def initialize(visitor_manager, data_file)
10
+ def initialize(data_manager, visitor_manager)
11
+ @data_manager = data_manager
10
12
  @visitor_manager = visitor_manager
11
- @data_file = data_file
12
13
  end
13
14
 
14
15
  def check_targeting(visitor_code, campaign_id, exp_ff_rule)
16
+ Logging::KameleoonLogger.debug(
17
+ "CALL: TargetingManager.check_targeting(visitorCode: '%s', campaignId: %s, exp_ff_rule: %s)",
18
+ visitor_code, campaign_id, exp_ff_rule
19
+ )
15
20
  segment = exp_ff_rule.targeting_segment
16
- return true if segment.nil?
21
+ if segment.nil?
22
+ Logging::KameleoonLogger.debug(
23
+ "RETURN: TargetingManager.check_targeting(visitorCode: '%s', campaignId: %s, exp_ff_rule: %s) -> " \
24
+ '(targeting: true)', visitor_code, campaign_id, exp_ff_rule
25
+ )
26
+ return true
27
+ end
17
28
 
18
29
  visitor = @visitor_manager.get_visitor(visitor_code)
19
- segment.check_tree(->(type) { get_condition_data(type, visitor, visitor_code, campaign_id) })
30
+ targeting = segment.check_tree(->(type) { get_condition_data(type, visitor, visitor_code, campaign_id) })
31
+ Logging::KameleoonLogger.debug(
32
+ "RETURN: TargetingManager.check_targeting(visitorCode: '%s', campaignId: %s, exp_ff_rule: %s) -> " \
33
+ '(targeting: %s)', visitor_code, campaign_id, exp_ff_rule, targeting
34
+ )
35
+ targeting
20
36
  end
21
37
 
22
38
  def get_condition_data(type, visitor, visitor_code, campaign_id)
39
+ Logging::KameleoonLogger.debug(
40
+ "CALL: TargetingManager.get_condition_data(type: %s, visitor, visitorCode: '%s', campaignId: %s)",
41
+ type, visitor_code, campaign_id
42
+ )
23
43
  condition_data = nil
24
44
  case type
25
45
  when Kameleoon::Targeting::ConditionType::CUSTOM_DATUM
@@ -41,7 +61,7 @@ module Kameleoon
41
61
  condition_data = visitor.operating_system unless visitor.nil?
42
62
  when Kameleoon::Targeting::ConditionType::SEGMENT
43
63
  condition_data = SegmentInfo.new(
44
- @data_file,
64
+ @data_manager.data_file,
45
65
  lambda { |type|
46
66
  get_condition_data(type, visitor, visitor_code, campaign_id)
47
67
  }
@@ -53,14 +73,22 @@ module Kameleoon
53
73
  when Kameleoon::Targeting::ConditionType::VISITOR_CODE
54
74
  condition_data = visitor_code
55
75
  when Kameleoon::Targeting::ConditionType::TARGET_FEATURE_FLAG
56
- condition_data = TargetFeatureFlagInfo.new(@data_file, visitor.variations) unless visitor.nil?
76
+ condition_data = TargetFeatureFlagInfo.new(@data_manager.data_file, visitor.variations) unless visitor.nil?
57
77
  when Kameleoon::Targeting::ConditionType::EXCLUSIVE_FEATURE_FLAG
58
78
  condition_data = ExclusiveFeatureFlagInfo.new(campaign_id, visitor&.variations)
59
- when ConditionType::FIRST_VISIT, ConditionType::LAST_VISIT, ConditionType::VISITS, ConditionType::SAME_DAY_VISITS, ConditionType::NEW_VISITORS
79
+ when ConditionType::FIRST_VISIT,
80
+ ConditionType::LAST_VISIT,
81
+ ConditionType::VISITS,
82
+ ConditionType::SAME_DAY_VISITS,
83
+ ConditionType::NEW_VISITORS
60
84
  condition_data = visitor.visitor_visits unless visitor.nil?
61
85
  when Kameleoon::Targeting::ConditionType::HEAT_SLICE
62
86
  condition_data = visitor&.kcs_heat
63
87
  end
88
+ Logging::KameleoonLogger.debug(
89
+ "RETURN: TargetingManager.get_condition_data(type: %s, visitor, visitor_code: '%s', campaign_id: %s) -> " \
90
+ '(condition_data: %s)', type, visitor_code, campaign_id, condition_data
91
+ )
64
92
  condition_data
65
93
  end
66
94
  end
@@ -1,4 +1,5 @@
1
1
  require 'kameleoon/targeting/condition_factory'
2
+ require 'kameleoon/logging/kameleoon_logger'
2
3
 
3
4
  module Kameleoon
4
5
  #@api private
@@ -6,13 +7,17 @@ module Kameleoon
6
7
  module TreeBuilder
7
8
 
8
9
  def create_tree(conditions_data_json)
9
- if conditions_data_json.nil?
10
- return nil
11
- end
10
+ return nil if conditions_data_json.nil?
11
+
12
+ Logging::KameleoonLogger.debug('CALL: TreeBuilder.create_tree(conditions_data_json: %s)',
13
+ conditions_data_json)
12
14
  if conditions_data_json['firstLevel'].empty?
13
15
  conditions_data_json['firstLevelOrOperators'] = []
14
16
  end
15
- create_first_level(conditions_data_json)
17
+ tree = create_first_level(conditions_data_json)
18
+ Logging::KameleoonLogger.debug('RETURN: TreeBuilder.create_tree(conditions_data_json: %s) -> (tree)',
19
+ conditions_data_json)
20
+ tree
16
21
  end
17
22
 
18
23
  private
@@ -69,4 +74,4 @@ module Kameleoon
69
74
  end
70
75
  end
71
76
  end
72
- end
77
+ end
@@ -7,6 +7,19 @@ module Kameleoon
7
7
  attr_reader :previous_visit_amount, :current_visit, :custom_data, :page_views, :geolocation, :device, :browser,
8
8
  :operating_system, :conversions, :experiments, :kcs
9
9
 
10
+ def to_s
11
+ "RemoteVisitorDataFilter{previous_visit_amount:#{@previous_visit_amount}," \
12
+ "current_visit:#{@current_visit}," \
13
+ "custom_data:#{@custom_data}," \
14
+ "page_views:#{@page_views}," \
15
+ "geolocation:#{@geolocation}," \
16
+ "device:#{@device}," \
17
+ "browser:#{@browser}," \
18
+ "operating_system:#{@operating_system}," \
19
+ "conversions:#{@conversions}," \
20
+ "experiments:#{@experiments},kcs:#{@kcs}}"
21
+ end
22
+
10
23
  def initialize(
11
24
  previous_visit_amount: 1, current_visit: true, custom_data: true, page_views: false,
12
25
  geolocation: false, device: false, browser: false, operating_system: false, conversions: false,
@@ -7,6 +7,10 @@ module Kameleoon
7
7
  class Variable
8
8
  attr_reader :key, :type, :value
9
9
 
10
+ def to_s
11
+ "Variable{key:'#{@key}',type:'#{@type}',value:#{@value}}"
12
+ end
13
+
10
14
  def initialize(key, type, value)
11
15
  @key = key
12
16
  @type = type
@@ -7,12 +7,20 @@ module Kameleoon
7
7
  class Variation
8
8
  attr_reader :key, :id, :experiment_id, :variables
9
9
 
10
+ def to_s
11
+ "Variation{key:'#{@key}',id:#{@id},experiment_id:#{@experiment_id},variables:#{@variables}}"
12
+ end
13
+
10
14
  def initialize(key, id, experiment_id, variables)
11
15
  @key = key
12
16
  @id = id
13
17
  @experiment_id = experiment_id
14
18
  @variables = variables
15
19
  end
20
+
21
+ def active?
22
+ variation_key != Configuration::VariationType::VARIATION_OFF
23
+ end
16
24
  end
17
25
  end
18
26
  end
@@ -4,6 +4,7 @@ require 'fiber'
4
4
  require 'bigdecimal'
5
5
  require 'kameleoon/utils'
6
6
  require 'kameleoon/exceptions'
7
+ require 'kameleoon/logging/kameleoon_logger'
7
8
 
8
9
  module Kameleoon
9
10
  # Utils is a helper module for project
@@ -50,5 +51,53 @@ module Kameleoon
50
51
  (Digest::SHA256.hexdigest(identifier.encode('UTF-8')).to_i(16) / (BigDecimal('2')**BigDecimal('256'))).round(16)
51
52
  end
52
53
  end
54
+
55
+ module Strval
56
+
57
+ def self.secret(secret)
58
+ hid_ch = '*'
59
+ vis_count = 4
60
+
61
+ return 'nil' if secret.nil?
62
+
63
+ length = secret.length
64
+
65
+ return hid_ch * length if length <= vis_count
66
+
67
+ hidden_length = [length - vis_count, vis_count].max
68
+
69
+ secret[0, length - hidden_length] + hid_ch * hidden_length
70
+ end
71
+ end
72
+
73
+ module Domain
74
+ HTTP = 'http://'
75
+ HTTPS = 'https://'
76
+ REGEX_DOMAIN = /^(\.?(([a-zA-Z\d][a-zA-Z\d-]*[a-zA-Z\d])|[a-zA-Z\d]))
77
+ (\.(([a-zA-Z\d][a-zA-Z\d-]*[a-zA-Z\d])|[a-zA-Z\d])){1,126}$/x.freeze
78
+
79
+ def self.validate_top_level_domain(top_level_domain)
80
+ return nil if top_level_domain.nil? || top_level_domain.empty?
81
+
82
+ top_level_domain = top_level_domain.downcase
83
+
84
+ [HTTP, HTTPS].each do |protocol|
85
+ next unless top_level_domain.start_with?(protocol)
86
+
87
+ top_level_domain = top_level_domain[protocol.length..]
88
+ Logging::KameleoonLogger.warning(
89
+ "The top-level domain contains '%s'. Domain after protocol trimming: '%s'", protocol, top_level_domain
90
+ )
91
+ break
92
+ end
93
+
94
+ unless REGEX_DOMAIN.match?(top_level_domain)
95
+ Logging::KameleoonLogger.error("The top-level domain '%s' is invalid.", top_level_domain)
96
+ return nil
97
+ end
98
+
99
+ top_level_domain
100
+ end
101
+ end
53
102
  end
54
103
  end
@@ -1,32 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kameleoon
4
+ SDK_VERSION = '3.5.0'
4
5
  SDK_NAME = 'RUBY'
5
- SDK_VERSION = '3.3.0'
6
-
7
- # SdkManager is a helper method for fetching / obtaining version of SDK from string
8
- class SdkVersion
9
- def self.get_version_components(version_string)
10
- versions = [0, 0, 0]
11
-
12
- version_parts = version_string.split('.')
13
- version_parts.each_with_index do |part, i|
14
- versions[i] = Integer(part)
15
- rescue ArgumentError
16
- puts "Invalid version component, index: #{i}, value: #{part}"
17
- return nil
18
- end
19
- versions
20
- end
21
-
22
- def self.get_float_version(version_string)
23
- version_components = get_version_components(version_string)
24
-
25
- return Float::NAN if version_components.nil?
26
-
27
- major = version_components[0]
28
- minor = version_components[1]
29
- "#{major}.#{minor}".to_f
30
- end
31
- end
32
6
  end