optimizely-sdk 3.9.0 → 4.0.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +202 -202
  3. data/lib/optimizely/audience.rb +127 -97
  4. data/lib/optimizely/bucketer.rb +156 -156
  5. data/lib/optimizely/condition_tree_evaluator.rb +123 -123
  6. data/lib/optimizely/config/datafile_project_config.rb +539 -508
  7. data/lib/optimizely/config/proxy_config.rb +34 -34
  8. data/lib/optimizely/config_manager/async_scheduler.rb +95 -95
  9. data/lib/optimizely/config_manager/http_project_config_manager.rb +330 -321
  10. data/lib/optimizely/config_manager/project_config_manager.rb +24 -24
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +53 -47
  12. data/lib/optimizely/decide/optimizely_decide_option.rb +28 -28
  13. data/lib/optimizely/decide/optimizely_decision.rb +60 -60
  14. data/lib/optimizely/decide/optimizely_decision_message.rb +26 -26
  15. data/lib/optimizely/decision_service.rb +563 -500
  16. data/lib/optimizely/error_handler.rb +39 -39
  17. data/lib/optimizely/event/batch_event_processor.rb +235 -234
  18. data/lib/optimizely/event/entity/conversion_event.rb +44 -43
  19. data/lib/optimizely/event/entity/decision.rb +38 -38
  20. data/lib/optimizely/event/entity/event_batch.rb +86 -86
  21. data/lib/optimizely/event/entity/event_context.rb +50 -50
  22. data/lib/optimizely/event/entity/impression_event.rb +48 -47
  23. data/lib/optimizely/event/entity/snapshot.rb +33 -33
  24. data/lib/optimizely/event/entity/snapshot_event.rb +48 -48
  25. data/lib/optimizely/event/entity/user_event.rb +22 -22
  26. data/lib/optimizely/event/entity/visitor.rb +36 -35
  27. data/lib/optimizely/event/entity/visitor_attribute.rb +38 -37
  28. data/lib/optimizely/event/event_factory.rb +156 -155
  29. data/lib/optimizely/event/event_processor.rb +25 -25
  30. data/lib/optimizely/event/forwarding_event_processor.rb +44 -43
  31. data/lib/optimizely/event/user_event_factory.rb +88 -88
  32. data/lib/optimizely/event_builder.rb +221 -228
  33. data/lib/optimizely/event_dispatcher.rb +71 -71
  34. data/lib/optimizely/exceptions.rb +135 -139
  35. data/lib/optimizely/helpers/constants.rb +415 -397
  36. data/lib/optimizely/helpers/date_time_utils.rb +30 -30
  37. data/lib/optimizely/helpers/event_tag_utils.rb +132 -132
  38. data/lib/optimizely/helpers/group.rb +31 -31
  39. data/lib/optimizely/helpers/http_utils.rb +65 -64
  40. data/lib/optimizely/helpers/validator.rb +183 -183
  41. data/lib/optimizely/helpers/variable_type.rb +67 -67
  42. data/lib/optimizely/logger.rb +46 -45
  43. data/lib/optimizely/notification_center.rb +174 -176
  44. data/lib/optimizely/optimizely_config.rb +271 -272
  45. data/lib/optimizely/optimizely_factory.rb +181 -181
  46. data/lib/optimizely/optimizely_user_context.rb +204 -107
  47. data/lib/optimizely/params.rb +31 -31
  48. data/lib/optimizely/project_config.rb +99 -91
  49. data/lib/optimizely/semantic_version.rb +166 -166
  50. data/lib/optimizely/{custom_attribute_condition_evaluator.rb → user_condition_evaluator.rb} +391 -369
  51. data/lib/optimizely/user_profile_service.rb +35 -35
  52. data/lib/optimizely/version.rb +21 -21
  53. data/lib/optimizely.rb +1130 -1117
  54. metadata +13 -13
