Class: NetworkUtil

Inherits:
Object
  • Object
show all
Defined in:
lib/wingify/utils/network_util.rb

Class Method Summary collapse

Class Method Details

._get_event_base_payload(user_id, event_name, visitor_user_agent = '', ip_address = '', is_usage_stats_event = false, usage_stat_account_id = '') ⇒ Object

Builds base payload for tracking events



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/wingify/utils/network_util.rb', line 109

def _get_event_base_payload(user_id, event_name, visitor_user_agent = '', ip_address = '', is_usage_stats_event = false,  = '')
     = SettingsService.instance.

    if is_usage_stats_event
         = 
    end

    uuid = UUIDUtil.get_uuid(user_id.to_s, .to_s)
    sdk_key = SettingsService.instance.sdk_key

    payload = {
        d: {
            msgId: "#{uuid}-#{get_current_unix_timestamp_in_millis}",
            visId: uuid,
            sessionId: get_current_unix_timestamp,
            event: {
                props: {
                    vwo_sdkName: SettingsService.instance.sdk_name,
                    vwo_sdkVersion: Constants::SDK_VERSION,
                },
                name: event_name,
                time: get_current_unix_timestamp_in_millis
            }
        }
    }

    if !is_usage_stats_event
        # set env key for standard sdk events
        payload[:d][:event][:props][:vwo_envKey] = sdk_key

        # set visitor props for standard sdk events
        payload[:d][:visitor] = {
            props: {
                vwo_fs_environment: sdk_key
            }
        }
    end

    payload
end

.convert_params_to_string(params) ⇒ String

Converts hash map query parameters to URL-encoded query string

Parameters:

  • params (Hash)

    Hash containing query parameters

Returns:

  • (String)

    URL-encoded query string



36
37
38
39
40
41
42
# File 'lib/wingify/utils/network_util.rb', line 36

def convert_params_to_string(params)
  return '' if params.nil? || params.empty?

  '?' + params.map do |key, value|
    "#{URI.encode_www_form_component(key.to_s)}=#{URI.encode_www_form_component(value.to_s)}"
  end.join('&')
end

.create_network_and_retry_debug_event(response, payload, api_name, extra_data) ⇒ Object



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
# File 'lib/wingify/utils/network_util.rb', line 459

def create_network_and_retry_debug_event(response, payload, api_name, extra_data)
  begin
    category = DebugCategoryEnum::RETRY
    msg_t = Constants::NETWORK_CALL_SUCCESS_WITH_RETRIES
    msg = build_message(LoggerService.get_messages(LogLevelEnum::INFO)[msg_t], {
      extraData: extra_data,
      attempts: response.get_total_attempts,
      err: get_formatted_error_message(response.get_error)
    })
    lt = LogLevelEnum::INFO.to_s
    if response.get_status_code != 200
      category = DebugCategoryEnum::NETWORK
      msg_t = Constants::NETWORK_CALL_FAILURE_AFTER_MAX_RETRIES
      msg = build_message(LoggerService.get_messages(LogLevelEnum::ERROR)[msg_t], {
        extraData: extra_data,
        attempts: response.get_total_attempts,
        err: get_formatted_error_message(response.get_error)
      })
      lt = LogLevelEnum::ERROR.to_s
    end
    debug_event_props = {
      cg: category,
      msg_t: msg_t,
      msg: msg,
      lt: lt
    }
    if api_name
      debug_event_props[:an] = api_name
    end

    if payload && payload[:d] && payload[:d][:sessionId]
      debug_event_props[:sId] = payload[:d][:sessionId]
    else
      debug_event_props[:sId] = get_current_unix_timestamp
    end
    debug_event_props
  rescue StandardError => err
    LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
      method: extra_data,
      err: get_formatted_error_message(err)
    })
  end
end

.get_attribute_payload_data(event_name, event_properties, context) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/wingify/utils/network_util.rb', line 238

