vwo-ruby-sdk 1.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.
- checksums.yaml +7 -0
- data/lib/vwo/bucketing_service.rb +158 -0
- data/lib/vwo/common/campaign_utils.rb +111 -0
- data/lib/vwo/common/constants.rb +50 -0
- data/lib/vwo/common/enums.rb +107 -0
- data/lib/vwo/common/function_utils.rb +25 -0
- data/lib/vwo/common/impression_utils.rb +84 -0
- data/lib/vwo/common/requests.rb +17 -0
- data/lib/vwo/common/schemas/settings_file.rb +90 -0
- data/lib/vwo/common/utils.rb +11 -0
- data/lib/vwo/common/uuid_utils.rb +79 -0
- data/lib/vwo/common/validations.rb +67 -0
- data/lib/vwo/custom_logger.rb +23 -0
- data/lib/vwo/decision_service.rb +305 -0
- data/lib/vwo/event_dispatcher.rb +67 -0
- data/lib/vwo/get_settings.rb +65 -0
- data/lib/vwo/project_config_manager.rb +40 -0
- data/lib/vwo/user_profile.rb +23 -0
- data/lib/vwo.rb +349 -0
- metadata +118 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require_relative '../custom_logger'
|
5
|
+
require_relative 'enums'
|
6
|
+
require_relative 'constants'
|
7
|
+
|
8
|
+
# Utility module for manipulating VWO campaigns
|
9
|
+
class VWO
|
10
|
+
module Common
|
11
|
+
module UUIDUtils
|
12
|
+
include VWO::Common::Enums
|
13
|
+
include VWO::Common::CONSTANTS
|
14
|
+
|
15
|
+
def self.parse(obj)
|
16
|
+
str = obj.to_s.sub(/\Aurn:uuid:/, '')
|
17
|
+
str.gsub!(/[^0-9A-Fa-f]/, '')
|
18
|
+
[str[0..31]].pack 'H*'
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.uuid_v5(uuid_namespace, name)
|
22
|
+
uuid_namespace = parse(uuid_namespace)
|
23
|
+
hash_class = ::Digest::SHA1
|
24
|
+
version = 5
|
25
|
+
|
26
|
+
hash = hash_class.new
|
27
|
+
hash.update(uuid_namespace)
|
28
|
+
hash.update(name)
|
29
|
+
|
30
|
+
ary = hash.digest.unpack('NnnnnN')
|
31
|
+
ary[2] = (ary[2] & 0x0FFF) | (version << 12)
|
32
|
+
ary[3] = (ary[3] & 0x3FFF) | 0x8000
|
33
|
+
# rubocop:disable Lint/FormatString
|
34
|
+
'%08x-%04x-%04x-%04x-%04x%08x' % ary
|
35
|
+
# rubocop:enable Lint/FormatString
|
36
|
+
end
|
37
|
+
|
38
|
+
VWO_NAMESPACE = uuid_v5(URL_NAMESPACE, 'https://vwo.com')
|
39
|
+
|
40
|
+
# Generates desired UUID
|
41
|
+
#
|
42
|
+
# @param[Integer|String] :user_id User identifier
|
43
|
+
# @param[Integer|String] :account_id Account identifier
|
44
|
+
#
|
45
|
+
# @return[Integer] Desired UUID
|
46
|
+
#
|
47
|
+
def generator_for(user_id, account_id)
|
48
|
+
user_id = user_id.to_s
|
49
|
+
account_id = account_id.to_s
|
50
|
+
user_id_namespace = generate(VWO_NAMESPACE, account_id)
|
51
|
+
uuid_for_account_user_id = generate(user_id_namespace, user_id)
|
52
|
+
|
53
|
+
desired_uuid = uuid_for_account_user_id.delete('-').upcase
|
54
|
+
|
55
|
+
VWO::CustomLogger.get_instance.log(
|
56
|
+
LogLevelEnum::DEBUG,
|
57
|
+
format(
|
58
|
+
LogMessageEnum::DebugMessages::UUID_FOR_USER,
|
59
|
+
file: FileNameEnum::UuidUtil,
|
60
|
+
user_id: user_id,
|
61
|
+
account_id: account_id,
|
62
|
+
desired_uuid: desired_uuid
|
63
|
+
)
|
64
|
+
)
|
65
|
+
desired_uuid
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generated uuid from namespace and name, uses uuid5
|
69
|
+
#
|
70
|
+
# @param[String] :namespace Namespace
|
71
|
+
# @param[String) :name Name
|
72
|
+
#
|
73
|
+
# @return[String|Nil] Uuid, nil if any of the arguments is empty
|
74
|
+
def generate(namespace, name)
|
75
|
+
VWO::Common::UUIDUtils.uuid_v5(namespace, name) if name && namespace
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'json-schema'
|
5
|
+
require_relative 'schemas/settings_file'
|
6
|
+
|
7
|
+
class VWO
|
8
|
+
module Common
|
9
|
+
module Validations
|
10
|
+
UTILITIES = {
|
11
|
+
'logger' => ['log'],
|
12
|
+
'event_dispatcher' => ['dispatch'],
|
13
|
+
'user_profile_service' => %w[lookup save]
|
14
|
+
}.freeze
|
15
|
+
# Validates the project settings_file
|
16
|
+
# @param [Hash]: JSON object received from DACDN server or somewhere else,
|
17
|
+
# must be json string representation.
|
18
|
+
# @return [Boolean]
|
19
|
+
def valid_settings_file?(settings_file)
|
20
|
+
settings_file = JSON.parse(settings_file)
|
21
|
+
JSON::Validator.validate!(VWO::Common::Schema::SETTINGS_FILE_SCHEMA, settings_file)
|
22
|
+
rescue StandardError
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Boolean]
|
27
|
+
def valid_value?(val)
|
28
|
+
!val.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Boolean]
|
32
|
+
def valid_number?(val)
|
33
|
+
val.is_a?(Numeric)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Boolean]
|
37
|
+
def valid_string?(val)
|
38
|
+
val.is_a?(String)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Boolean]
|
42
|
+
def valid_hash?(val)
|
43
|
+
val.is_a?(Hash)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Class] - User defined class instance
|
47
|
+
# @param [utility_name] - Name of the utility
|
48
|
+
# @return [Boolean]
|
49
|
+
def valid_utility?(utility, utility_name)
|
50
|
+
utility_attributes = UTILITIES[utility_name]
|
51
|
+
return false if utility_attributes.nil?
|
52
|
+
|
53
|
+
utility_attributes.each do |attr|
|
54
|
+
return false unless method?(utility, attr)
|
55
|
+
end
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# @return [Boolean]
|
62
|
+
def method?(object, method)
|
63
|
+
object.methods.include?(method.to_sym)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
class VWO
|
6
|
+
class CustomLogger
|
7
|
+
@logger = nil
|
8
|
+
@logger_instance = nil
|
9
|
+
|
10
|
+
def self.get_instance(logger_instance = nil)
|
11
|
+
@@logger ||= VWO::CustomLogger.new(logger_instance)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(logger_instance)
|
15
|
+
@@logger_instance = logger_instance || Logger.new(STDOUT)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Override this method to handle logs in a custom manner
|
19
|
+
def log(level, message)
|
20
|
+
@@logger_instance.log(level, message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,305 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'custom_logger'
|
4
|
+
require_relative 'common/enums'
|
5
|
+
require_relative 'common/campaign_utils'
|
6
|
+
require_relative 'common/validations'
|
7
|
+
require_relative 'bucketing_service'
|
8
|
+
|
9
|
+
# Class encapsulating all decision related capabilities.
|
10
|
+
class VWO
|
11
|
+
class DecisionService
|
12
|
+
include VWO::Common::Enums
|
13
|
+
include VWO::Common::CampaignUtils
|
14
|
+
include Common::Validations
|
15
|
+
|
16
|
+
# Initializes DecisionService with settings_file, UserProfileService and logger.
|
17
|
+
# @param[Hash] - Settings file of the project.
|
18
|
+
# @param[Class] - Class instance having the capability of
|
19
|
+
# lookup and save.
|
20
|
+
def initialize(settings_file, user_profile_service = nil)
|
21
|
+
@logger = CustomLogger.get_instance
|
22
|
+
@user_profile_service = user_profile_service
|
23
|
+
# Check if user_profile_service provided is valid or not
|
24
|
+
@user_profile_service = user_profile_service if valid_utility?(user_profile_service, 'user_profile_service')
|
25
|
+
@bucketer = VWO::BucketingService.new
|
26
|
+
@settings_file = settings_file
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns variation for the user for required campaign
|
30
|
+
# First lookup in the UPS, if user_profile is found,
|
31
|
+
# return from there
|
32
|
+
# Else, calculates the variation with helper method
|
33
|
+
#
|
34
|
+
#
|
35
|
+
# @param[String] :user_id The unique ID assigned to User
|
36
|
+
# @param[Hash] :campaign Campaign in which user is participating
|
37
|
+
# @param[String] :campaign_test_key The unique ID of the campaign passed
|
38
|
+
# @return[String,String] ({variation_id, variation_name}|Nil): Tuple of
|
39
|
+
# variation_id and variation_name if variation allotted, else nil
|
40
|
+
|
41
|
+
def get(user_id, campaign, campaign_test_key)
|
42
|
+
campaign_bucket_map = resolve_campaign_bucket_map(user_id)
|
43
|
+
variation = get_stored_variation(user_id, campaign_test_key, campaign_bucket_map) if valid_hash?(campaign_bucket_map)
|
44
|
+
|
45
|
+
if variation
|
46
|
+
@logger.log(
|
47
|
+
LogLevelEnum::INFO,
|
48
|
+
format(
|
49
|
+
LogMessageEnum::InfoMessages::GOT_STORED_VARIATION,
|
50
|
+
file: FILE,
|
51
|
+
campaign_test_key: campaign_test_key,
|
52
|
+
user_id: user_id,
|
53
|
+
variation_name: variation['name']
|
54
|
+
)
|
55
|
+
)
|
56
|
+
return variation['id'], variation['name']
|
57
|
+
end
|
58
|
+
|
59
|
+
variation_id, variation_name = get_variation_allotted(user_id, campaign)
|
60
|
+
|
61
|
+
if variation_name
|
62
|
+
save_user_profile(user_id, campaign_test_key, variation_name) if variation_name
|
63
|
+
|
64
|
+
@logger.log(
|
65
|
+
LogLevelEnum::INFO,
|
66
|
+
format(
|
67
|
+
LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
|
68
|
+
file: FILE,
|
69
|
+
campaign_test_key: campaign_test_key,
|
70
|
+
user_id: user_id,
|
71
|
+
variation_name: variation_name
|
72
|
+
)
|
73
|
+
)
|
74
|
+
else
|
75
|
+
@logger.log(
|
76
|
+
LogLevelEnum::INFO,
|
77
|
+
format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_test_key: campaign_test_key, user_id: user_id)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
[variation_id, variation_name]
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the Variation Allotted to User
|
84
|
+
#
|
85
|
+
# @param[String] :user_id The unique ID assigned to User
|
86
|
+
# @param[Hash] :campaign Campaign Object
|
87
|
+
#
|
88
|
+
# @return[Hash] Variation Object allotted to User
|
89
|
+
|
90
|
+
def get_variation_allotted(user_id, campaign)
|
91
|
+
variation_id, variation_name = nil
|
92
|
+
unless valid_value?(user_id)
|
93
|
+
@logger.log(
|
94
|
+
LogLevelEnum::ERROR,
|
95
|
+
format(LogMessageEnum::ErrorMessages::INVALID_USER_ID, file: FILE, user_id: user_id, method: 'get_variation_alloted')
|
96
|
+
)
|
97
|
+
return variation_id, variation_name
|
98
|
+
end
|
99
|
+
|
100
|
+
if @bucketer.user_part_of_campaign?(user_id, campaign)
|
101
|
+
variation_id, variation_name = get_variation_of_campaign_for_user(user_id, campaign)
|
102
|
+
@logger.log(
|
103
|
+
LogLevelEnum::DEBUG,
|
104
|
+
format(
|
105
|
+
LogMessageEnum::DebugMessages::GOT_VARIATION_FOR_USER,
|
106
|
+
file: FILE,
|
107
|
+
variation_name: variation_name,
|
108
|
+
user_id: user_id,
|
109
|
+
campaign_test_key: campaign['key'],
|
110
|
+
method: 'get_variation_allotted'
|
111
|
+
)
|
112
|
+
)
|
113
|
+
else
|
114
|
+
# not part of campaign
|
115
|
+
@logger.log(
|
116
|
+
LogLevelEnum::DEBUG,
|
117
|
+
format(
|
118
|
+
LogMessageEnum::DebugMessages::USER_NOT_PART_OF_CAMPAIGN,
|
119
|
+
file: FILE,
|
120
|
+
user_id: user_id,
|
121
|
+
campaign_test_key: nil,
|
122
|
+
method: 'get_variation_allotted'
|
123
|
+
)
|
124
|
+
)
|
125
|
+
end
|
126
|
+
[variation_id, variation_name]
|
127
|
+
end
|
128
|
+
|
129
|
+
# Assigns random variation ID to a particular user
|
130
|
+
# Depending on the PercentTraffic.
|
131
|
+
# Makes user a part of campaign if user's included in Traffic.
|
132
|
+
#
|
133
|
+
# @param[String] :user_id The unique ID assigned to a user
|
134
|
+
# @param[Hash] :campaign The Campaign of which user is to be made a part of
|
135
|
+
# @return[Hash|nil] Variation allotted to User
|
136
|
+
def get_variation_of_campaign_for_user(user_id, campaign)
|
137
|
+
unless campaign
|
138
|
+
@logger.log(
|
139
|
+
LogLevelEnum::ERROR,
|
140
|
+
format(
|
141
|
+
LogMessageEnum::ErrorMessages::INVALID_CAMPAIGN,
|
142
|
+
file: FILE,
|
143
|
+
method: 'get_variation_of_campaign_for_user'
|
144
|
+
)
|
145
|
+
)
|
146
|
+
return nil, nil
|
147
|
+
end
|
148
|
+
|
149
|
+
variation = @bucketer.bucket_user_to_variation(user_id, campaign)
|
150
|
+
|
151
|
+
if variation && variation['name']
|
152
|
+
@logger.log(
|
153
|
+
LogLevelEnum::INFO,
|
154
|
+
format(
|
155
|
+
LogMessageEnum::InfoMessages::GOT_VARIATION_FOR_USER,
|
156
|
+
file: FILE,
|
157
|
+
variation_name: variation['name'],
|
158
|
+
user_id: user_id,
|
159
|
+
campaign_test_key: campaign['key']
|
160
|
+
)
|
161
|
+
)
|
162
|
+
return variation['id'], variation['name']
|
163
|
+
end
|
164
|
+
|
165
|
+
@logger.log(
|
166
|
+
LogLevelEnum::INFO,
|
167
|
+
format(
|
168
|
+
LogMessageEnum::InfoMessages::USER_GOT_NO_VARIATION,
|
169
|
+
file: FILE,
|
170
|
+
user_id: user_id,
|
171
|
+
campaign_test_key: campaign['key']
|
172
|
+
)
|
173
|
+
)
|
174
|
+
[nil, nil]
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
# Returns the campaign bucket map corresponding to the user_id
|
180
|
+
#
|
181
|
+
# @param[String] :user_id Unique user identifier
|
182
|
+
# @return[Hash]
|
183
|
+
|
184
|
+
def resolve_campaign_bucket_map(user_id)
|
185
|
+
user_data = get_user_profile(user_id)
|
186
|
+
campaign_bucket_map = {}
|
187
|
+
campaign_bucket_map = user_data['campaignBucketMap'] if user_data
|
188
|
+
campaign_bucket_map.dup
|
189
|
+
end
|
190
|
+
|
191
|
+
# Get the UserProfileData after looking up into lookup method
|
192
|
+
# Being provided via UserProfileService
|
193
|
+
#
|
194
|
+
# @param[String]: Unique user identifier
|
195
|
+
# @return[Hash|Boolean]: user_profile data
|
196
|
+
|
197
|
+
def get_user_profile(user_id)
|
198
|
+
unless @user_profile_service
|
199
|
+
@logger.log(
|
200
|
+
LogLevelEnum::DEBUG,
|
201
|
+
format(LogMessageEnum::DebugMessages::NO_USER_PROFILE_SERVICE_LOOKUP, file: FILE)
|
202
|
+
)
|
203
|
+
return false
|
204
|
+
end
|
205
|
+
|
206
|
+
data = @user_profile_service.lookup(user_id)
|
207
|
+
@logger.log(
|
208
|
+
LogLevelEnum::INFO,
|
209
|
+
format(
|
210
|
+
LogMessageEnum::InfoMessages::LOOKING_UP_USER_PROFILE_SERVICE,
|
211
|
+
file: FILE,
|
212
|
+
user_id: user_id,
|
213
|
+
status: data.nil? ? 'Not Found' : 'Found'
|
214
|
+
)
|
215
|
+
)
|
216
|
+
data
|
217
|
+
rescue StandardError
|
218
|
+
@logger.log(
|
219
|
+
LogLevelEnum::ERROR,
|
220
|
+
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_PROFILE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
221
|
+
)
|
222
|
+
false
|
223
|
+
end
|
224
|
+
|
225
|
+
# If userProfileService is provided and variation was stored,
|
226
|
+
# Get the stored variation
|
227
|
+
# @param[String] :user_id
|
228
|
+
# @param[String] :campaign_test_key campaign identified
|
229
|
+
# @param[Hash] :campaign_bucket_map BucketMap consisting of stored user variation
|
230
|
+
#
|
231
|
+
# @return[Object, nil] if found then variation settings object otherwise None
|
232
|
+
|
233
|
+
def get_stored_variation(user_id, campaign_test_key, campaign_bucket_map)
|
234
|
+
if campaign_bucket_map[campaign_test_key]
|
235
|
+
decision = campaign_bucket_map[campaign_test_key]
|
236
|
+
variation_name = decision['variationName']
|
237
|
+
@logger.log(
|
238
|
+
LogLevelEnum::DEBUG,
|
239
|
+
format(
|
240
|
+
LogMessageEnum::DebugMessages::GETTING_STORED_VARIATION,
|
241
|
+
file: FILE,
|
242
|
+
campaign_test_key: campaign_test_key,
|
243
|
+
user_id: user_id,
|
244
|
+
variation_name: variation_name
|
245
|
+
)
|
246
|
+
)
|
247
|
+
return get_campaign_variation(
|
248
|
+
@settings_file,
|
249
|
+
campaign_test_key,
|
250
|
+
variation_name
|
251
|
+
)
|
252
|
+
end
|
253
|
+
|
254
|
+
@logger.log(
|
255
|
+
LogLevelEnum::DEBUG,
|
256
|
+
format(
|
257
|
+
LogMessageEnum::DebugMessages::NO_STORED_VARIATION,
|
258
|
+
file: FILE,
|
259
|
+
campaign_test_key: campaign_test_key,
|
260
|
+
user_id: user_id
|
261
|
+
)
|
262
|
+
)
|
263
|
+
nil
|
264
|
+
end
|
265
|
+
|
266
|
+
# If userProfileService is provided and variation was stored
|
267
|
+
# Save the assigned variation
|
268
|
+
# It creates bucket and then stores.
|
269
|
+
#
|
270
|
+
# @param[String] :user_id Unique user identifier
|
271
|
+
# @param[String] :campaign_test_key Unique campaign identifier
|
272
|
+
# @param[String] :variation_name Variation identifier
|
273
|
+
# @return[Boolean] true if found otherwise false
|
274
|
+
|
275
|
+
def save_user_profile(user_id, _campaign_test_key, variation_name)
|
276
|
+
unless @user_profile_service
|
277
|
+
@logger.log(
|
278
|
+
LogLevelEnum::DEBUG,
|
279
|
+
format(LogMessageEnum::DebugMessages::NO_USER_PROFILE_SERVICE_SAVE, file: FILE)
|
280
|
+
)
|
281
|
+
return false
|
282
|
+
end
|
283
|
+
new_campaign_bucket_map = {
|
284
|
+
campaign_test_key: {
|
285
|
+
variationName: variation_name
|
286
|
+
}
|
287
|
+
}
|
288
|
+
@user_profile_service.save(
|
289
|
+
userId: user_id,
|
290
|
+
campaignBucketMap: new_campaign_bucket_map
|
291
|
+
)
|
292
|
+
@logger.log(
|
293
|
+
LogLevelEnum::INFO,
|
294
|
+
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_PROFILE_SERVICE, file: FILE, user_id: user_id)
|
295
|
+
)
|
296
|
+
true
|
297
|
+
rescue StandardError
|
298
|
+
@logger.log(
|
299
|
+
LogLevelEnum::ERROR,
|
300
|
+
format(LogMessageEnum::ErrorMessages::SAVE_USER_PROFILE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
301
|
+
)
|
302
|
+
false
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'custom_logger'
|
4
|
+
require_relative 'common/enums'
|
5
|
+
require_relative 'common/requests'
|
6
|
+
|
7
|
+
# Module for dispatching events to the server.
|
8
|
+
class VWO
|
9
|
+
class EventDispatcher
|
10
|
+
include VWO::Common::Enums
|
11
|
+
|
12
|
+
EXCLUDE_KEYS = ['url'].freeze
|
13
|
+
|
14
|
+
# Initialize the dispatcher with logger
|
15
|
+
#
|
16
|
+
# @param [Boolean] : To specify whether the request
|
17
|
+
# to our server should be made or not.
|
18
|
+
#
|
19
|
+
def initialize(is_development_mode = false)
|
20
|
+
@logger = CustomLogger.get_instance
|
21
|
+
@is_development_mode = is_development_mode
|
22
|
+
end
|
23
|
+
|
24
|
+
# Dispatch the event being represented in the properties object.
|
25
|
+
#
|
26
|
+
# @param[Hash] :properties Object holding information about
|
27
|
+
# the request to be dispatched to the VWO backend.
|
28
|
+
# @return[Boolean]
|
29
|
+
#
|
30
|
+
def dispatch(properties)
|
31
|
+
return true if @is_development_mode
|
32
|
+
|
33
|
+
modified_properties = properties.reject do |key, _value|
|
34
|
+
EXCLUDE_KEYS.include?(key)
|
35
|
+
end
|
36
|
+
|
37
|
+
resp = VWO::Common::Requests.get(properties['url'], modified_properties)
|
38
|
+
if resp.code == '200'
|
39
|
+
@logger.log(
|
40
|
+
LogLevelEnum::INFO,
|
41
|
+
format(
|
42
|
+
LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
|
43
|
+
file: FileNameEnum::EventDispatcher,
|
44
|
+
end_point: properties[:url],
|
45
|
+
campaign_id: properties[:experiment_id],
|
46
|
+
user_id: properties[:uId],
|
47
|
+
account_id: properties[:account_id],
|
48
|
+
variation_id: properties[:combination]
|
49
|
+
)
|
50
|
+
)
|
51
|
+
return true
|
52
|
+
else
|
53
|
+
@logger.log(
|
54
|
+
LogLevelEnum::ERROR,
|
55
|
+
format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum.EventDispatcher, end_point: properties['url'])
|
56
|
+
)
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
rescue StandardError
|
60
|
+
@logger.log(
|
61
|
+
LogLevelEnum::ERROR,
|
62
|
+
format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::EventDispatcher, end_point: properties['url'])
|
63
|
+
)
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'common/utils'
|
4
|
+
require_relative 'common/constants'
|
5
|
+
require_relative 'common/requests'
|
6
|
+
require_relative 'common/validations'
|
7
|
+
|
8
|
+
class VWO
|
9
|
+
class GetSettings
|
10
|
+
include VWO::Common::Validations
|
11
|
+
|
12
|
+
PROTOCOL = 'https'
|
13
|
+
HOSTNAME = VWO::Common::CONSTANTS::ENDPOINTS::BASE_URL
|
14
|
+
PATH = VWO::Common::CONSTANTS::ENDPOINTS::ACCOUNT_SETTINGS
|
15
|
+
|
16
|
+
def initialize(account_id, sdk_key)
|
17
|
+
@account_id = account_id
|
18
|
+
@sdk_key = sdk_key
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get method to retrieve settings_file for customer from dacdn server
|
22
|
+
# @param [string]: Account ID of user
|
23
|
+
# @param [string]: Unique sdk key for user,
|
24
|
+
# can be retrieved from our website
|
25
|
+
# @return[string]: Json String representation of settings_file,
|
26
|
+
# as received from the website,
|
27
|
+
# nil if no settings_file is found or sdk_key is incorrect
|
28
|
+
|
29
|
+
def get
|
30
|
+
is_valid_key = valid_number?(@account_id) || valid_string?(@account_id)
|
31
|
+
|
32
|
+
unless is_valid_key && valid_string?(@sdk_key)
|
33
|
+
STDERR.warn 'account_id and sdk_key are required for fetching account settings. Aborting!'
|
34
|
+
return '{}'
|
35
|
+
end
|
36
|
+
|
37
|
+
dacdn_url = "#{PROTOCOL}://#{HOSTNAME}#{PATH}"
|
38
|
+
|
39
|
+
settings_file_response = VWO::Common::Requests.get(dacdn_url, params)
|
40
|
+
|
41
|
+
if settings_file_response.code != '200'
|
42
|
+
STDERR.warn <<-DOC
|
43
|
+
Request failed for fetching account settings.
|
44
|
+
Got Status Code: #{settings_file_response.code}
|
45
|
+
and message: #{settings_file_response.body}.
|
46
|
+
DOC
|
47
|
+
end
|
48
|
+
settings_file_response.body
|
49
|
+
rescue StandardError => e
|
50
|
+
STDERR.warn "Error fetching Settings File #{e}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def params
|
56
|
+
{
|
57
|
+
a: @account_id,
|
58
|
+
i: @sdk_key,
|
59
|
+
r: VWO::Common::Utils.get_random_number,
|
60
|
+
platform: 'server',
|
61
|
+
'api-version' => 2
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'custom_logger'
|
4
|
+
require_relative 'common/enums'
|
5
|
+
require_relative 'common/campaign_utils'
|
6
|
+
|
7
|
+
# Representation of the VWO settings file.
|
8
|
+
|
9
|
+
class VWO
|
10
|
+
class ProjectConfigManager
|
11
|
+
include VWO::Common::Enums
|
12
|
+
include VWO::Common::CampaignUtils
|
13
|
+
|
14
|
+
# ProjectConfigManager init method to load and set project config data.
|
15
|
+
#
|
16
|
+
# @params
|
17
|
+
# settings_file (Hash): Hash object of setting
|
18
|
+
# representing the project settings_file.
|
19
|
+
|
20
|
+
def initialize(settings_file)
|
21
|
+
@settings_file = JSON.parse(settings_file)
|
22
|
+
@logger = VWO::CustomLogger.get_instance
|
23
|
+
end
|
24
|
+
|
25
|
+
# Processes the settings_file, assigns variation allocation range
|
26
|
+
def process_settings_file
|
27
|
+
(@settings_file['campaigns'] || []).each do |campaign|
|
28
|
+
set_variation_allocation(campaign)
|
29
|
+
end
|
30
|
+
@logger.log(
|
31
|
+
LogLevelEnum::DEBUG,
|
32
|
+
format(LogMessageEnum::DebugMessages::SETTINGS_FILE_PROCESSED, file: FileNameEnum::ProjectConfigManager)
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_settings_file
|
37
|
+
@settings_file
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class VWO
|
4
|
+
# Abstract class encapsulating user profile service functionality.
|
5
|
+
# Override with your own implementation for storing
|
6
|
+
# And retrieving the user profile.
|
7
|
+
|
8
|
+
class UserProfile
|
9
|
+
# Abstract method, must be defined to fetch the
|
10
|
+
# User profile dict corresponding to the user_id.
|
11
|
+
#
|
12
|
+
# @param[String] :user_id ID for user whose profile needs to be retrieved.
|
13
|
+
# @return[Hash] :user_profile_obj Object representing the user's profile.
|
14
|
+
#
|
15
|
+
def lookup(_user_id); end
|
16
|
+
|
17
|
+
# Abstract method, must be to defined to save
|
18
|
+
# The user profile dict sent to this method.
|
19
|
+
# @param[Hash] :user_profile_obj Object representing the user's profile.
|
20
|
+
#
|
21
|
+
def save(_user_profile_obj); end
|
22
|
+
end
|
23
|
+
end
|