vwo-sdk 1.6.0 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vwo.rb +571 -195
- data/lib/vwo/constants.rb +26 -3
- data/lib/vwo/core/bucketer.rb +1 -1
- data/lib/vwo/core/variation_decider.rb +155 -40
- data/lib/vwo/enums.rb +30 -5
- data/lib/vwo/logger.rb +1 -1
- data/lib/vwo/schemas/settings_file.rb +1 -1
- data/lib/vwo/services/batch_events_dispatcher.rb +110 -0
- data/lib/vwo/services/batch_events_queue.rb +175 -0
- data/lib/vwo/services/event_dispatcher.rb +1 -13
- data/lib/vwo/services/hooks_manager.rb +36 -0
- data/lib/vwo/services/operand_evaluator.rb +1 -1
- data/lib/vwo/services/segment_evaluator.rb +1 -1
- data/lib/vwo/services/settings_file_manager.rb +8 -4
- data/lib/vwo/services/settings_file_processor.rb +6 -1
- data/lib/vwo/services/usage_stats.rb +29 -0
- data/lib/vwo/user_storage.rb +1 -1
- data/lib/vwo/utils/campaign.rb +108 -1
- data/lib/vwo/utils/custom_dimensions.rb +26 -3
- data/lib/vwo/utils/feature.rb +1 -1
- data/lib/vwo/utils/function.rb +1 -1
- data/lib/vwo/utils/impression.rb +58 -7
- data/lib/vwo/utils/request.rb +15 -1
- data/lib/vwo/utils/segment.rb +1 -1
- data/lib/vwo/utils/uuid.rb +1 -1
- data/lib/vwo/utils/validations.rb +85 -1
- metadata +9 -5
@@ -0,0 +1,110 @@
|
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative '../logger'
|
16
|
+
require_relative '../enums'
|
17
|
+
require_relative '../utils/request'
|
18
|
+
class VWO
|
19
|
+
module Services
|
20
|
+
class BatchEventsDispatcher
|
21
|
+
include VWO::Enums
|
22
|
+
# Initialize the BatchEventDispatcher with logger and development mode
|
23
|
+
#
|
24
|
+
# @param [Boolean] : To specify whether the request
|
25
|
+
# to our server should be made or not.
|
26
|
+
#
|
27
|
+
def initialize
|
28
|
+
@logger = VWO::Logger.get_instance
|
29
|
+
@queue = []
|
30
|
+
end
|
31
|
+
|
32
|
+
# Dispatch the impression event having properties object only if dev-mode is OFF
|
33
|
+
#
|
34
|
+
# @param[Hash] :properties hash having impression properties
|
35
|
+
# the request to be dispatched to the VWO server
|
36
|
+
# @return[Boolean]
|
37
|
+
#
|
38
|
+
def dispatch(impression, callback, query_params)
|
39
|
+
url = CONSTANTS::HTTPS_PROTOCOL + CONSTANTS::ENDPOINTS::BASE_URL + CONSTANTS::ENDPOINTS::BATCH_EVENTS
|
40
|
+
account_id = query_params[:a]
|
41
|
+
resp = VWO::Utils::Request.post(url, query_params, impression)
|
42
|
+
if resp.code == '200'
|
43
|
+
@logger.log(
|
44
|
+
LogLevelEnum::INFO,
|
45
|
+
format(
|
46
|
+
LogMessageEnum::InfoMessages::BULK_IMPRESSION_SUCCESS,
|
47
|
+
file: FileNameEnum::BatchEventsDispatcher,
|
48
|
+
end_point: url,
|
49
|
+
a: account_id
|
50
|
+
)
|
51
|
+
)
|
52
|
+
message = nil
|
53
|
+
elsif resp.code == '413'
|
54
|
+
@logger.log(
|
55
|
+
LogLevelEnum::DEBUG,
|
56
|
+
format(
|
57
|
+
LogMessageEnum::DebugMessages::BATCH_EVENT_LIMIT_EXCEEDED,
|
58
|
+
file: FileNameEnum::BatchEventsDispatcher,
|
59
|
+
end_point: url,
|
60
|
+
accountId: impression[:a],
|
61
|
+
eventsPerRequest: impression.length()
|
62
|
+
)
|
63
|
+
)
|
64
|
+
|
65
|
+
@logger.log(
|
66
|
+
LogLevelEnum::ERROR,
|
67
|
+
format(
|
68
|
+
LogMessageEnum::ErrorMessages::IMPRESSION_FAILED,
|
69
|
+
file: FileNameEnum::BatchEventsDispatcher,
|
70
|
+
end_point: url
|
71
|
+
)
|
72
|
+
)
|
73
|
+
message = resp.message
|
74
|
+
else
|
75
|
+
@logger.log(
|
76
|
+
LogLevelEnum::DEBUG,
|
77
|
+
format(
|
78
|
+
LogMessageEnum::DebugMessages::BULK_NOT_PROCESSED,
|
79
|
+
file: FileNameEnum::BatchEventsDispatcher
|
80
|
+
)
|
81
|
+
)
|
82
|
+
|
83
|
+
@logger.log(
|
84
|
+
LogLevelEnum::ERROR,
|
85
|
+
format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::BatchEventsDispatcher, end_point: url)
|
86
|
+
)
|
87
|
+
message = resp.message
|
88
|
+
end
|
89
|
+
if callback
|
90
|
+
callback.call(message, impression)
|
91
|
+
end
|
92
|
+
rescue StandardError => e
|
93
|
+
@logger.log(
|
94
|
+
LogLevelEnum::DEBUG,
|
95
|
+
format(
|
96
|
+
LogMessageEnum::DebugMessages::BULK_NOT_PROCESSED,
|
97
|
+
file: FileNameEnum::BatchEventsDispatcher
|
98
|
+
)
|
99
|
+
)
|
100
|
+
|
101
|
+
@logger.log(
|
102
|
+
LogLevelEnum::ERROR,
|
103
|
+
format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::BatchEventsDispatcher, end_point: url)
|
104
|
+
)
|
105
|
+
false
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative '../logger'
|
16
|
+
require_relative '../enums'
|
17
|
+
require_relative '../utils/request'
|
18
|
+
|
19
|
+
class VWO
|
20
|
+
module Services
|
21
|
+
class BatchEventsQueue
|
22
|
+
include VWO::Enums
|
23
|
+
|
24
|
+
def initialize(batch_config, is_development_mode = false)
|
25
|
+
@is_development_mode = is_development_mode
|
26
|
+
@logger = VWO::Logger.get_instance
|
27
|
+
@queue = []
|
28
|
+
@queue_metadata = {}
|
29
|
+
@batch_config = batch_config
|
30
|
+
|
31
|
+
if batch_config[:request_time_interval]
|
32
|
+
@request_time_interval = batch_config[:request_time_interval]
|
33
|
+
else
|
34
|
+
@request_time_interval = CONSTANTS::DEFAULT_REQUEST_TIME_INTERVAL
|
35
|
+
@logger.log(
|
36
|
+
LogLevelEnum::DEBUG,
|
37
|
+
format(
|
38
|
+
LogMessageEnum::DebugMessages::EVENT_BATCHING_INSUFFICIENT,
|
39
|
+
file: FileNameEnum::BatchEventsQueue,
|
40
|
+
key: 'request_time_interval'
|
41
|
+
)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
if batch_config[:events_per_request]
|
46
|
+
@events_per_request = batch_config[:events_per_request]
|
47
|
+
else
|
48
|
+
@events_per_request = CONSTANTS::DEFAULT_EVENTS_PER_REQUEST
|
49
|
+
@logger.log(
|
50
|
+
LogLevelEnum::DEBUG,
|
51
|
+
format(
|
52
|
+
LogMessageEnum::DebugMessages::EVENT_BATCHING_INSUFFICIENT,
|
53
|
+
file: FileNameEnum::BatchEventsQueue,
|
54
|
+
key: 'events_per_request'
|
55
|
+
)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
@flush_callback = nil
|
60
|
+
if batch_config.key?(:flushCallback) && batch_config[:flushCallback].is_a?(Method)
|
61
|
+
@flush_callback = batch_config[:flushCallback]
|
62
|
+
end
|
63
|
+
|
64
|
+
@dispatcher = batch_config[:dispatcher]
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_new_batch_timer
|
68
|
+
@timer = Time.now + @request_time_interval
|
69
|
+
end
|
70
|
+
|
71
|
+
def enqueue(event)
|
72
|
+
return true if @is_development_mode
|
73
|
+
@queue.push(event)
|
74
|
+
update_queue_metadata(event)
|
75
|
+
unless @timer
|
76
|
+
create_new_batch_timer
|
77
|
+
@thread = Thread.new{flush_when_request_times_up}
|
78
|
+
end
|
79
|
+
if @events_per_request === @queue.length()
|
80
|
+
flush
|
81
|
+
kill_old_thread
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def flush_when_request_times_up
|
86
|
+
while @timer > Time.now
|
87
|
+
sleep(1)
|
88
|
+
end
|
89
|
+
flush
|
90
|
+
kill_old_thread
|
91
|
+
end
|
92
|
+
|
93
|
+
def flush(manual = false)
|
94
|
+
if @queue.length() > 0
|
95
|
+
@logger.log(
|
96
|
+
LogLevelEnum::DEBUG,
|
97
|
+
format(
|
98
|
+
LogMessageEnum::DebugMessages::BEFORE_FLUSHING,
|
99
|
+
file: FileNameEnum::BatchEventsQueue,
|
100
|
+
manually: manual ? 'manually' : '',
|
101
|
+
length: @queue.length(),
|
102
|
+
timer: manual ? 'Timer will be cleared and registered again,' : '',
|
103
|
+
queue_metadata: @queue_metadata
|
104
|
+
)
|
105
|
+
)
|
106
|
+
|
107
|
+
@dispatcher.call(@queue, @flush_callback)
|
108
|
+
@logger.log(
|
109
|
+
LogLevelEnum::INFO,
|
110
|
+
format(
|
111
|
+
LogMessageEnum::InfoMessages::AFTER_FLUSHING,
|
112
|
+
file: FILE,
|
113
|
+
manually: manual ? 'manually,' : '',
|
114
|
+
length: @queue.length(),
|
115
|
+
queue_metadata: @queue_metadata
|
116
|
+
)
|
117
|
+
)
|
118
|
+
@queue_metadata = {}
|
119
|
+
@queue = []
|
120
|
+
else
|
121
|
+
@logger.log(
|
122
|
+
LogLevelEnum::INFO,
|
123
|
+
format(
|
124
|
+
'Batch queue is empty. Nothing to flush.',
|
125
|
+
file: FILE
|
126
|
+
)
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
clear_request_timer
|
131
|
+
unless manual
|
132
|
+
if @thread
|
133
|
+
@old_thread = @thread
|
134
|
+
end
|
135
|
+
end
|
136
|
+
true
|
137
|
+
end
|
138
|
+
|
139
|
+
def clear_request_timer
|
140
|
+
@timer = nil
|
141
|
+
end
|
142
|
+
|
143
|
+
def kill_thread
|
144
|
+
if @thread
|
145
|
+
@thread.kill
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def kill_old_thread
|
150
|
+
if @old_thread
|
151
|
+
@old_thread.kill
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def update_queue_metadata(event)
|
156
|
+
if event[:eT] == 1
|
157
|
+
unless @queue_metadata.key?(VWO::EVENTS::TRACK_USER)
|
158
|
+
@queue_metadata[VWO::EVENTS::TRACK_USER] = 0
|
159
|
+
end
|
160
|
+
@queue_metadata[VWO::EVENTS::TRACK_USER] = @queue_metadata[VWO::EVENTS::TRACK_USER] + 1
|
161
|
+
elsif event[:eT] == 2
|
162
|
+
unless @queue_metadata.key?(VWO::EVENTS::TRACK_GOAL)
|
163
|
+
@queue_metadata[VWO::EVENTS::TRACK_GOAL] = 0
|
164
|
+
end
|
165
|
+
@queue_metadata[VWO::EVENTS::TRACK_GOAL] = @queue_metadata[VWO::EVENTS::TRACK_GOAL] + 1
|
166
|
+
elsif event[:eT] == 3
|
167
|
+
unless @queue_metadata.key?(VWO::EVENTS::PUSH)
|
168
|
+
@queue_metadata[VWO::EVENTS::PUSH] = 0
|
169
|
+
end
|
170
|
+
@queue_metadata[VWO::EVENTS::PUSH] = @queue_metadata[VWO::EVENTS::PUSH] + 1
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019-
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -48,18 +48,6 @@ class VWO
|
|
48
48
|
|
49
49
|
resp = VWO::Utils::Request.get(impression['url'], modified_event)
|
50
50
|
if resp.code == '200'
|
51
|
-
@logger.log(
|
52
|
-
LogLevelEnum::INFO,
|
53
|
-
format(
|
54
|
-
LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
|
55
|
-
file: FileNameEnum::EventDispatcher,
|
56
|
-
end_point: impression[:url],
|
57
|
-
campaign_id: impression[:experiment_id],
|
58
|
-
user_id: impression[:uId],
|
59
|
-
account_id: impression[:account_id],
|
60
|
-
variation_id: impression[:combination]
|
61
|
-
)
|
62
|
-
)
|
63
51
|
true
|
64
52
|
else
|
65
53
|
@logger.log(
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
class VWO
|
16
|
+
module Services
|
17
|
+
class HooksManager
|
18
|
+
# Hooks Manager is responsible for triggering callbacks useful to the end-user based on certain lifecycle events.
|
19
|
+
# Possible use with integrations when the user intends to send an event when a visitor is part of the experiment.
|
20
|
+
def initialize(config)
|
21
|
+
@logger = VWO::Logger.get_instance
|
22
|
+
if config.key?(:integrations) && config[:integrations].key?(:callback) && config[:integrations][:callback].is_a?(Method)
|
23
|
+
@callback = config[:integrations][:callback]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Executes the callback
|
28
|
+
# @param[Hash] properties Properties from the callback
|
29
|
+
def execute(properties)
|
30
|
+
if @callback
|
31
|
+
@callback.call(properties)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019-
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -25,7 +25,6 @@ class VWO
|
|
25
25
|
|
26
26
|
PROTOCOL = 'https'
|
27
27
|
HOSTNAME = ::VWO::CONSTANTS::ENDPOINTS::BASE_URL
|
28
|
-
PATH = ::VWO::CONSTANTS::ENDPOINTS::ACCOUNT_SETTINGS
|
29
28
|
|
30
29
|
def initialize(account_id, sdk_key)
|
31
30
|
@account_id = account_id
|
@@ -40,7 +39,7 @@ class VWO
|
|
40
39
|
# as received from the server,
|
41
40
|
# nil if no settings_file is found or sdk_key is incorrect
|
42
41
|
|
43
|
-
def get_settings_file
|
42
|
+
def get_settings_file(is_via_webhook = false)
|
44
43
|
is_valid_key = valid_number?(@account_id) || valid_string?(@account_id)
|
45
44
|
|
46
45
|
unless is_valid_key && valid_string?(@sdk_key)
|
@@ -48,7 +47,12 @@ class VWO
|
|
48
47
|
return '{}'
|
49
48
|
end
|
50
49
|
|
51
|
-
|
50
|
+
if is_via_webhook
|
51
|
+
path = ::VWO::CONSTANTS::ENDPOINTS::WEBHOOK_SETTINGS_URL
|
52
|
+
else
|
53
|
+
path = ::VWO::CONSTANTS::ENDPOINTS::SETTINGS_URL
|
54
|
+
end
|
55
|
+
vwo_server_url = "#{PROTOCOL}://#{HOSTNAME}#{path}"
|
52
56
|
|
53
57
|
settings_file_response = ::VWO::Utils::Request.get(vwo_server_url, params)
|
54
58
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019-
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -44,6 +44,11 @@ class VWO
|
|
44
44
|
)
|
45
45
|
end
|
46
46
|
|
47
|
+
def update_settings_file(settings_file)
|
48
|
+
@settings_file = settings_file
|
49
|
+
process_settings_file
|
50
|
+
end
|
51
|
+
|
47
52
|
def get_settings_file
|
48
53
|
@settings_file
|
49
54
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
class VWO
|
16
|
+
module Services
|
17
|
+
class UsageStats
|
18
|
+
attr_reader :usage_stats
|
19
|
+
# Initialize the UsageStats
|
20
|
+
def initialize(stats, is_development_mode = false)
|
21
|
+
@usage_stats = {}
|
22
|
+
unless is_development_mode
|
23
|
+
@usage_stats = stats
|
24
|
+
@usage_stats[:_l] = 1 if @usage_stats.length > 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|