def get_attribute_payload_data(event_name, event_properties, context)
    properties = _get_event_base_payload(context.id, event_name, context.user_agent, context.ip_address)
    properties[:d][:event][:props][:isCustomEvent] = true

    # use sessionId from context if present
    if context.get_session_id
        properties[:d][:sessionId] = context.get_session_id
    end

    # use uuid from context if present
    if context.get_uuid && !context.get_uuid.empty?
        properties[:d][:visId] = context.get_uuid
        properties[:d][:msgId] = "#{context.get_uuid}-#{get_current_unix_timestamp_in_millis}"
    end

    if event_properties.is_a?(Hash) && !event_properties.empty?
        event_properties.each { |key, value| properties[:d][:visitor][:props][key] = value }
    end

    LoggerService.log(LogLevelEnum::DEBUG, "IMPRESSION_FOR_SYNC_VISITOR_PROP", {
        eventName: event_name,
        accountId: SettingsService.instance.,
        userId: context.id
    })
    properties
end

.get_base_properties_for_bulk(account_id, user_id) ⇒ Object

Returns the base properties for bulk operations



45
46
47
48
49
50
# File 'lib/wingify/utils/network_util.rb', line 45

def get_base_properties_for_bulk(, user_id)
    {
        sId: get_current_unix_timestamp,  # Session ID
        u: UUIDUtil.get_uuid(user_id, )  # UUID based on user and account ID
    }
end

.get_debugger_event_payload(event_props) ⇒ Object

get debugger event payload



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# File 'lib/wingify/utils/network_util.rb', line 429

def get_debugger_event_payload(event_props)
    user_id = SettingsService.instance..to_s + "_" + SettingsService.instance.sdk_key
    properties = _get_event_base_payload(user_id, EventEnum::DEBUGGER_EVENT, nil, nil)
    
    # check if event_props contains uuid key and should be non null and non empty string
    if event_props.key?(:uuid) && event_props[:uuid].is_a?(String) && !event_props[:uuid].empty?
        properties[:d][:msgId] = "#{event_props[:uuid]}-#{get_current_unix_timestamp_in_millis}"
        properties[:d][:visId] = event_props[:uuid]
    else
        event_props[:uuid] = properties[:d][:visId]
    end

    # check if event_props contains sessionId key 
    if event_props.key?(:sId)
        properties[:d][:sessionId] = event_props[:sId]
    else
        event_props[:sId] = properties[:d][:sessionId]
    end

    event_props[:a] = SettingsService.instance..to_s
    event_props[:product] = Constants::PRODUCT_NAME
    event_props[:sn] = SettingsService.instance.sdk_name
    event_props[:sv] = Constants::SDK_VERSION
    event_props[:eventId] = UUIDUtil.get_random_uuid(SettingsService.instance.sdk_key)

    properties[:d][:event][:props] = {}
    properties[:d][:event][:props][:vwoMeta] = event_props
    properties
end

.get_event_batching_query_params(account_id) ⇒ Object

Returns query params for event batching



77
78
79
80
81
82
83
# File 'lib/wingify/utils/network_util.rb', line 77

def get_event_batching_query_params()
    {
    a: ,  # Account ID
    sd: SettingsService.instance.sdk_name,  # SDK Name
    sv: Constants::SDK_VERSION  # SDK Version
    }
end

.get_events_base_properties(event_name, visitor_user_agent = '', ip_address = '', is_usage_stats_event = false, usage_stat_account_id = '') ⇒ Object

Builds generic properties for different tracking calls



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/wingify/utils/network_util.rb', line 86

def get_events_base_properties(event_name, visitor_user_agent = '', ip_address = '', is_usage_stats_event = false,  = '')
    properties = {
        en: event_name,
        a: SettingsService.instance.,
        eTime: get_current_unix_timestamp_in_millis,
        random: get_random_number,
        p: 'FS',
        visitor_ua: visitor_user_agent || '',
        visitor_ip: ip_address || ''
    }

    if !is_usage_stats_event
        # set env key for standard sdk events
        properties[:env] = SettingsService.instance.sdk_key
    else
        # set env key for usage stats events
        properties[:a] = 
    end

    properties
end

.get_sdk_init_event_payload(event_name, settings_fetch_time, sdk_init_time) ⇒ Object

