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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/resources/error_messages.json +46 -18
  3. data/lib/resources/info_messages.json +4 -2
  4. data/lib/vwo/api/get_flag.rb +13 -8
  5. data/lib/vwo/api/track_event.rb +2 -2
  6. data/lib/vwo/constants/constants.rb +24 -1
  7. data/lib/vwo/decorators/storage_decorator.rb +1 -5
  8. data/lib/vwo/enums/api_enum.rb +7 -3
  9. data/lib/vwo/enums/debug_category_enum.rb +20 -0
  10. data/lib/vwo/enums/event_enum.rb +1 -0
  11. data/lib/vwo/models/user/context_model.rb +36 -2
  12. data/lib/vwo/models/vwo_options_model.rb +14 -3
  13. data/lib/vwo/packages/network_layer/client/network_client.rb +189 -34
  14. data/lib/vwo/packages/network_layer/manager/network_manager.rb +71 -6
  15. data/lib/vwo/packages/network_layer/models/request_model.rb +38 -4
  16. data/lib/vwo/packages/network_layer/models/response_model.rb +10 -1
  17. data/lib/vwo/packages/segmentation_evaluator/core/segmentation_manager.rb +2 -1
  18. data/lib/vwo/packages/segmentation_evaluator/evaluators/segment_evaluator.rb +5 -3
  19. data/lib/vwo/packages/segmentation_evaluator/evaluators/segment_operand_evaluator.rb +3 -2
  20. data/lib/vwo/services/logger_service.rb +21 -1
  21. data/lib/vwo/services/settings_service.rb +37 -9
  22. data/lib/vwo/services/storage_service.rb +5 -4
  23. data/lib/vwo/utils/{batch_event_dispatcher.rb → batch_event_dispatcher_util.rb} +70 -9
  24. data/lib/vwo/utils/campaign_util.rb +35 -0
  25. data/lib/vwo/utils/debugger_service_util.rb +40 -0
  26. data/lib/vwo/utils/event_util.rb +8 -2
  27. data/lib/vwo/utils/function_util.rb +14 -0
  28. data/lib/vwo/utils/gateway_service_util.rb +5 -5
  29. data/lib/vwo/utils/impression_util.rb +16 -2
  30. data/lib/vwo/utils/meg_util.rb +29 -22
  31. data/lib/vwo/utils/network_util.rb +145 -38
  32. data/lib/vwo/utils/rule_evaluation_util.rb +1 -1
  33. data/lib/vwo/vwo_builder.rb +15 -11
  34. data/lib/vwo/vwo_client.rb +11 -25
  35. metadata +5 -4
  36. 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, "SETTINGS_FETCH_ERROR", { err: e.message })
73
- nil
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, "sdkKey is required for fetching account settings. Aborting!", nil)
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, "Error fetching settings: #{e.message}", nil)
119
- raise e
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, "SETTINGS_SCHEMA_INVALID")
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, "STORED_DATA_ERROR", { err: e.message })
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, "STORED_DATA_ERROR", { err: e.message })
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 BatchEventDispatcher
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
- UrlUtil.get_base_url,
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: "#{HttpMethodEnum::POST} #{UrlEnum::BATCH_EVENTS}",
59
- err: err.is_a?(Hash) ? err.to_json : err
81
+ method: extra_data,
82
+ err: get_formatted_error_message(err)
60
83
  })
61
84
  end
62
- end
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
@@ -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
- # send event
48
- NetworkUtil.send_event(properties, payload)
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, "GATEWAY_URL_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
- UrlUtil.get_base_url,
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, "Error fetching from Gateway Service: #{e.message}", nil)
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
@@ -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
- StorageDecorator.new.set_data_in_storage(
253
- {
254
- feature_key: "#{Constants::VWO_META_MEG_KEY}#{group_id}",
255
- context: context,
256
- experiment_id: winner_campaign.id,
257
- experiment_key: winner_campaign.key,
258
- experiment_variation_id: winner_campaign.type == CampaignTypeEnum::PERSONALIZE ? winner_campaign.variations[0].id : -1
259
- },
260
- storage_service
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
- StorageDecorator.new.set_data_in_storage(
334
- {
335
- feature_key: "#{Constants::VWO_META_MEG_KEY}#{group_id}",
336
- context: context,
337
- experiment_id: winner_campaign.id,
338
- experiment_key: winner_campaign.key,
339
- experiment_variation_id: winner_campaign.type == CampaignTypeEnum::PERSONALIZE ? winner_campaign.variations[0].id : -1
340
- },
341
- storage_service
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)