@@ -1,30 +1,30 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2019, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
- module Optimizely
19
- module Helpers
20
- module DateTimeUtils
21
- module_function
22
-
23
- def create_timestamp
24
- # Returns Integer current UTC timestamp
25
- utc = Time.now.getutc
26
- (utc.to_f * 1000).to_i
27
- end
28
- end
29
- end
30
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2019, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module Optimizely
19
+ module Helpers
20
+ module DateTimeUtils
21
+ module_function
22
+
23
+ def create_timestamp
24
+ # Returns Integer current UTC timestamp
25
+ utc = Time.now.getutc
26
+ (utc.to_f * 1000).to_i
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,132 +1,132 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2017-2018, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
- require 'optimizely/logger'
19
- require 'optimizely/helpers/validator'
20
-
21
- module Optimizely
22
- module Helpers
23
- module EventTagUtils
24
- module_function
25
-
26
- REVENUE_EVENT_METRIC_NAME = 'revenue'
27
- NUMERIC_EVENT_METRIC_NAME = 'value'
28
-
29
- def get_revenue_value(event_tags, logger)
30
- # Grab the revenue value from the event tags. "revenue" is a reserved keyword.
31
- # The value will be parsed to an integer if possible.
32
- # Example:
33
- # 4.0 or "4.0" will be parsed to int(4).
34
- # 4.1 will not be parsed and the method will return nil.
35
- # event_tags - Hash representing metadata associated with the event.
36
- # logger - Optional component which provides a log method to log messages.
37
- #
38
- # Returns revenue value as an integer number
39
- # Returns nil if revenue can't be retrieved from the event tags.
40
-
41
- if event_tags.nil?
42
- logger.log(Logger::DEBUG, 'Event tags is undefined.')
43
- return nil
44
- end
45
-
46
- unless Helpers::Validator.event_tags_valid?(event_tags)
47
- logger.log(Logger::DEBUG, 'Event tags is not a hash.')
48
- return nil
49
- end
50
-
51
- unless event_tags.key?(REVENUE_EVENT_METRIC_NAME)
52
- logger.log(Logger::DEBUG, 'The revenue key is not defined in the event tags.')
53
- return nil
54
- end
55
-
56
- if event_tags[REVENUE_EVENT_METRIC_NAME].nil?
57
- logger.log(Logger::DEBUG, 'The revenue key is nil.')
58
- return nil
59
- end
60
-
61
- raw_value = event_tags[REVENUE_EVENT_METRIC_NAME]
62
-
63
- unless Helpers::Validator.string_numeric?(raw_value)
64
- logger.log(Logger::WARN, 'Revenue value is not an integer or float, or is not a numeric string.')
65
- return nil
66
- end
67
-
68
- raw_value = raw_value.to_f if raw_value.is_a? String
69
-
70
- unless raw_value == raw_value.to_i
71
- logger.log(Logger::WARN, "Failed to parse revenue value #{raw_value} from event tags.")
72
- return nil
73
- end
74
-
75
- logger.log(Logger::INFO, "Parsed revenue value #{raw_value.to_i} from event tags.")
76
- raw_value.to_i
77
- end
78
-
79
- def get_numeric_value(event_tags, logger)
80
- # Grab the numeric event value from the event tags. "value" is a reserved keyword.
81
- # The value of 'value' can be a float or a numeric string
82
- #
83
- # event_tags - +Hash+ representing metadata associated with the event.
84
- # logger - Optional component which provides a log method to log messages.
85
- # Returns +Number+ | +nil+ if value can't be retrieved from the event tags.
86
-
87
- if event_tags.nil?
88
- logger.log(Logger::DEBUG, 'Event tags is undefined.')
89
- return nil
90
- end
91
-
92
- unless Helpers::Validator.event_tags_valid?(event_tags)
93
- logger.log(Logger::DEBUG, 'Event tags is not a dictionary.')
94
- return nil
95
- end
96
-
97
- unless event_tags.key?(NUMERIC_EVENT_METRIC_NAME)
98
- logger.log(Logger::DEBUG, 'The numeric metric key is not defined in the event tags.')
99
- return nil
100
- end
101
-
102
- if event_tags[NUMERIC_EVENT_METRIC_NAME].nil?
103
- logger.log(Logger::DEBUG, 'The numeric metric key is null.')
104
- return nil
105
- end
106
-
107
- raw_value = event_tags[NUMERIC_EVENT_METRIC_NAME]
108
-
109
- if raw_value.is_a?(TrueClass) || raw_value.is_a?(FalseClass)
110
- logger.log(Logger::DEBUG, 'Provided numeric value is a boolean, which is an invalid format.')
111
- return nil
112
- end
113
-
114
- if raw_value.is_a?(Array) || raw_value.is_a?(Hash) || raw_value.to_f.nan? || raw_value.to_f.infinite?
115
- logger.log(Logger::DEBUG, 'Provided numeric value is in an invalid format.')
116
- return nil
117
- end
118
-
119
- unless Helpers::Validator.string_numeric?(raw_value)
120
- logger.log(Logger::DEBUG, 'Provided numeric value is not a numeric string.')
121
- return nil
122
- end
123
-
124
- raw_value = raw_value.to_f
125
-
126
- logger.log(Logger::INFO, "The numeric metric value #{raw_value} will be sent to results.")
127
-
128
- raw_value
129
- end
130
- end
131
- end
132
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2017-2018, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ require 'optimizely/logger'
19
+ require 'optimizely/helpers/validator'
20
+
21
+ module Optimizely
22
+ module Helpers
23
+ module EventTagUtils
24
+ module_function
25
+
26
+ REVENUE_EVENT_METRIC_NAME = 'revenue'
27
+ NUMERIC_EVENT_METRIC_NAME = 'value'
28
+
29
+ def get_revenue_value(event_tags, logger)
30
+ # Grab the revenue value from the event tags. "revenue" is a reserved keyword.
31
+ # The value will be parsed to an integer if possible.
32
+ # Example:
33
+ # 4.0 or "4.0" will be parsed to int(4).
34
+ # 4.1 will not be parsed and the method will return nil.
35
+ # event_tags - Hash representing metadata associated with the event.
36
+ # logger - Optional component which provides a log method to log messages.
37
+ #
38
+ # Returns revenue value as an integer number
39
+ # Returns nil if revenue can't be retrieved from the event tags.
40
+
41
+ if event_tags.nil?
42
+ logger.log(Logger::DEBUG, 'Event tags is undefined.')
43
+ return nil
44
+ end
45
+
46
+ unless Helpers::Validator.event_tags_valid?(event_tags)
47
+ logger.log(Logger::DEBUG, 'Event tags is not a hash.')
48
+ return nil
49
+ end
50
+
51
+ unless event_tags.key?(REVENUE_EVENT_METRIC_NAME)
52
+ logger.log(Logger::DEBUG, 'The revenue key is not defined in the event tags.')
53
+ return nil
54
+ end
55
+
56
+ if event_tags[REVENUE_EVENT_METRIC_NAME].nil?
57
+ logger.log(Logger::DEBUG, 'The revenue key is nil.')
58
+ return nil
59
+ end
60
+
61
+ raw_value = event_tags[REVENUE_EVENT_METRIC_NAME]
62
+
63
+ unless Helpers::Validator.string_numeric?(raw_value)
64
+ logger.log(Logger::WARN, 'Revenue value is not an integer or float, or is not a numeric string.')
65
+ return nil
66
+ end
67
+
68
+ raw_value = raw_value.to_f if raw_value.is_a? String
69
+
70
+ unless raw_value == raw_value.to_i
71
+ logger.log(Logger::WARN, "Failed to parse revenue value #{raw_value} from event tags.")
72
+ return nil
73
+ end
74
+
75
+ logger.log(Logger::INFO, "Parsed revenue value #{raw_value.to_i} from event tags.")
76
+ raw_value.to_i
77
+ end
78
+
79
+ def get_numeric_value(event_tags, logger)
80
+ # Grab the numeric event value from the event tags. "value" is a reserved keyword.
81
+ # The value of 'value' can be a float or a numeric string
82
+ #
83
+ # event_tags - +Hash+ representing metadata associated with the event.
84
+ # logger - Optional component which provides a log method to log messages.
85
+ # Returns +Number+ | +nil+ if value can't be retrieved from the event tags.
86
+
87
+ if event_tags.nil?
88
+ logger.log(Logger::DEBUG, 'Event tags is undefined.')
89
+ return nil
90
+ end
91
+
92
+ unless Helpers::Validator.event_tags_valid?(event_tags)
93
+ logger.log(Logger::DEBUG, 'Event tags is not a dictionary.')
94
+ return nil
95
+ end
96
+
97
+ unless event_tags.key?(NUMERIC_EVENT_METRIC_NAME)
98
+ logger.log(Logger::DEBUG, 'The numeric metric key is not defined in the event tags.')
99
+ return nil
100
+ end
101
+
102
+ if event_tags[NUMERIC_EVENT_METRIC_NAME].nil?
103
+ logger.log(Logger::DEBUG, 'The numeric metric key is null.')
104
+ return nil
105
+ end
106
+
107
+ raw_value = event_tags[NUMERIC_EVENT_METRIC_NAME]
108
+
109
+ if raw_value.is_a?(TrueClass) || raw_value.is_a?(FalseClass)
110
+ logger.log(Logger::DEBUG, 'Provided numeric value is a boolean, which is an invalid format.')
111
+ return nil
112
+ end
113
+
114
+ if raw_value.is_a?(Array) || raw_value.is_a?(Hash) || raw_value.to_f.nan? || raw_value.to_f.infinite?
115
+ logger.log(Logger::DEBUG, 'Provided numeric value is in an invalid format.')
116
+ return nil
117
+ end
118
+
119
+ unless Helpers::Validator.string_numeric?(raw_value)
120
+ logger.log(Logger::DEBUG, 'Provided numeric value is not a numeric string.')
121
+ return nil
122
+ end
123
+
124
+ raw_value = raw_value.to_f
125
+
126
+ logger.log(Logger::INFO, "The numeric metric value #{raw_value} will be sent to results.")
127
+
128
+ raw_value
129
+ end
130
+ end
131
+ end
132
+ end
@@ -1,31 +1,31 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2017, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
- module Optimizely
19
- module Helpers
20
- module Group
21
- OVERLAPPING_POLICY = 'overlapping'
22
- RANDOM_POLICY = 'random'
23
-
24
- module_function
25
-
26
- def random_policy?(group)
27
- group['policy'] == RANDOM_POLICY
28
- end
29
- end
30
- end
31
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2017, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module Optimizely
19
+ module Helpers
20
+ module Group
21
+ OVERLAPPING_POLICY = 'overlapping'
22
+ RANDOM_POLICY = 'random'
23
+
24
+ module_function
25
+
26
+ def random_policy?(group)
27
+ group['policy'] == RANDOM_POLICY
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,64 +1,65 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2020, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'net/http'
20
-
21
- module Optimizely
22
- module Helpers
23
- module HttpUtils
24
- module_function
25
-
26
- def make_request(url, http_method, request_body = nil, headers = {}, read_timeout = nil, proxy_config = nil)
27
- # makes http/https GET/POST request and returns response
28
- #
29
- uri = URI.parse(url)
30
-
31
- if http_method == :get
32
- request = Net::HTTP::Get.new(uri.request_uri)
33
- elsif http_method == :post
34
- request = Net::HTTP::Post.new(uri.request_uri)
35
- request.body = request_body if request_body
36
- else
37
- return nil
38
- end
39
-
40
- # set headers
41
- headers&.each do |key, val|
42
- request[key] = val
43
- end
44
-
45
- # do not try to make request with proxy unless we have at least a host
46
- http_class = if proxy_config&.host
47
- Net::HTTP::Proxy(
48
- proxy_config.host,
49
- proxy_config.port,
50
- proxy_config.username,
51
- proxy_config.password
52
- )
53
- else
54
- Net::HTTP
55
- end
56
-
57
- http = http_class.new(uri.host, uri.port)
58
- http.read_timeout = read_timeout if read_timeout
59
- http.use_ssl = uri.scheme == 'https'
60
- http.request(request)
61
- end
62
- end
63
- end
64
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2020, 2022, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'net/http'
20
+
21
+ module Optimizely
22
+ module Helpers
23
+ module HttpUtils
24
+ module_function
25
+
26
+ def make_request(url, http_method, request_body = nil, headers = {}, read_timeout = nil, proxy_config = nil) # rubocop:disable Metrics/ParameterLists
27
+ # makes http/https GET/POST request and returns response
28
+ #
29
+ uri = URI.parse(url)
30
+
31
+ case http_method
32
+ when :get
33
+ request = Net::HTTP::Get.new(uri.request_uri)
34
+ when :post
35
+ request = Net::HTTP::Post.new(uri.request_uri)
36
+ request.body = request_body if request_body
37
+ else
38
+ return nil
39
+ end
40
+
41
+ # set headers
42
+ headers&.each do |key, val|
43
+ request[key] = val
44
+ end
45
+
46
+ # do not try to make request with proxy unless we have at least a host
47
+ http_class = if proxy_config&.host
48
+ Net::HTTP::Proxy(
49
+ proxy_config.host,
50
+ proxy_config.port,
51
+ proxy_config.username,
52
+ proxy_config.password
53
+ )
54
+ else
55
+ Net::HTTP
56
+ end
57
+
58
+ http = http_class.new(uri.host, uri.port)
59
+ http.read_timeout = read_timeout if read_timeout
60
+ http.use_ssl = uri.scheme == 'https'
61
+ http.request(request)
62
+ end
63
+ end
64
+ end
65
+ end