Constructs the payload for init called event.

Parameters:

  • event_name
    • The name of the event.

  • settings_fetch_time
    • Time taken to fetch settings in milliseconds.

  • sdk_init_time
    • Time taken to initialize the SDK in milliseconds.



270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/wingify/utils/network_util.rb', line 270

def get_sdk_init_event_payload(event_name, settings_fetch_time, sdk_init_time)
    user_id = SettingsService.instance..to_s + "_" + SettingsService.instance.sdk_key
    properties = _get_event_base_payload(user_id, event_name, nil, nil)
    properties[:d][:event][:props][:vwo_fs_environment] = SettingsService.instance.sdk_key
    properties[:d][:event][:props][:product] = Constants::PRODUCT_NAME
    data = {
        "isSDKInitialized": true,
        "settingsFetchTime": settings_fetch_time,
        "sdkInitTime": sdk_init_time
    }
    properties[:d][:event][:props][:data] = data
    properties
end

.get_sdk_usage_stats_payload_data(event_name, usage_stats_account_id) ⇒ Object

Constructs the payload for usage stats called event.

Parameters:

  • event_name
    • The name of the event.

  • usage_stats_account_id
    • The account id for usage stats.



288
289
290
291
292
293
294
# File 'lib/wingify/utils/network_util.rb', line 288

def get_sdk_usage_stats_payload_data(event_name, )
    user_id = SettingsService.instance..to_s + "_" + SettingsService.instance.sdk_key
    properties = _get_event_base_payload(user_id, event_name, nil, nil, true, )
    properties[:d][:event][:props][:product] = Constants::PRODUCT_NAME
    properties[:d][:event][:props][:vwoMeta] = UsageStatsUtil.get_usage_stats
    properties
end

.get_settings_path(sdk_key, account_id) ⇒ Object

Returns settings path with sdkKey and accountId



53
54
55
56
57
58
59
# File 'lib/wingify/utils/network_util.rb', line 53

def get_settings_path(sdk_key, )
    {
        i: sdk_key,  # API key
        r: rand,     # Random number for cache busting
        a:   # Account ID
    }
end

.get_track_event_path(event, account_id, user_id) ⇒ Object

Returns the event tracking path



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/wingify/utils/network_util.rb', line 62

def get_track_event_path(event, , user_id)
    {
    event_type: event,  # Type of event
    account_id: ,  # Account ID
    uId: user_id,  # User ID
    u: UUIDUtil.get_uuid(user_id, ),  # UUID for user
    sdk: SettingsService.instance.sdk_name,  # SDK Name
    'sdk-v': Constants::SDK_VERSION,  # SDK Version
    random: get_random_number,  # Random number for uniqueness
    sId: get_current_unix_timestamp,  # Session ID
    ed: JSON.generate({ p: 'server' })  # Additional encoded data
    }
end

.get_track_goal_payload_data(event_name, event_properties, context) ⇒ Object

Constructs payload for tracking goals with custom event properties



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/wingify/utils/network_util.rb', line 205

def get_track_goal_payload_data(event_name, event_properties, context)
    properties = _get_event_base_payload(context.id, event_name, context.user_agent, context.ip_address)
    properties[:d][:event][:props][:isCustomEvent] = true

    # use sessionId from context if present
    if context.get_session_id
        properties[:d][:sessionId] = context.get_session_id
    end

    # use uuid from context if present
    if context.get_uuid && !context.get_uuid.empty?
        properties[:d][:visId] = context.get_uuid
        properties[:d][:msgId] = "#{context.get_uuid}-#{get_current_unix_timestamp_in_millis}"
    end

    if SettingsService.instance.is_gateway_service_provided
        properties[:d][:event][:props][:variation] = 1
        properties[:d][:event][:props][:id] = 1  # Temporary value for ID
    end

    if event_properties.is_a?(Hash) && !event_properties.empty?
    event_properties.each { |key, value| properties[:d][:event][:props][key] = value }
    end

    LoggerService.log(LogLevelEnum::DEBUG, "IMPRESSION_FOR_TRACK_GOAL", {
        eventName: event_name,
        accountId: SettingsService.instance.,
        userId: context.id
    })

    properties
