wingify-fme-ruby-sdk 1.50.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 (88) hide show
  1. checksums.yaml +7 -0
  2. data/lib/resources/debug_messages.json +21 -0
  3. data/lib/resources/error_messages.json +63 -0
  4. data/lib/resources/info_messages.json +43 -0
  5. data/lib/resources/warn_messages.json +1 -0
  6. data/lib/vwo.rb +40 -0
  7. data/lib/wingify/api/get_flag.rb +244 -0
  8. data/lib/wingify/api/set_attribute.rb +57 -0
  9. data/lib/wingify/api/track_event.rb +80 -0
  10. data/lib/wingify/constants/constants.rb +106 -0
  11. data/lib/wingify/decorators/storage_decorator.rb +82 -0
  12. data/lib/wingify/enums/api_enum.rb +23 -0
  13. data/lib/wingify/enums/campaign_type_enum.rb +19 -0
  14. data/lib/wingify/enums/debug_category_enum.rb +20 -0
  15. data/lib/wingify/enums/decision_types_enum.rb +18 -0
  16. data/lib/wingify/enums/event_enum.rb +22 -0
  17. data/lib/wingify/enums/headers_enum.rb +20 -0
  18. data/lib/wingify/enums/hooks_enum.rb +17 -0
  19. data/lib/wingify/enums/http_method_enum.rb +18 -0
  20. data/lib/wingify/enums/log_level_enum.rb +21 -0
  21. data/lib/wingify/enums/log_level_to_number.rb +27 -0
  22. data/lib/wingify/enums/status_enum.rb +19 -0
  23. data/lib/wingify/enums/storage_enum.rb +22 -0
  24. data/lib/wingify/enums/url_enum.rb +22 -0
  25. data/lib/wingify/models/campaign/campaign_model.rb +192 -0
  26. data/lib/wingify/models/campaign/feature_model.rb +111 -0
  27. data/lib/wingify/models/campaign/impact_campaign_model.rb +38 -0
  28. data/lib/wingify/models/campaign/metric_model.rb +44 -0
  29. data/lib/wingify/models/campaign/rule_model.rb +56 -0
  30. data/lib/wingify/models/campaign/variable_model.rb +51 -0
  31. data/lib/wingify/models/campaign/variation_model.rb +137 -0
  32. data/lib/wingify/models/gateway_service_model.rb +39 -0
  33. data/lib/wingify/models/schemas/settings_schema_validation.rb +104 -0
  34. data/lib/wingify/models/settings/settings_model.rb +101 -0
  35. data/lib/wingify/models/storage/storage_data_model.rb +44 -0
  36. data/lib/wingify/models/user/context_model.rb +154 -0
  37. data/lib/wingify/models/user/context_vwo_model.rb +38 -0
  38. data/lib/wingify/models/user/get_flag_response.rb +50 -0
  39. data/lib/wingify/models/vwo_options_model.rb +129 -0
  40. data/lib/wingify/packages/decision_maker/decision_maker.rb +60 -0
  41. data/lib/wingify/packages/logger/core/log_manager.rb +92 -0
  42. data/lib/wingify/packages/logger/core/transport_manager.rb +76 -0
  43. data/lib/wingify/packages/logger/log_message_builder.rb +70 -0
  44. data/lib/wingify/packages/logger/logger.rb +38 -0
  45. data/lib/wingify/packages/logger/transports/console_transport.rb +49 -0
  46. data/lib/wingify/packages/network_layer/client/network_client.rb +276 -0
  47. data/lib/wingify/packages/network_layer/handlers/request_handler.rb +37 -0
  48. data/lib/wingify/packages/network_layer/manager/network_manager.rb +145 -0
  49. data/lib/wingify/packages/network_layer/models/global_request_model.rb +105 -0
  50. data/lib/wingify/packages/network_layer/models/request_model.rb +179 -0
  51. data/lib/wingify/packages/network_layer/models/response_model.rb +62 -0
  52. data/lib/wingify/packages/segmentation_evaluator/core/segmentation_manager.rb +77 -0
  53. data/lib/wingify/packages/segmentation_evaluator/enums/segment_operand_regex_enum.rb +29 -0
  54. data/lib/wingify/packages/segmentation_evaluator/enums/segment_operand_value_enum.rb +26 -0
  55. data/lib/wingify/packages/segmentation_evaluator/enums/segment_operator_value_enum.rb +33 -0
  56. data/lib/wingify/packages/segmentation_evaluator/evaluators/segment_evaluator.rb +218 -0
  57. data/lib/wingify/packages/segmentation_evaluator/evaluators/segment_operand_evaluator.rb +415 -0
  58. data/lib/wingify/packages/segmentation_evaluator/utils/segment_util.rb +44 -0
  59. data/lib/wingify/packages/storage/connector.rb +26 -0
  60. data/lib/wingify/packages/storage/storage.rb +47 -0
  61. data/lib/wingify/services/batch_event_queue.rb +179 -0
  62. data/lib/wingify/services/campaign_decision_service.rb +161 -0
  63. data/lib/wingify/services/hooks_service.rb +51 -0
  64. data/lib/wingify/services/logger_service.rb +114 -0
  65. data/lib/wingify/services/settings_service.rb +178 -0
  66. data/lib/wingify/services/storage_service.rb +66 -0
  67. data/lib/wingify/utils/batch_event_dispatcher_util.rb +178 -0
  68. data/lib/wingify/utils/brand_context.rb +33 -0
  69. data/lib/wingify/utils/brand_util.rb +53 -0
  70. data/lib/wingify/utils/campaign_util.rb +284 -0
  71. data/lib/wingify/utils/data_type_util.rb +105 -0
  72. data/lib/wingify/utils/debugger_service_util.rb +40 -0
  73. data/lib/wingify/utils/decision_util.rb +259 -0
  74. data/lib/wingify/utils/event_util.rb +55 -0
  75. data/lib/wingify/utils/function_util.rb +141 -0
  76. data/lib/wingify/utils/gateway_service_util.rb +101 -0
  77. data/lib/wingify/utils/impression_util.rb +66 -0
  78. data/lib/wingify/utils/log_message_util.rb +42 -0
  79. data/lib/wingify/utils/meg_util.rb +357 -0
  80. data/lib/wingify/utils/network_util.rb +503 -0
  81. data/lib/wingify/utils/rule_evaluation_util.rb +57 -0
  82. data/lib/wingify/utils/settings_util.rb +38 -0
  83. data/lib/wingify/utils/usage_stats_util.rb +119 -0
  84. data/lib/wingify/utils/uuid_util.rb +96 -0
  85. data/lib/wingify/wingify_builder.rb +261 -0
  86. data/lib/wingify/wingify_client.rb +227 -0
  87. data/lib/wingify.rb +117 -0
  88. metadata +327 -0
