vwo-fme-ruby-sdk 1.6.1 → 1.8.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 +4 -4
- data/lib/resources/error_messages.json +46 -18
- data/lib/resources/info_messages.json +4 -2
- data/lib/vwo/api/get_flag.rb +13 -8
- data/lib/vwo/api/track_event.rb +2 -2
- data/lib/vwo/constants/constants.rb +24 -1
- data/lib/vwo/decorators/storage_decorator.rb +1 -5
- data/lib/vwo/enums/api_enum.rb +7 -3
- data/lib/vwo/enums/debug_category_enum.rb +20 -0
- data/lib/vwo/enums/event_enum.rb +1 -0
- data/lib/vwo/models/user/context_model.rb +36 -2
- data/lib/vwo/models/vwo_options_model.rb +14 -3
- data/lib/vwo/packages/network_layer/client/network_client.rb +189 -34
- data/lib/vwo/packages/network_layer/manager/network_manager.rb +71 -6
- data/lib/vwo/packages/network_layer/models/request_model.rb +38 -4
- data/lib/vwo/packages/network_layer/models/response_model.rb +10 -1
- data/lib/vwo/packages/segmentation_evaluator/core/segmentation_manager.rb +2 -1
- data/lib/vwo/packages/segmentation_evaluator/evaluators/segment_evaluator.rb +5 -3
- data/lib/vwo/packages/segmentation_evaluator/evaluators/segment_operand_evaluator.rb +3 -2
- data/lib/vwo/services/logger_service.rb +21 -1
- data/lib/vwo/services/settings_service.rb +37 -9
- data/lib/vwo/services/storage_service.rb +5 -4
- data/lib/vwo/utils/{batch_event_dispatcher.rb → batch_event_dispatcher_util.rb} +70 -9
- data/lib/vwo/utils/campaign_util.rb +35 -0
- data/lib/vwo/utils/debugger_service_util.rb +40 -0
- data/lib/vwo/utils/event_util.rb +8 -2
- data/lib/vwo/utils/function_util.rb +14 -0
- data/lib/vwo/utils/gateway_service_util.rb +5 -5
- data/lib/vwo/utils/impression_util.rb +16 -2
- data/lib/vwo/utils/meg_util.rb +29 -22
- data/lib/vwo/utils/network_util.rb +145 -38
- data/lib/vwo/utils/rule_evaluation_util.rb +1 -1
- data/lib/vwo/vwo_builder.rb +15 -11
- data/lib/vwo/vwo_client.rb +11 -25
- metadata +5 -4
- data/lib/vwo/utils/url_util.rb +0 -53
|
@@ -21,9 +21,11 @@ require_relative '../utils/network_util'
|
|
|
21
21
|
require_relative '../services/logger_service'
|
|
22
22
|
require_relative '../enums/log_level_enum'
|
|
23
23
|
require_relative '../models/schemas/settings_schema_validation'
|
|
24
|
+
require_relative '../enums/api_enum'
|
|
25
|
+
require_relative '../utils/debugger_service_util'
|
|
24
26
|
|
|
25
27
|
class SettingsService
|
|
26
|
-
attr_accessor :sdk_key, :account_id, :expiry, :network_timeout, :hostname, :port, :protocol, :is_gateway_service_provided, :is_settings_valid, :settings_fetch_time
|
|
28
|
+
attr_accessor :sdk_key, :account_id, :expiry, :network_timeout, :hostname, :port, :protocol, :is_gateway_service_provided, :is_settings_valid, :settings_fetch_time, :proxy_url, :is_proxy_url_provided, :collection_prefix
|
|
27
29
|
|
|
28
30
|
class << self
|
|
29
31
|
attr_accessor :instance
|
|
@@ -53,6 +55,15 @@ class SettingsService
|
|
|
53
55
|
@protocol = parsed_url.scheme
|
|
54
56
|
@port = parsed_url.port || options.dig(:gateway_service, :port)
|
|
55
57
|
@is_gateway_service_provided = true
|
|
58
|
+
if options[:proxy_url] && !options[:proxy_url].nil? && !options[:proxy_url].empty?
|
|
59
|
+
LoggerService.log(LogLevelEnum::INFO, "PROXY_AND_GATEWAY_SERVICE_PROVIDED")
|
|
60
|
+
end
|
|
61
|
+
elsif options[:proxy_url] && !options[:proxy_url].nil? && !options[:proxy_url].empty?
|
|
62
|
+
parsed_url = URI.parse(options[:proxy_url])
|
|
63
|
+
@hostname = parsed_url.hostname
|
|
64
|
+
@protocol = parsed_url.scheme
|
|
65
|
+
@port = parsed_url.port
|
|
66
|
+
@is_proxy_url_provided = true
|
|
56
67
|
else
|
|
57
68
|
@hostname = Constants::HOST_NAME
|
|
58
69
|
@protocol = Constants::HTTPS_PROTOCOL
|
|
@@ -62,6 +73,13 @@ class SettingsService
|
|
|
62
73
|
SettingsService.instance = self
|
|
63
74
|
end
|
|
64
75
|
|
|
76
|
+
def get_updated_endpoint_with_collection_prefix(endpoint)
|
|
77
|
+
if @collection_prefix && !@collection_prefix.empty?
|
|
78
|
+
return "/#{@collection_prefix}#{endpoint}"
|
|
79
|
+
end
|
|
80
|
+
return endpoint
|
|
81
|
+
end
|
|
82
|
+
|
|
65
83
|
# Fetch settings and cache them in storage.
|
|
66
84
|
# @return [SettingsModel] The fetched settings
|
|
67
85
|
def fetch_settings_and_cache_in_storage
|
|
@@ -69,8 +87,8 @@ class SettingsService
|
|
|
69
87
|
response = fetch_settings
|
|
70
88
|
response
|
|
71
89
|
rescue => e
|
|
72
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
73
|
-
|
|
90
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_FETCHING_SETTINGS", { err: e.message, an: ApiEnum::INIT}, false)
|
|
91
|
+
{}
|
|
74
92
|
end
|
|
75
93
|
end
|
|
76
94
|
|
|
@@ -79,7 +97,7 @@ class SettingsService
|
|
|
79
97
|
# @return [SettingsModel] The fetched settings
|
|
80
98
|
def fetch_settings(is_via_webhook = false)
|
|
81
99
|
if @sdk_key.nil? || @account_id.nil?
|
|
82
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
100
|
+
LoggerService.log(LogLevelEnum::ERROR, "INVALID_SDK_KEY_OR_ACCOUNT_ID", { an: ApiEnum::INIT})
|
|
83
101
|
end
|
|
84
102
|
|
|
85
103
|
network_instance = NetworkManager.instance
|
|
@@ -108,15 +126,25 @@ class SettingsService
|
|
|
108
126
|
# calculate the time taken to fetch the settings
|
|
109
127
|
settings_fetch_end_time = (Time.now.to_f * 1000).to_i
|
|
110
128
|
time_taken = settings_fetch_end_time - settings_fetch_start_time
|
|
111
|
-
@settings_fetch_time = time_taken.to_s
|
|
129
|
+
@settings_fetch_time = time_taken.to_s
|
|
130
|
+
|
|
131
|
+
if response.get_total_attempts > 0
|
|
132
|
+
api_enum = is_via_webhook ? ApiEnum::UPDATE_SETTINGS : ApiEnum::INIT
|
|
133
|
+
debug_event_props = NetworkUtil.create_network_and_retry_debug_event(response, nil, api_enum, path)
|
|
134
|
+
# send debug event
|
|
135
|
+
DebuggerServiceUtil.send_debugger_event(debug_event_props)
|
|
136
|
+
end
|
|
112
137
|
settings = response.get_data
|
|
138
|
+
if settings.nil? || settings.empty?
|
|
139
|
+
settings = {}
|
|
140
|
+
end
|
|
113
141
|
# Deep duplicate the settings to avoid modifying the original object
|
|
114
142
|
normalized_settings = SettingsService.normalize_settings(settings)
|
|
115
|
-
|
|
143
|
+
@collection_prefix = normalized_settings['collectionPrefix'] if normalized_settings['collectionPrefix'] && !normalized_settings['collectionPrefix'].empty?
|
|
116
144
|
normalized_settings
|
|
117
145
|
rescue => e
|
|
118
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
119
|
-
|
|
146
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_FETCHING_SETTINGS", { err: e.message, an: ApiEnum::INIT})
|
|
147
|
+
{}
|
|
120
148
|
end
|
|
121
149
|
end
|
|
122
150
|
|
|
@@ -134,7 +162,7 @@ class SettingsService
|
|
|
134
162
|
LoggerService.log(LogLevelEnum::INFO, "SETTINGS_FETCH_SUCCESS")
|
|
135
163
|
settings
|
|
136
164
|
else
|
|
137
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
165
|
+
LoggerService.log(LogLevelEnum::ERROR, "INVALID_SETTINGS_SCHEMA", { accountId: @account_id, sdkKey: @sdk_key, settings: settings, an: ApiEnum::INIT}, false)
|
|
138
166
|
{}
|
|
139
167
|
end
|
|
140
168
|
end
|
|
@@ -18,6 +18,7 @@ require_relative '../packages/storage/storage'
|
|
|
18
18
|
require_relative '../services/logger_service'
|
|
19
19
|
require_relative '../enums/log_level_enum'
|
|
20
20
|
require_relative '../utils/data_type_util'
|
|
21
|
+
require_relative '../enums/api_enum'
|
|
21
22
|
|
|
22
23
|
class StorageService
|
|
23
24
|
attr_accessor :storage_data
|
|
@@ -40,7 +41,7 @@ class StorageService
|
|
|
40
41
|
data = storage_instance.get(feature_key, context.get_id)
|
|
41
42
|
return data.nil? ? StorageEnum::NO_DATA_FOUND : data
|
|
42
43
|
rescue StandardError => e
|
|
43
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
44
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_READING_DATA_FROM_STORAGE", { err: e.message, an: ApiEnum::GET_FLAG, sId: context.get_session_id, uuid: context.get_uuid})
|
|
44
45
|
return StorageEnum::NO_DATA_FOUND
|
|
45
46
|
end
|
|
46
47
|
end
|
|
@@ -48,7 +49,7 @@ class StorageService
|
|
|
48
49
|
# Stores data in the storage.
|
|
49
50
|
# @param data [Hash] The data to be stored.
|
|
50
51
|
# @return [Boolean] True if data is successfully stored, otherwise false.
|
|
51
|
-
def set_data_in_storage(data)
|
|
52
|
+
def set_data_in_storage(data, context)
|
|
52
53
|
storage_instance = Storage.instance.get_connector
|
|
53
54
|
|
|
54
55
|
# Check if the storage instance is available
|
|
@@ -57,8 +58,8 @@ class StorageService
|
|
|
57
58
|
begin
|
|
58
59
|
storage_instance.set(data)
|
|
59
60
|
return true
|
|
60
|
-
rescue StandardError
|
|
61
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
61
|
+
rescue StandardError => e
|
|
62
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_STORING_DATA_IN_STORAGE", { err: e.message, an: ApiEnum::GET_FLAG, sId: context.get_session_id, uuid: context.get_uuid})
|
|
62
63
|
return false
|
|
63
64
|
end
|
|
64
65
|
end
|
|
@@ -12,15 +12,19 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
require 'set'
|
|
15
16
|
require_relative './network_util'
|
|
16
17
|
require_relative '../enums/http_method_enum'
|
|
17
18
|
require_relative '../enums/url_enum'
|
|
18
19
|
require_relative '../enums/log_level_enum'
|
|
20
|
+
require_relative '../enums/event_enum'
|
|
19
21
|
require_relative '../services/logger_service'
|
|
20
22
|
require_relative '../packages/network_layer/manager/network_manager'
|
|
21
23
|
require_relative '../packages/network_layer/models/request_model'
|
|
24
|
+
require_relative '../packages/network_layer/models/response_model'
|
|
25
|
+
require_relative '../utils/function_util'
|
|
22
26
|
|
|
23
|
-
class
|
|
27
|
+
class BatchEventDispatcherUtil
|
|
24
28
|
|
|
25
29
|
class << self
|
|
26
30
|
|
|
@@ -40,26 +44,45 @@ class BatchEventDispatcher
|
|
|
40
44
|
headers['Authorization'] = "#{SettingsService.instance.sdk_key}"
|
|
41
45
|
|
|
42
46
|
request = RequestModel.new(
|
|
43
|
-
|
|
47
|
+
SettingsService.instance.hostname,
|
|
44
48
|
HttpMethodEnum::POST,
|
|
45
|
-
UrlEnum::BATCH_EVENTS,
|
|
49
|
+
SettingsService.instance.get_updated_endpoint_with_collection_prefix(UrlEnum::BATCH_EVENTS),
|
|
46
50
|
properties,
|
|
47
51
|
payload,
|
|
48
52
|
headers,
|
|
49
53
|
SettingsService.instance.protocol,
|
|
50
54
|
SettingsService.instance.port
|
|
51
55
|
)
|
|
56
|
+
|
|
57
|
+
event_counts = extract_event_counts(payload)
|
|
58
|
+
extra_data = "#{Constants::BATCH_EVENTS} having"
|
|
59
|
+
if event_counts[:variation_shown_count] > 0
|
|
60
|
+
extra_data += "getFlag events: #{event_counts[:variation_shown_count]}, "
|
|
61
|
+
end
|
|
62
|
+
if event_counts[:custom_event_count] > 0
|
|
63
|
+
extra_data += "conversion events: #{event_counts[:custom_event_count]}, "
|
|
64
|
+
end
|
|
65
|
+
if event_counts[:set_attribute_count] > 0
|
|
66
|
+
extra_data += "setAttribute events: #{event_counts[:set_attribute_count]}, "
|
|
67
|
+
end
|
|
52
68
|
|
|
53
69
|
begin
|
|
54
70
|
response = network_instance.post(request)
|
|
71
|
+
# Only send debug event if response is valid and has retry attempts
|
|
72
|
+
if response.is_a?(ResponseModel) && response.get_total_attempts && response.get_total_attempts > 0
|
|
73
|
+
debug_event_props = NetworkUtil.create_network_and_retry_debug_event(response, nil, Constants::BATCH_EVENTS, extra_data)
|
|
74
|
+
# send debug event
|
|
75
|
+
DebuggerServiceUtil.send_debugger_event(debug_event_props) if debug_event_props
|
|
76
|
+
end
|
|
55
77
|
handle_batch_response(UrlEnum::BATCH_EVENTS, payload, properties, response, response.get_data, callback)
|
|
56
78
|
rescue StandardError => err
|
|
79
|
+
# TODO: remove this log after testing
|
|
57
80
|
LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
|
|
58
|
-
method:
|
|
59
|
-
err: err
|
|
81
|
+
method: extra_data,
|
|
82
|
+
err: get_formatted_error_message(err)
|
|
60
83
|
})
|
|
61
84
|
end
|
|
62
|
-
|
|
85
|
+
end
|
|
63
86
|
|
|
64
87
|
# Handles the response from a batch event API call
|
|
65
88
|
# @param end_point [String] The API endpoint that was called
|
|
@@ -69,6 +92,7 @@ class BatchEventDispatcher
|
|
|
69
92
|
# @param raw_data [String] The raw response data from the API
|
|
70
93
|
# @param callback [Proc] Optional callback to be executed after handling the response
|
|
71
94
|
def handle_batch_response(end_point, payload, query_params, res, raw_data, callback)
|
|
95
|
+
# TODO: update this method with debug event logs
|
|
72
96
|
events_per_request = payload[:ev].length
|
|
73
97
|
account_id = query_params[:a]
|
|
74
98
|
|
|
@@ -78,7 +102,7 @@ class BatchEventDispatcher
|
|
|
78
102
|
LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
|
|
79
103
|
method: "#{HttpMethodEnum::POST} #{UrlEnum::BATCH_EVENTS}",
|
|
80
104
|
err: error
|
|
81
|
-
})
|
|
105
|
+
}, false)
|
|
82
106
|
callback.call(error, payload.to_json) if callback.respond_to?(:call)
|
|
83
107
|
return {status: "error", events: payload}
|
|
84
108
|
else
|
|
@@ -99,7 +123,7 @@ class BatchEventDispatcher
|
|
|
99
123
|
LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
|
|
100
124
|
method: "#{HttpMethodEnum::POST} #{UrlEnum::BATCH_EVENTS}",
|
|
101
125
|
err: error
|
|
102
|
-
})
|
|
126
|
+
}, false)
|
|
103
127
|
callback.call(error, payload.to_json) if callback.respond_to?(:call)
|
|
104
128
|
return {status: "error", events: payload}
|
|
105
129
|
else
|
|
@@ -107,11 +131,48 @@ class BatchEventDispatcher
|
|
|
107
131
|
LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
|
|
108
132
|
method: "#{HttpMethodEnum::POST} #{UrlEnum::BATCH_EVENTS}",
|
|
109
133
|
err: error
|
|
110
|
-
})
|
|
134
|
+
}, false)
|
|
111
135
|
callback.call(error, payload.to_json) if callback.respond_to?(:call)
|
|
112
136
|
return {status: "error", events: payload}
|
|
113
137
|
end
|
|
114
138
|
end
|
|
115
139
|
end
|
|
140
|
+
|
|
141
|
+
# Extracts event counts from a batch payload
|
|
142
|
+
# @param payload [Hash] The payload containing events
|
|
143
|
+
# @return [Hash] Hash with variationShownCount, setAttributeCount, and customEventCount
|
|
144
|
+
def extract_event_counts(payload)
|
|
145
|
+
counts = {
|
|
146
|
+
variation_shown_count: 0,
|
|
147
|
+
set_attribute_count: 0,
|
|
148
|
+
custom_event_count: 0
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Get all standard event names from EventEnum
|
|
152
|
+
standard_event_names = EventEnum.constants.map { |const| EventEnum.const_get(const) }.to_set
|
|
153
|
+
events = payload&.dig(:ev) || []
|
|
154
|
+
|
|
155
|
+
events.each do |entry|
|
|
156
|
+
name = entry&.dig(:d, :event, :name)
|
|
157
|
+
|
|
158
|
+
next unless name
|
|
159
|
+
|
|
160
|
+
if name == EventEnum::VWO_VARIATION_SHOWN
|
|
161
|
+
counts[:variation_shown_count] += 1
|
|
162
|
+
next
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
if name == EventEnum::VWO_SYNC_VISITOR_PROP
|
|
166
|
+
counts[:set_attribute_count] += 1
|
|
167
|
+
next
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
unless standard_event_names.include?(name)
|
|
171
|
+
counts[:custom_event_count] += 1
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
counts
|
|
176
|
+
end
|
|
116
177
|
end
|
|
117
178
|
end
|
|
@@ -246,4 +246,39 @@ module CampaignUtil
|
|
|
246
246
|
})
|
|
247
247
|
end
|
|
248
248
|
end
|
|
249
|
+
|
|
250
|
+
# Retrieves the campaign key from the campaign ID
|
|
251
|
+
# @param settings [SettingsModel] The settings for the VWO instance
|
|
252
|
+
# @param campaign_id [Integer] The ID of the campaign
|
|
253
|
+
# @return [String] The campaign key
|
|
254
|
+
def self.get_campaign_key_from_campaign_id(settings, campaign_id)
|
|
255
|
+
settings.get_campaigns.each do |campaign|
|
|
256
|
+
return campaign.get_key if campaign.get_id == campaign_id
|
|
257
|
+
end
|
|
258
|
+
nil
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Retrieves the variation name from the campaign ID and variation ID
|
|
262
|
+
# @param settings [SettingsModel] The settings for the VWO instance
|
|
263
|
+
# @param campaign_id [Integer] The ID of the campaign
|
|
264
|
+
# @param variation_id [Integer] The ID of the variation
|
|
265
|
+
# @return [String] The variation name
|
|
266
|
+
def self.get_variation_name_from_campaign_id_and_variation_id(settings, campaign_id, variation_id)
|
|
267
|
+
campaign = settings.get_campaigns.find { |c| c.get_id == campaign_id }
|
|
268
|
+
return nil unless campaign
|
|
269
|
+
|
|
270
|
+
variation = campaign.get_variations.find { |v| v.get_id == variation_id }
|
|
271
|
+
variation ? variation.get_key : nil
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Retrieves the campaign type from the campaign ID
|
|
275
|
+
# @param settings [SettingsModel] The settings for the VWO instance
|
|
276
|
+
# @param campaign_id [Integer] The ID of the campaign
|
|
277
|
+
# @return [String] The campaign type
|
|
278
|
+
def self.get_campaign_type_from_campaign_id(settings, campaign_id)
|
|
279
|
+
campaign = settings.get_campaigns.find { |c| c.get_id == campaign_id }
|
|
280
|
+
return nil unless campaign
|
|
281
|
+
|
|
282
|
+
campaign.get_type
|
|
283
|
+
end
|
|
249
284
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Copyright 2024-2025 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 '../services/logger_service'
|
|
16
|
+
require_relative '../enums/log_level_enum'
|
|
17
|
+
require_relative '../utils/network_util'
|
|
18
|
+
require_relative '../services/batch_event_queue'
|
|
19
|
+
require_relative '../enums/event_enum'
|
|
20
|
+
|
|
21
|
+
class DebuggerServiceUtil
|
|
22
|
+
class << self
|
|
23
|
+
def send_debugger_event(event_props)
|
|
24
|
+
# get base properties for the event
|
|
25
|
+
properties = NetworkUtil.get_events_base_properties(EventEnum::VWO_DEBUGGER_EVENT)
|
|
26
|
+
|
|
27
|
+
# get debugger event payload
|
|
28
|
+
payload = NetworkUtil.get_debugger_event_payload(event_props)
|
|
29
|
+
|
|
30
|
+
# send event
|
|
31
|
+
if BatchEventsQueue.instance
|
|
32
|
+
# add the payload to the batch events queue
|
|
33
|
+
BatchEventsQueue.instance.enqueue(payload)
|
|
34
|
+
else
|
|
35
|
+
# Send the prepared payload via POST API request
|
|
36
|
+
NetworkUtil.send_event(properties, payload)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/vwo/utils/event_util.rb
CHANGED
|
@@ -44,6 +44,12 @@ def send_sdk_usage_stats_event(usage_stats_account_id)
|
|
|
44
44
|
# create payload
|
|
45
45
|
payload = NetworkUtil.get_sdk_usage_stats_payload_data(EventEnum::VWO_USAGE_STATS, usage_stats_account_id)
|
|
46
46
|
|
|
47
|
-
#
|
|
48
|
-
|
|
47
|
+
# check if batching is enabled
|
|
48
|
+
if BatchEventsQueue.instance
|
|
49
|
+
# add the payload to the batch events queue
|
|
50
|
+
BatchEventsQueue.instance.enqueue(payload)
|
|
51
|
+
else
|
|
52
|
+
# send event
|
|
53
|
+
NetworkUtil.send_event(properties, payload)
|
|
54
|
+
end
|
|
49
55
|
end
|
|
@@ -125,3 +125,17 @@ def add_linked_campaigns_to_settings(settings)
|
|
|
125
125
|
feature.set_rules_linked_campaign(rules_linked_campaign)
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
|
+
|
|
129
|
+
# Formats error messages for logging
|
|
130
|
+
# @param error [Object] The error object (can be Error, String, Hash, etc.)
|
|
131
|
+
# @return [String] The formatted error message
|
|
132
|
+
def get_formatted_error_message(error)
|
|
133
|
+
if error.is_a?(StandardError)
|
|
134
|
+
error.message
|
|
135
|
+
elsif error.is_a?(String)
|
|
136
|
+
error
|
|
137
|
+
elsif error.is_a?(Hash) || error.is_a?(Array)
|
|
138
|
+
error.to_json
|
|
139
|
+
end
|
|
140
|
+
error
|
|
141
|
+
end
|
|
@@ -17,10 +17,10 @@ require_relative '../packages/network_layer/manager/network_manager'
|
|
|
17
17
|
require_relative '../packages/network_layer/models/request_model'
|
|
18
18
|
require_relative '../enums/http_method_enum'
|
|
19
19
|
require_relative '../services/settings_service'
|
|
20
|
-
require_relative 'url_util'
|
|
21
20
|
require_relative '../enums/campaign_type_enum'
|
|
22
21
|
require_relative '../services/logger_service'
|
|
23
22
|
require_relative '../enums/log_level_enum'
|
|
23
|
+
require_relative '../enums/api_enum'
|
|
24
24
|
|
|
25
25
|
# Retrieves data from a web service using the specified query parameters and endpoint.
|
|
26
26
|
# @param query_params [Hash] The parameters to be used in the query string of the request.
|
|
@@ -30,15 +30,15 @@ def get_from_gateway_service(query_params, endpoint)
|
|
|
30
30
|
network_instance = NetworkManager.instance
|
|
31
31
|
|
|
32
32
|
unless SettingsService.instance.is_gateway_service_provided
|
|
33
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
33
|
+
LoggerService.log(LogLevelEnum::ERROR, "INVALID_GATEWAY_URL", { an: ApiEnum::GET_FLAG})
|
|
34
34
|
return false
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
begin
|
|
38
38
|
request = RequestModel.new(
|
|
39
|
-
|
|
39
|
+
SettingsService.instance.hostname,
|
|
40
40
|
HttpMethodEnum::GET,
|
|
41
|
-
endpoint,
|
|
41
|
+
SettingsService.instance.get_updated_endpoint_with_collection_prefix(endpoint),
|
|
42
42
|
query_params,
|
|
43
43
|
nil,
|
|
44
44
|
nil,
|
|
@@ -49,7 +49,7 @@ def get_from_gateway_service(query_params, endpoint)
|
|
|
49
49
|
response = network_instance.get(request)
|
|
50
50
|
return response.get_data
|
|
51
51
|
rescue StandardError => e
|
|
52
|
-
LoggerService.log(LogLevelEnum::ERROR, "
|
|
52
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_FETCHING_SETTINGS", { err: e.message, an: ApiEnum::GET_FLAG})
|
|
53
53
|
return false
|
|
54
54
|
end
|
|
55
55
|
end
|
|
@@ -17,6 +17,7 @@ require_relative './network_util'
|
|
|
17
17
|
require_relative '../models/user/context_model'
|
|
18
18
|
require_relative '../enums/event_enum'
|
|
19
19
|
require_relative '../services/batch_event_queue'
|
|
20
|
+
require_relative '../utils/campaign_util'
|
|
20
21
|
# Creates and sends an impression for a variation shown event.
|
|
21
22
|
# This function constructs the necessary properties and payload for the event
|
|
22
23
|
# and uses the NetworkUtil to send a POST API request.
|
|
@@ -25,7 +26,7 @@ require_relative '../services/batch_event_queue'
|
|
|
25
26
|
# @param campaign_id [Integer] The ID of the campaign.
|
|
26
27
|
# @param variation_id [Integer] The ID of the variation shown to the user.
|
|
27
28
|
# @param context [ContextModel] The user context model containing user-specific data.
|
|
28
|
-
def create_and_send_impression_for_variation_shown(settings, campaign_id, variation_id, context)
|
|
29
|
+
def create_and_send_impression_for_variation_shown(settings, campaign_id, variation_id, context, feature_key)
|
|
29
30
|
# Get base properties for the event
|
|
30
31
|
properties = NetworkUtil.get_events_base_properties(
|
|
31
32
|
EventEnum::VWO_VARIATION_SHOWN,
|
|
@@ -41,12 +42,25 @@ def create_and_send_impression_for_variation_shown(settings, campaign_id, variat
|
|
|
41
42
|
context
|
|
42
43
|
)
|
|
43
44
|
|
|
45
|
+
campaign_key_with_feature_name = CampaignUtil.get_campaign_key_from_campaign_id(settings, campaign_id)
|
|
46
|
+
variation_name = CampaignUtil.get_variation_name_from_campaign_id_and_variation_id(settings, campaign_id, variation_id)
|
|
47
|
+
|
|
48
|
+
campaign_key = ''
|
|
49
|
+
|
|
50
|
+
if feature_key == campaign_key_with_feature_name
|
|
51
|
+
campaign_key = Constants::IMPACT_ANALYSIS
|
|
52
|
+
else
|
|
53
|
+
campaign_key = campaign_key_with_feature_name.split("#{feature_key}_")[1]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
campaign_type = CampaignUtil.get_campaign_type_from_campaign_id(settings, campaign_id)
|
|
57
|
+
|
|
44
58
|
# check if batching is enabled
|
|
45
59
|
if BatchEventsQueue.instance
|
|
46
60
|
# add the payload to the batch events queue
|
|
47
61
|
BatchEventsQueue.instance.enqueue(payload)
|
|
48
62
|
else
|
|
49
63
|
# Send the constructed payload via POST request
|
|
50
|
-
NetworkUtil.send_post_api_request(properties, payload)
|
|
64
|
+
NetworkUtil.send_post_api_request(properties, payload, { campaign_type: campaign_type, feature_key: feature_key, campaign_key: campaign_key, variation_name: variation_name })
|
|
51
65
|
end
|
|
52
66
|
end
|
data/lib/vwo/utils/meg_util.rb
CHANGED
|
@@ -30,6 +30,7 @@ require_relative './decision_util'
|
|
|
30
30
|
require_relative './function_util'
|
|
31
31
|
require_relative '../services/logger_service'
|
|
32
32
|
require_relative '../enums/log_level_enum'
|
|
33
|
+
require_relative '../enums/api_enum'
|
|
33
34
|
|
|
34
35
|
# Evaluates groups for a given feature and group ID.
|
|
35
36
|
# @param settings [SettingsModel] The settings for the VWO instance
|
|
@@ -249,16 +250,20 @@ def normalize_weights_and_find_winning_campaign(shortlisted_campaigns, context,
|
|
|
249
250
|
}
|
|
250
251
|
)
|
|
251
252
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
253
|
+
begin
|
|
254
|
+
StorageDecorator.new.set_data_in_storage(
|
|
255
|
+
{
|
|
256
|
+
feature_key: "#{Constants::VWO_META_MEG_KEY}#{group_id}",
|
|
257
|
+
context: context,
|
|
258
|
+
experiment_id: winner_campaign.id,
|
|
259
|
+
experiment_key: winner_campaign.key,
|
|
260
|
+
experiment_variation_id: winner_campaign.type == CampaignTypeEnum::PERSONALIZE ? winner_campaign.variations[0].id : -1
|
|
261
|
+
},
|
|
262
|
+
storage_service
|
|
263
|
+
)
|
|
264
|
+
rescue StandardError => e
|
|
265
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_STORING_DATA_IN_STORAGE", { err: e.message, an: ApiEnum::GET_FLAG, sId: context.get_session_id, uuid: context.get_uuid})
|
|
266
|
+
end
|
|
262
267
|
|
|
263
268
|
return winner_campaign if called_campaign_ids.include?(winner_campaign.id)
|
|
264
269
|
else
|
|
@@ -329,18 +334,20 @@ def get_campaign_using_advanced_algo(settings, shortlisted_campaigns, context, c
|
|
|
329
334
|
algo: 'using advanced algorithm'
|
|
330
335
|
}
|
|
331
336
|
)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
337
|
+
begin
|
|
338
|
+
StorageDecorator.new.set_data_in_storage(
|
|
339
|
+
{
|
|
340
|
+
feature_key: "#{Constants::VWO_META_MEG_KEY}#{group_id}",
|
|
341
|
+
context: context,
|
|
342
|
+
experiment_id: winner_campaign.id,
|
|
343
|
+
experiment_key: winner_campaign.key,
|
|
344
|
+
experiment_variation_id: winner_campaign.type == CampaignTypeEnum::PERSONALIZE ? winner_campaign.variations[0].id : -1
|
|
345
|
+
},
|
|
346
|
+
storage_service
|
|
347
|
+
)
|
|
348
|
+
rescue StandardError => e
|
|
349
|
+
LoggerService.log(LogLevelEnum::ERROR, "ERROR_STORING_DATA_IN_STORAGE", { err: e.message, an: ApiEnum::GET_FLAG, sId: context.get_session_id, uuid: context.get_uuid})
|
|
350
|
+
end
|
|
344
351
|
return winner_campaign if called_campaign_ids.include?(winner_campaign.id)
|
|
345
352
|
else
|
|
346
353
|
LoggerService.log(LogLevelEnum::INFO, "No winner campaign found for MEG group: #{group_id}, using advanced algorithm", nil)
|