end

.get_track_user_payload_data(event_name, campaign_id, variation_id, context) ⇒ Object

Builds track-user payload data



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/wingify/utils/network_util.rb', line 151

def get_track_user_payload_data(event_name, campaign_id, variation_id, context)
    user_id = context.get_id
    visitor_user_agent = context.get_user_agent
    ip_address = context.get_ip_address
    custom_variables = context.get_custom_variables
    post_segmentation_variables = context.get_post_segmentation_variables

    properties = _get_event_base_payload(user_id, event_name, visitor_user_agent, ip_address)

    # use sessionId from context if present
    if context.get_session_id
        properties[:d][:sessionId] = context.get_session_id
    end

    # use uuid from context if present
    if context.get_uuid && !context.get_uuid.empty?
        properties[:d][:visId] = context.get_uuid
        properties[:d][:msgId] = "#{context.get_uuid}-#{get_current_unix_timestamp_in_millis}"
    end

    properties[:d][:event][:props][:id] = campaign_id
    properties[:d][:event][:props][:variation] = variation_id
    properties[:d][:event][:props][:isFirst] = 1

    # Only add visitor_ua and visitor_ip if they are non-null
    properties[:d][:visitor_ua] = visitor_user_agent if visitor_user_agent && !visitor_user_agent.empty?
    properties[:d][:visitor_ip] = ip_address if ip_address && !ip_address.empty?

    # Add post-segmentation variables if they exist in custom variables
    if post_segmentation_variables&.any? && custom_variables&.any?
        post_segmentation_variables.each do |key|
            # Try to get value using string key first, then symbol key
            value = custom_variables[key] || custom_variables[key.to_sym]
            if value
                properties[:d][:visitor][:props][key] = value
            end
        end
    end

    # Add IP address as a standard attribute if available
    if ip_address && !ip_address.empty?
      properties[:d][:visitor][:props][:ip] = ip_address
    end

    LoggerService.log(LogLevelEnum::DEBUG, "IMPRESSION_FOR_TRACK_USER", {
        accountId: SettingsService.instance.,
        userId: user_id,
        campaignId: campaign_id
    })

    properties
end

.send_event(properties, payload) ⇒ Object

Sends an event to VWO (generic event sender).

Parameters:

  • properties
    • Query parameters for the request.

  • payload
    • The payload for the request.

  • event_name
    • The name of the event to send.



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/wingify/utils/network_util.rb', line 375

def send_event(properties, payload)
    network_instance = NetworkManager.instance
    headers = {}
    headers[HeadersEnum::USER_AGENT] = payload[:d][:visitor_ua] if payload[:d][:visitor_ua]
    headers[HeadersEnum::IP] = payload[:d][:visitor_ip] if payload[:d][:visitor_ip]

    request = RequestModel.new(
        SettingsService.instance.events_hostname,
        HttpMethodEnum::POST,
        SettingsService.instance.get_updated_endpoint_with_collection_prefix(UrlEnum::EVENTS, SettingsService.instance.is_gateway_service_provided),
        properties,
        payload,
        headers,
        SettingsService.instance.protocol,
        SettingsService.instance.port,
    )

    begin
        if network_instance.get_client.get_should_use_threading
            network_instance.get_client.get_thread_pool.post {
                response = network_instance.post(request)
                if response.get_status_code == 200
                    LoggerService.log(LogLevelEnum::INFO, "NETWORK_CALL_SUCCESS", {
                        event: properties[:en],
                        endPoint: UrlEnum::EVENTS,
                        accountId: SettingsService.instance.,
                        uuid: request.get_body[:d][:visId]
                    })
                end
                response
            }
        else
            response = network_instance.post(request)
            if response.get_status_code == 200
                LoggerService.log(LogLevelEnum::INFO, "NETWORK_CALL_SUCCESS", {
                    event: properties[:en],
                    endPoint: UrlEnum::EVENTS,
                    accountId: SettingsService.instance.,
                    uuid: request.get_body[:d][:visId]
                })
            end
            response
        end
    rescue ResponseModel => err
        if properties.key?(:en) && properties[:en] != EventEnum::DEBUGGER_EVENT
          LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
            method: "event: #{properties[:en]}",
            err: get_formatted_error_message(err.get_error)
          })
        end
    end