@@ -0,0 +1,44 @@
1
+ # Copyright 2024-2026 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 '../user/context_model'
16
+
17
+ class StorageDataModel
18
+ attr_accessor :feature_key, :context, :rollout_id, :rollout_key, :rollout_variation_id,
19
+ :experiment_id, :experiment_key, :experiment_variation_id
20
+
21
+ def initialize
22
+ @feature_key = ''
23
+ @context = nil
24
+ @rollout_id = nil
25
+ @rollout_key = ''
26
+ @rollout_variation_id = nil
27
+ @experiment_id = nil
28
+ @experiment_key = ''
29
+ @experiment_variation_id = nil
30
+ end
31
+
32
+ # Creates a model instance from a hash (dictionary)
33
+ def model_from_dictionary(storage_data)
34
+ @feature_key = storage_data[:feature_key]
35
+ @context = storage_data[:context]
36
+ @rollout_id = storage_data[:rollout_id]
37
+ @rollout_key = storage_data[:rollout_key]
38
+ @rollout_variation_id = storage_data[:rollout_variation_id]
39
+ @experiment_id = storage_data[:experiment_id]
40
+ @experiment_key = storage_data[:experiment_key]
41
+ @experiment_variation_id = storage_data[:experiment_variation_id]
42
+ self
43
+ end
44
+ end
@@ -0,0 +1,154 @@
1
+ # Copyright 2024-2026 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 './context_vwo_model'
16
+ require_relative '../../utils/uuid_util'
17
+ require_relative '../../services/settings_service'
18
+
19
+ class ContextModel
20
+ attr_accessor :id, :user_agent, :ip_address, :custom_variables, :variation_targeting_variables, :post_segmentation_variables, :vwo, :session_id, :uuid, :bucketing_seed
21
+
22
+ def initialize(id = nil, user_agent = nil, ip_address = nil, custom_variables = {}, variation_targeting_variables = {}, post_segmentation_variables = {}, vwo = nil, session_id = nil, uuid = nil, bucketing_seed = nil)
23
+ @id = id
24
+ @user_agent = user_agent
25
+ @ip_address = ip_address
26
+ @custom_variables = custom_variables || {}
27
+ @variation_targeting_variables = variation_targeting_variables || {}
28
+ @post_segmentation_variables = post_segmentation_variables || {}
29
+ @vwo = vwo
30
+ @session_id = session_id
31
+ @uuid = uuid
32
+ @bucketing_seed = bucketing_seed
33
+ end
34
+
35
+ # Creates a model instance from a hash (dictionary)
36
+ def model_from_dictionary(context)
37
+ if context.key?(:customVariables) && !context[:customVariables].is_a?(Hash)
38
+ raise TypeError, 'Invalid context, customVariables should be a hash'
39
+ end
40
+
41
+ if context.key?(:userAgent) && !context[:userAgent].is_a?(String)
42
+ raise TypeError, 'Invalid context, userAgent should be a string'
43
+ end
44
+
45
+ if context.key?(:ipAddress) && !context[:ipAddress].is_a?(String)
46
+ raise TypeError, 'Invalid context, ipAddress should be a string'
47
+ end
48
+
49
+ @id = context[:id]
50
+ @user_agent = context[:userAgent]
51
+ @ip_address = context[:ipAddress]
52
+ @custom_variables = context[:customVariables] if context.key?(:customVariables)
53
+ @variation_targeting_variables = context[:variationTargetingVariables] if context.key?(:variationTargetingVariables)
54
+ @post_segmentation_variables = context[:postSegmentationVariables] if context.key?(:postSegmentationVariables)
55
+ @vwo = ContextVWOModel.new.model_from_dictionary(context[:_vwo]) if context.key?(:_vwo)
56
+ @bucketing_seed = context[:bucketingSeed].to_s if context.key?(:bucketingSeed)
57
+
58
+ # check if sessionId is present in context and should be non null and non empty
59
+ if context.key?(:sessionId) && !context[:sessionId].nil? && !context[:sessionId].to_s.empty?
60
+ @session_id = context[:sessionId].to_i
61
+ else
62
+ @session_id = Time.now.to_i
63
+ end
64
+
65
+ # check if uuid is present in context and should be non null and non empty string
66
+ if context.key?(:uuid) && context[:uuid].is_a?(String) && !context[:uuid].empty?
67
+ @uuid = context[:uuid]
68
+ else
69
+ @uuid = UUIDUtil.get_uuid(id.to_s, SettingsService.instance.account_id.to_s)
70
+ end
71
+
72
+ self
73
+ end
74
+
75
+ def get_id
76
+ @id
77
+ end
78
+
79
+ def set_id(id)
80
+ @id = id
81
+ end
82
+
83
+ def get_user_agent
84
+ @user_agent
85
+ end
86
+
87
+ def set_user_agent(user_agent)
88
+ @user_agent = user_agent
89
+ end
90
+
91
+ def get_ip_address
92
+ @ip_address
93
+ end
94
+
95
+ def set_ip_address(ip_address)
96
+ @ip_address = ip_address
97
+ end
98
+
99
+ def get_custom_variables
100
+ @custom_variables
101
+ end
102
+
103
+ def set_custom_variables(custom_variables)
104
+ @custom_variables = custom_variables
105
+ end
106
+
107
+ def get_variation_targeting_variables
108
+ @variation_targeting_variables
109
+ end
110
+
111
+ def set_variation_targeting_variables(variation_targeting_variables)
112
+ @variation_targeting_variables = variation_targeting_variables
113
+ end
114
+
115
+ def get_post_segmentation_variables
116
+ @post_segmentation_variables
117
+ end
118
+
119
+ def set_post_segmentation_variables(post_segmentation_variables)
120
+ @post_segmentation_variables = post_segmentation_variables
121
+ end
122
+
123
+ def get_vwo
124
+ @vwo
125
+ end
126
+
127
+ def set_vwo(vwo)
128
+ @vwo = vwo
129
+ end
130
+
131
+ def get_session_id
132
+ @session_id
133
+ end
134
+
135
+ def set_session_id(session_id)
136
+ @session_id = session_id
137
+ end
138
+
139
+ def get_uuid
140
+ @uuid
141
+ end
142
+
143
+ def set_uuid(uuid)
144
+ @uuid = uuid
145
+ end
146
+
147
+ def get_bucketing_seed
148
+ @bucketing_seed
149
+ end
150
+
151
+ def set_bucketing_seed(bucketing_seed)
152
+ @bucketing_seed = bucketing_seed
153
+ end
154
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright 2024-2026 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 ContextVWOModel
16
+ attr_accessor :location, :user_agent
17
+
18
+ def initialize(location = {}, user_agent = {})
19
+ @location = location
20
+ @user_agent = user_agent
21
+ end
22
+
23
+ # Creates a model instance from a hash (dictionary)
24
+ def model_from_dictionary(context)
25
+ @location = context["location"] if context.key?("location")
26
+ @user_agent = context["userAgent"] if context.key?("userAgent")
27
+ self
28
+ end
29
+
30
+ def get_location
31
+ @location
32
+ end
33
+
34
+ def get_ua_info
35
+ @user_agent
36
+ end
37
+ end
38
+
@@ -0,0 +1,50 @@
1
+ # Copyright 2024-2026 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 GetFlagResponse
16
+ attr_reader :is_enabled, :get_variables, :get_variable, :get_uuid, :get_session_id
17
+
18
+ def initialize(is_enabled, variables = [], uuid = nil, session_id = nil)
19
+ @is_enabled = is_enabled
20
+ @variables = variables
21
+ @uuid = uuid
22
+ @session_id = session_id
23
+ end
24
+
25
+ # Define method for is_enabled
26
+ def is_enabled
27
+ @is_enabled
28
+ end
29
+
30
+ # Define method for get_variables
31
+ def get_variables
32
+ @variables
33
+ end
34
+
35
+ # Define method for get_variable
36
+ def get_variable(key, default_value = nil)
37
+ variable = @variables.find { |var| var.key == key }
38
+ variable ? variable.value : default_value
39
+ end
40
+
41
+ # Define method for get_uuid
42
+ def get_uuid
43
+ @uuid
44
+ end
45
+
46
+ # Define method for get_session_id
47
+ def get_session_id
48
+ @session_id
49
+ end
50
+ end
@@ -0,0 +1,129 @@
1
+ # Copyright 2024-2026 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 VWOOptionsModel
16
+ attr_accessor :account_id, :sdk_key, :is_development_mode, :storage, :gateway_service,
17
+ :poll_interval, :logger, :segmentation, :integrations, :network,
18
+ :should_wait_for_tracking_calls, :settings, :vwo_builder, :is_usage_stats_disabled, :_vwo_meta,
19
+ :retry_config, :proxy_url
20
+
21
+ def initialize(options = {})
22
+ @account_id = options[:account_id]
23
+ @sdk_key = options[:sdk_key]
24
+ @is_development_mode = options[:is_development_mode]
25
+ @storage = options[:storage]
26
+ @gateway_service = options[:gateway_service]
27
+ @poll_interval = options[:poll_interval]
28
+ @logger = options[:logger]
29
+ @segmentation = options[:segmentation]
30
+ @integrations = options[:integrations]
31
+ @network = options[:network]
32
+ @should_wait_for_tracking_calls = options[:should_wait_for_tracking_calls]
33
+ @settings = options[:settings]
34
+ @vwo_builder = options[:vwo_builder]
35
+ @is_usage_stats_disabled = options[:is_usage_stats_disabled]
36
+ @_vwo_meta = options[:_vwo_meta]
37
+ @retry_config = options[:retry_config]
38
+ @proxy_url = options[:proxy_url]
39
+ end
40
+
41
+ # Creates a model instance from a hash (dictionary)
42
+ def model_from_dictionary(options)
43
+ @account_id = options[:account_id]
44
+ @sdk_key = options[:sdk_key]
45
+ @vwo_builder = options[:vwo_builder]
46
+
47
+ @should_wait_for_tracking_calls = options[:should_wait_for_tracking_calls] if options.key?(:should_wait_for_tracking_calls)
48
+ @is_development_mode = options[:is_development_mode] if options.key?(:is_development_mode)
49
+ @storage = options[:storage] if options.key?(:storage)
50
+ @gateway_service = options[:gateway_service] if options.key?(:gateway_service)
51
+ @poll_interval = options[:poll_interval] if options.key?(:poll_interval)
52
+ @logger = options[:logger] if options.key?(:logger)
53
+ @segmentation = options[:segmentation] if options.key?(:segmentation)
54
+ @integrations = options[:integrations] if options.key?(:integrations)
55
+ @network = options[:network] if options.key?(:network)
56
+ @settings = options[:settings] if options.key?(:settings)
57
+ @retry_config = options[:retry_config] if options.key?(:retry_config)
58
+ @proxy_url = options[:proxy_url] if options.key?(:proxy_url)
59
+ self
60
+ end
61
+
62
+ def get_account_id
63
+ @account_id
64
+ end
65
+
66
+ def get_sdk_key
67
+ @sdk_key
68
+ end
69
+
70
+ def get_is_development_mode
71
+ @is_development_mode
72
+ end
73
+
74
+ def get_storage
75
+ @storage
76
+ end
77
+
78
+ def get_gateway_service
79
+ @gateway_service
80
+ end
81
+
82
+ def get_poll_interval
83
+ @poll_interval
84
+ end
85
+
86
+ def get_logger
87
+ @logger
88
+ end
89
+
90
+ def get_segmentation
91
+ @segmentation
92
+ end
93
+
94
+ def get_integrations
95
+ @integrations
96
+ end
97
+
98
+ def get_network
99
+ @network
100
+ end
101
+
102
+ def get_should_wait_for_tracking_calls
103
+ @should_wait_for_tracking_calls
104
+ end
105
+
106
+ def get_settings
107
+ @settings
108
+ end
109
+
110
+ def get_vwo_builder
111
+ @vwo_builder
112
+ end
113
+
114
+ def get_is_usage_stats_disabled
115
+ @is_usage_stats_disabled
116
+ end
117
+
118
+ def get_vwo_meta
119
+ @_vwo_meta
120
+ end
121
+
122
+ def get_retry_config
123
+ @retry_config
124
+ end
125
+
126
+ def get_proxy_url
127
+ @proxy_url
128
+ end
129
+ end
@@ -0,0 +1,60 @@
1
+ # Copyright 2024-2026 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 'murmurhash3'
16
+
17
+ class DecisionMaker
18
+ SEED_VALUE = 1 # Seed value for the hash function
19
+
20
+ # Generates a bucket value based on the hash value, maximum value, and an optional multiplier.
21
+ #
22
+ # @param hash_value [Integer] The hash value used for calculation.
23
+ # @param max_value [Integer] The maximum value for bucket scaling.
24
+ # @param multiplier [Integer] Optional multiplier to adjust the value (default: 1).
25
+ # @return [Integer] The calculated bucket value.
26
+ def generate_bucket_value(hash_value, max_value, multiplier = 1)
27
+ ratio = hash_value.to_f / (2**32)
28
+ multiplied_value = ((max_value * ratio) + 1) * multiplier
29
+ multiplied_value.floor
30
+ end
31
+
32
+ # Gets the bucket value for a user based on the hash key and maximum value.
33
+ #
34
+ # @param hash_key [String] The hash key for the user.
35
+ # @param max_value [Integer] The maximum value for bucket scaling (default: 100).
36
+ # @return [Integer] The calculated bucket value for the user.
37
+ def get_bucket_value_for_user(hash_key, max_value = 100)
38
+ hash_value = MurmurHash3::V32.str_hash(hash_key, SEED_VALUE)
39
+ generate_bucket_value(hash_value, max_value)
40
+ end
41
+
42
+ # Calculates the bucket value for a given string with an optional multiplier and maximum value.
43
+ #
44
+ # @param str [String] The input string to calculate the bucket value for.
45
+ # @param multiplier [Integer] Optional multiplier to adjust the value (default: 1).
46
+ # @param max_value [Integer] The maximum value for bucket scaling (default: 10000).
47
+ # @return [Integer] The calculated bucket value.
48
+ def calculate_bucket_value(str, multiplier = 1, max_value = 10000)
49
+ hash_value = generate_hash_value(str)
50
+ generate_bucket_value(hash_value, max_value, multiplier)
51
+ end
52
+
53
+ # Generates the hash value for a given hash key using MurmurHash v3.
54
+ #
55
+ # @param hash_key [String] The hash key for which the hash value is generated.
56
+ # @return [Integer] The generated hash value.
57
+ def generate_hash_value(hash_key)
58
+ MurmurHash3::V32.str_hash(hash_key, SEED_VALUE)
59
+ end
60
+ end
@@ -0,0 +1,92 @@
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
+ # log_manager.rb
16
+ require 'securerandom'
17
+ require_relative '../logger'
18
+ require_relative 'transport_manager'
19
+ require_relative '../transports/console_transport'
20
+ require_relative '../../../enums/log_level_enum'
21
+
22
+ class LogManager < VWOLogger
23
+ @instance = nil
24
+
25
+ # Use the `instance` method to initialize and get the instance
26
+ def self.instance(config = {})
27
+ # If an instance already exists, return it
28
+ if @instance.nil?
29
+ @instance = new(config)
30
+ end
31
+ @instance
32
+ end
33
+
34
+ def initialize(config = {})
35
+ # Store the config in an instance variable
36
+ @config = config
37
+
38
+ # Initialize default config values inside @config
39
+ @config[:name] ||= 'VWO Logger'
40
+ @config[:request_id] ||= SecureRandom.uuid
41
+ @config[:level] ||= 'ERROR'
42
+ @config[:prefix] ||= 'VWO-SDK'
43
+ @config[:date_time_format] ||= lambda { Time.now.iso8601 }
44
+
45
+ # Initialize the transport manager with the @config hash
46
+ @transport_manager = LogTransportManager.new(@config)
47
+ handle_transports
48
+ end
49
+
50
+ def trace(message)
51
+ @transport_manager.log('TRACE', message)
52
+ end
53
+
54
+ def debug(message)
55
+ @transport_manager.log('DEBUG', message)
56
+ end
57
+
58
+ def info(message)
59
+ @transport_manager.log('INFO', message)
60
+ end
61
+
62
+ def warn(message)
63
+ @transport_manager.log('WARN', message)
64
+ end
65
+
66
+ def error(message, extraData = {})
67
+ @transport_manager.log('ERROR', message)
68
+ # sendLogToVWO(message, LogLevelEnum::ERROR, extraData)
69
+ end
70
+
71
+ private
72
+
73
+ def handle_transports
74
+ transports = @config[:transports] || []
75
+
76
+ if transports.any?
77
+ add_transports(transports)
78
+ elsif @config[:transport]
79
+ add_transport(@config[:transport])
80
+ else
81
+ add_transport(ConsoleTransport.new(level: @config[:level], prefix: @config[:prefix]))
82
+ end
83
+ end
84
+
85
+ def add_transport(transport)
86
+ @transport_manager.add_transport(transport)
87
+ end
88
+
89
+ def add_transports(transports)
90
+ transports.each { |transport| add_transport(transport) }
91
+ end
92
+ end
@@ -0,0 +1,76 @@
1
+ # Copyright 2024-2026 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 '../log_message_builder'
16
+ require_relative '../../../enums/log_level_to_number'
17
+
18
+ class LogTransportManager
19
+ def initialize(config)
20
+ @transports = []
21
+ @config = config # This should be the global config passed to LogManager
22
+ end
23
+
24
+ def add_transport(transport)
25
+ @transports.push(transport)
26
+ end
27
+
28
+ def should_log?(transport_level, config_level)
29
+ target_level = LogLevelToNumber.to_number(transport_level)
30
+ desired_level = LogLevelToNumber.to_number(config_level || @config[:level])
31
+ target_level >= desired_level
32
+ end
33
+
34
+ def trace(message)
35
+ log('TRACE', message)
36
+ end
37
+
38
+ def debug(message)
39
+ log('DEBUG', message)
40
+ end
41
+
42
+ def info(message)
43
+ log('INFO', message)
44
+ end
45
+
46
+ def warn(message)
47
+ log('WARN', message)
48
+ end
49
+
50
+ def error(message)
51
+ log('ERROR', message)
52
+ end
53
+
54
+ def log(level, message)
55
+ @transports.each do |transport|
56
+ # Pass the global config (from LogManager) to LogMessageBuilder, not the transport
57
+ log_message_builder = LogMessageBuilder.new(@config, transport)
58
+ formatted_message = log_message_builder.format_message(level, message)
59
+
60
+ if should_log?(level, transport.level)
61
+ if transport.respond_to?(:log) && transport.method(:log).arity == 2
62
+ # Use custom log handler if available with correct arity
63
+ transport.log(level, message)
64
+ elsif transport.respond_to?(level.downcase.to_sym)
65
+ # Use level-specific method if available
66
+ transport.send(level.downcase.to_sym, formatted_message)
67
+ else
68
+ # Fallback to console_log
69
+ transport.console_log(level, formatted_message)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+