end

.send_post_api_request(properties, payload, campaign_info = {}) ⇒ Object

Sends a POST API request with given properties and payload



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'lib/wingify/utils/network_util.rb', line 297

def send_post_api_request(properties, payload, campaign_info = {})
    network_instance = NetworkManager.instance
    headers = {}
    headers[HeadersEnum::USER_AGENT] = payload[:d][:visitor_ua] if payload[:d][:visitor_ua]
    headers[HeadersEnum::IP] = payload[:d][:visitor_ip] if payload[:d][:visitor_ip]

    request = RequestModel.new(
    SettingsService.instance.events_hostname,
    HttpMethodEnum::POST,
    SettingsService.instance.get_updated_endpoint_with_collection_prefix(UrlEnum::EVENTS, SettingsService.instance.is_gateway_service_provided),
    properties,
    payload,
    headers,
    SettingsService.instance.protocol,
    SettingsService.instance.port
    )
    
    api_name = nil  
    extra_data_for_message = nil
    if properties.key?(:en) && properties[:en] == EventEnum::VARIATION_SHOWN
      api_name = ApiEnum::GET_FLAG
      if campaign_info && campaign_info.key?(:campaign_type) && (campaign_info[:campaign_type] == CampaignTypeEnum::ROLLOUT || campaign_info[:campaign_type] == CampaignTypeEnum::PERSONALIZE)
        extra_data_for_message = "feature: #{campaign_info[:feature_key]}, rule: #{campaign_info[:variation_name]}"
      elsif campaign_info
        extra_data_for_message = "feature: #{campaign_info[:feature_key]}, rule: #{campaign_info[:campaign_key]} and variation: #{campaign_info[:variation_name]}"
      end
    elsif properties.key?(:en) && properties[:en] != EventEnum::VARIATION_SHOWN
      if properties.key?(:en) && properties[:en] == EventEnum::SYNC_VISITOR_PROP
        api_name = ApiEnum::SET_ATTRIBUTE
        extra_data_for_message = api_name
      elsif properties.key?(:en) && properties[:en] != EventEnum::VARIATION_SHOWN && properties[:en] != EventEnum::DEBUGGER_EVENT && properties[:en] != EventEnum::INIT_CALLED
        api_name = ApiEnum::TRACK_EVENT
        extra_data_for_message = "event: #{properties[:en]}"
      end
    end
    begin
        if network_instance.get_client.get_should_use_threading
            network_instance.get_client.get_thread_pool.post {
                response = network_instance.post(request)
                if response.get_total_attempts > 0
                  debug_event_props = create_network_and_retry_debug_event(response, request.get_body, api_name, extra_data_for_message)
                  debug_event_props[:uuid] = request.get_body[:d][:visId]
                  DebuggerServiceUtil.send_debugger_event(debug_event_props)
                end
                if response.get_status_code == 200
                  LoggerService.log(LogLevelEnum::INFO, "NETWORK_CALL_SUCCESS", {
                    event: properties[:en],
                    endPoint: UrlEnum::EVENTS,
                    accountId: SettingsService.instance.,
                    uuid: request.get_body[:d][:visId]
                  })
                end
                response
            }
        else
            response = network_instance.post(request)
            if response.get_status_code == 200
                LoggerService.log(LogLevelEnum::INFO, "NETWORK_CALL_SUCCESS", {
                    event: properties[:en],
                    endPoint: UrlEnum::EVENTS,
                    accountId: SettingsService.instance.,
                    uuid: request.get_body[:d][:visId]
                })
            end
            response
        end
    rescue ResponseModel => err
        LoggerService.log(LogLevelEnum::ERROR, "NETWORK_CALL_FAILED", {
            method: extra_data_for_message,
            err: get_formatted_error_message(err.get_error)
        })
    end
end