statsig 1.30.0 → 1.32.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,3 @@
1
- # typed: true
2
-
3
1
  require 'config_result'
4
2
  require 'evaluator'
5
3
  require 'network'
@@ -13,13 +11,11 @@ require 'dynamic_config'
13
11
  require 'feature_gate'
14
12
  require 'error_boundary'
15
13
  require 'layer'
16
- require 'sorbet-runtime'
14
+
17
15
  require 'diagnostics'
18
16
 
19
17
  class StatsigDriver
20
- extend T::Sig
21
18
 
22
- sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void }
23
19
  def initialize(secret_key, options = nil, error_callback = nil)
24
20
  unless secret_key.start_with?('secret-')
25
21
  raise Statsig::ValueError.new('Invalid secret key provided. Provide your project secret key from the Statsig console')
@@ -31,8 +27,8 @@ class StatsigDriver
31
27
 
32
28
  @err_boundary = Statsig::ErrorBoundary.new(secret_key)
33
29
  @err_boundary.capture(task: lambda {
34
- @diagnostics = Statsig::Diagnostics.new('initialize')
35
- tracker = @diagnostics.track('overall')
30
+ @diagnostics = Statsig::Diagnostics.new()
31
+ tracker = @diagnostics.track('initialize', 'overall')
36
32
  @options = options || StatsigOptions.new
37
33
  @shutdown = false
38
34
  @secret_key = secret_key
@@ -43,101 +39,102 @@ class StatsigDriver
43
39
  @evaluator = Statsig::Evaluator.new(@store, @options, @persistent_storage_utils)
44
40
  tracker.end(success: true)
45
41
 
46
- @logger.log_diagnostics_event(@diagnostics)
42
+ @logger.log_diagnostics_event(@diagnostics, 'initialize')
47
43
  }, caller: __method__.to_s)
48
44
  end
49
45
 
50
- sig do
51
- params(
52
- user: StatsigUser,
53
- gate_name: String,
54
- disable_log_exposure: T::Boolean,
55
- skip_evaluation: T::Boolean
56
- ).returns(FeatureGate)
57
- end
58
- def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: false)
46
+ def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: false, disable_evaluation_details: false)
59
47
  if skip_evaluation
60
48
  gate = @store.get_gate(gate_name)
61
49
  return FeatureGate.new(gate_name) if gate.nil?
62
- return FeatureGate.new(gate['name'], target_app_ids: gate['targetAppIDs'])
50
+ return FeatureGate.new(gate.name, target_app_ids: gate.target_app_ids)
63
51
  end
64
52
  user = verify_inputs(user, gate_name, 'gate_name')
65
53
 
66
- res = @evaluator.check_gate(user, gate_name)
67
- if res.nil?
68
- res = Statsig::ConfigResult.new(gate_name)
69
- end
54
+ res = Statsig::ConfigResult.new(name: gate_name, disable_exposures: disable_log_exposure, disable_evaluation_details: disable_evaluation_details)
55
+ @evaluator.check_gate(user, gate_name, res)
70
56
 
71
- if res == $fetch_from_server
72
- res = check_gate_fallback(user, gate_name)
73
- # exposure logged by the server
74
- else
75
- unless disable_log_exposure
76
- @logger.log_gate_exposure(
77
- user, res.name, res.gate_value, res.rule_id, res.secondary_exposures, res.evaluation_details
78
- )
79
- end
57
+ unless disable_log_exposure
58
+ @logger.log_gate_exposure(
59
+ user, res.name, res.gate_value, res.rule_id, res.secondary_exposures, res.evaluation_details
60
+ )
80
61
  end
81
62
  FeatureGate.from_config_result(res)
82
63
  end
83
64
 
84
- sig { params(user: StatsigUser, gate_name: String, options: Statsig::GetGateOptions).returns(FeatureGate) }
85
- def get_gate(user, gate_name, options = Statsig::GetGateOptions.new)
65
+ def get_gate(user, gate_name, options = nil)
86
66
  @err_boundary.capture(task: lambda {
87
67
  run_with_diagnostics(task: lambda {
88
- get_gate_impl(user, gate_name, disable_log_exposure: options.disable_log_exposure, skip_evaluation: options.skip_evaluation)
68
+ get_gate_impl(user, gate_name,
69
+ disable_log_exposure: options&.disable_log_exposure == true,
70
+ skip_evaluation: options&.skip_evaluation == true,
71
+ disable_evaluation_details: options&.disable_evaluation_details == true
72
+ )
89
73
  }, caller: __method__.to_s)
90
74
  }, recover: -> { false }, caller: __method__.to_s)
91
75
  end
92
76
 
93
- sig { params(user: StatsigUser, gate_name: String, options: Statsig::CheckGateOptions).returns(T::Boolean) }
94
- def check_gate(user, gate_name, options = Statsig::CheckGateOptions.new)
77
+ def check_gate(user, gate_name, options = nil)
95
78
  @err_boundary.capture(task: lambda {
96
79
  run_with_diagnostics(task: lambda {
97
- get_gate_impl(user, gate_name, disable_log_exposure: options.disable_log_exposure).value
80
+ get_gate_impl(
81
+ user,
82
+ gate_name,
83
+ disable_log_exposure: options&.disable_log_exposure == true,
84
+ disable_evaluation_details: options&.disable_evaluation_details == true
85
+ ).value
98
86
  }, caller: __method__.to_s)
99
87
  }, recover: -> { false }, caller: __method__.to_s)
100
88
  end
101
89
 
102
- sig { params(user: StatsigUser, gate_name: String).void }
103
90
  def manually_log_gate_exposure(user, gate_name)
104
91
  @err_boundary.capture(task: lambda {
105
- res = @evaluator.check_gate(user, gate_name)
106
- context = { 'is_manual_exposure' => true }
92
+ res = Statsig::ConfigResult.new(name: gate_name)
93
+ @evaluator.check_gate(user, gate_name, res)
94
+ context = { :is_manual_exposure => true }
107
95
  @logger.log_gate_exposure(user, gate_name, res.gate_value, res.rule_id, res.secondary_exposures, res.evaluation_details, context)
108
96
  })
109
97
  end
110
98
 
111
- sig { params(user: StatsigUser, dynamic_config_name: String, options: Statsig::GetConfigOptions).returns(DynamicConfig) }
112
- def get_config(user, dynamic_config_name, options = Statsig::GetConfigOptions.new)
99
+ def get_config(user, dynamic_config_name, options = nil)
113
100
  @err_boundary.capture(task: lambda {
114
101
  run_with_diagnostics(task: lambda {
115
102
  user = verify_inputs(user, dynamic_config_name, "dynamic_config_name")
116
- get_config_impl(user, dynamic_config_name, options.disable_log_exposure)
103
+ get_config_impl(
104
+ user,
105
+ dynamic_config_name,
106
+ options&.disable_log_exposure == true,
107
+ disable_evaluation_details: options&.disable_evaluation_details == true
108
+ )
117
109
  }, caller: __method__.to_s)
118
110
  }, recover: -> { DynamicConfig.new(dynamic_config_name) }, caller: __method__.to_s)
119
111
  end
120
112
 
121
- sig { params(user: StatsigUser, experiment_name: String, options: Statsig::GetExperimentOptions).returns(DynamicConfig) }
122
- def get_experiment(user, experiment_name, options = Statsig::GetExperimentOptions.new)
113
+ def get_experiment(user, experiment_name, options = nil)
123
114
  @err_boundary.capture(task: lambda {
124
115
  run_with_diagnostics(task: lambda {
125
116
  user = verify_inputs(user, experiment_name, "experiment_name")
126
- get_config_impl(user, experiment_name, options.disable_log_exposure, user_persisted_values: options.user_persisted_values)
117
+ get_config_impl(
118
+ user,
119
+ experiment_name,
120
+ options&.disable_log_exposure == true,
121
+ user_persisted_values: options&.user_persisted_values,
122
+ disable_evaluation_details: options&.disable_evaluation_details == true
123
+ )
127
124
  }, caller: __method__.to_s)
128
125
  }, recover: -> { DynamicConfig.new(experiment_name) }, caller: __method__.to_s)
129
126
  end
130
127
 
131
- sig { params(user: StatsigUser, config_name: String).void }
132
128
  def manually_log_config_exposure(user, config_name)
133
129
  @err_boundary.capture(task: lambda {
134
- res = @evaluator.get_config(user, config_name)
135
- context = { 'is_manual_exposure' => true }
130
+ res = Statsig::ConfigResult.new(name: config_name)
131
+ @evaluator.get_config(user, config_name, res)
132
+
133
+ context = { :is_manual_exposure => true }
136
134
  @logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.evaluation_details, context)
137
135
  }, caller: __method__.to_s)
138
136
  end
139
137
 
140
- sig { params(user: StatsigUser, id_type: String).returns(Statsig::UserPersistedValues) }
141
138
  def get_user_persisted_values(user, id_type)
142
139
  @err_boundary.capture(task: lambda {
143
140
  persisted_values = @persistent_storage_utils.get_user_persisted_values(user, id_type)
@@ -147,39 +144,34 @@ class StatsigDriver
147
144
  }, caller: __method__.to_s)
148
145
  end
149
146
 
150
- sig { params(user: StatsigUser, layer_name: String, options: Statsig::GetLayerOptions).returns(Layer) }
151
- def get_layer(user, layer_name, options = Statsig::GetLayerOptions.new)
147
+ def get_layer(user, layer_name, options = nil)
152
148
  @err_boundary.capture(task: lambda {
153
149
  run_with_diagnostics(task: lambda {
154
150
  user = verify_inputs(user, layer_name, "layer_name")
151
+ exposures_disabled = options&.disable_log_exposure == true
152
+ res = Statsig::ConfigResult.new(
153
+ name: layer_name,
154
+ disable_exposures: exposures_disabled,
155
+ disable_evaluation_details: options&.disable_evaluation_details == true
156
+ )
157
+ @evaluator.get_layer(user, layer_name, res)
155
158
 
156
- res = @evaluator.get_layer(user, layer_name)
157
- if res.nil?
158
- res = Statsig::ConfigResult.new(layer_name)
159
- end
160
-
161
- if res == $fetch_from_server
162
- if res.config_delegate.nil?
163
- return Layer.new(layer_name)
164
- end
165
- res = get_config_fallback(user, res.config_delegate)
166
- # exposure logged by the server
167
- end
168
-
169
- exposure_log_func = !options.disable_log_exposure ? lambda { |layer, parameter_name|
159
+ exposure_log_func = !exposures_disabled ? lambda { |layer, parameter_name|
170
160
  @logger.log_layer_exposure(user, layer, parameter_name, res)
171
161
  } : nil
162
+
172
163
  Layer.new(res.name, res.json_value, res.rule_id, res.group_name, res.config_delegate, exposure_log_func)
173
164
  }, caller: __method__.to_s)
174
165
  }, recover: lambda { Layer.new(layer_name) }, caller: __method__.to_s)
175
166
  end
176
167
 
177
- sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void }
178
168
  def manually_log_layer_parameter_exposure(user, layer_name, parameter_name)
179
169
  @err_boundary.capture(task: lambda {
180
- res = @evaluator.get_layer(user, layer_name)
170
+ res = Statsig::ConfigResult.new(name: layer_name)
171
+ @evaluator.get_layer(user, layer_name, res)
172
+
181
173
  layer = Layer.new(layer_name, res.json_value, res.rule_id, res.group_name, res.config_delegate)
182
- context = { 'is_manual_exposure' => true }
174
+ context = { :is_manual_exposure => true }
183
175
  @logger.log_layer_exposure(user, layer, parameter_name, res, context)
184
176
  }, caller: __method__.to_s)
185
177
  end
@@ -213,35 +205,30 @@ class StatsigDriver
213
205
  }, caller: __method__.to_s)
214
206
  end
215
207
 
216
- sig { returns(T::Array[String]) }
217
208
  def list_gates
218
209
  @err_boundary.capture(task: lambda {
219
210
  @evaluator.list_gates
220
211
  }, caller: __method__.to_s)
221
212
  end
222
213
 
223
- sig { returns(T::Array[String]) }
224
214
  def list_configs
225
215
  @err_boundary.capture(task: lambda {
226
216
  @evaluator.list_configs
227
217
  }, caller: __method__.to_s)
228
218
  end
229
219
 
230
- sig { returns(T::Array[String]) }
231
220
  def list_experiments
232
221
  @err_boundary.capture(task: lambda {
233
222
  @evaluator.list_experiments
234
223
  }, caller: __method__.to_s)
235
224
  end
236
225
 
237
- sig { returns(T::Array[String]) }
238
226
  def list_autotunes
239
227
  @err_boundary.capture(task: lambda {
240
228
  @evaluator.list_autotunes
241
229
  }, caller: __method__.to_s)
242
230
  end
243
231
 
244
- sig { returns(T::Array[String]) }
245
232
  def list_layers
246
233
  @err_boundary.capture(task: lambda {
247
234
  @evaluator.list_layers
@@ -295,8 +282,8 @@ class StatsigDriver
295
282
  def run_with_diagnostics(task:, caller:)
296
283
  diagnostics = nil
297
284
  if Statsig::Diagnostics::API_CALL_KEYS.include?(caller) && Statsig::Diagnostics.sample(1)
298
- diagnostics = Statsig::Diagnostics.new('api_call')
299
- tracker = diagnostics.track(caller)
285
+ diagnostics = Statsig::Diagnostics.new()
286
+ tracker = diagnostics.track('api_call', caller)
300
287
  end
301
288
  begin
302
289
  res = task.call
@@ -305,12 +292,11 @@ class StatsigDriver
305
292
  tracker&.end(success: false)
306
293
  raise e
307
294
  ensure
308
- @logger.log_diagnostics_event(diagnostics)
295
+ @logger.log_diagnostics_event(diagnostics, 'api_call')
309
296
  end
310
297
  return res
311
298
  end
312
299
 
313
- sig { params(user: StatsigUser, config_name: String, variable_name: String).returns(StatsigUser) }
314
300
  def verify_inputs(user, config_name, variable_name)
315
301
  validate_user(user)
316
302
  if !config_name.is_a?(String) || config_name.empty?
@@ -322,27 +308,16 @@ class StatsigDriver
322
308
  normalize_user(user)
323
309
  end
324
310
 
325
- sig do
326
- params(
327
- user: StatsigUser,
328
- config_name: String,
329
- disable_log_exposure: T::Boolean,
330
- user_persisted_values: T.nilable(Statsig::UserPersistedValues)
331
- ).returns(DynamicConfig)
332
- end
333
- def get_config_impl(user, config_name, disable_log_exposure, user_persisted_values: nil)
334
- res = @evaluator.get_config(user, config_name, user_persisted_values: user_persisted_values)
335
- if res.nil?
336
- res = Statsig::ConfigResult.new(config_name)
337
- end
311
+ def get_config_impl(user, config_name, disable_log_exposure, user_persisted_values: nil, disable_evaluation_details: false)
312
+ res = Statsig::ConfigResult.new(
313
+ name: config_name,
314
+ disable_exposures: disable_log_exposure,
315
+ disable_evaluation_details: disable_evaluation_details
316
+ )
317
+ @evaluator.get_config(user, config_name, res, user_persisted_values: user_persisted_values)
338
318
 
339
- if res == $fetch_from_server
340
- res = get_config_fallback(user, config_name)
341
- # exposure logged by the server
342
- else
343
- if !disable_log_exposure
344
- @logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.evaluation_details)
345
- end
319
+ unless disable_log_exposure
320
+ @logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.evaluation_details)
346
321
  end
347
322
 
348
323
  DynamicConfig.new(res.name, res.json_value, res.rule_id, res.group_name, res.id_type, res.evaluation_details)
@@ -372,34 +347,4 @@ class StatsigDriver
372
347
  puts 'SDK has been shutdown. Updates in the Statsig Console will no longer reflect.'
373
348
  end
374
349
  end
375
-
376
- def check_gate_fallback(user, gate_name)
377
- network_result = @net.check_gate(user, gate_name)
378
- if network_result.nil?
379
- config_result = Statsig::ConfigResult.new(gate_name)
380
- return config_result
381
- end
382
-
383
- Statsig::ConfigResult.new(
384
- network_result['name'],
385
- network_result['value'],
386
- {},
387
- network_result['rule_id'],
388
- )
389
- end
390
-
391
- def get_config_fallback(user, dynamic_config_name)
392
- network_result = @net.get_config(user, dynamic_config_name)
393
- if network_result.nil?
394
- config_result = Statsig::ConfigResult.new(dynamic_config_name)
395
- return config_result
396
- end
397
-
398
- Statsig::ConfigResult.new(
399
- network_result['name'],
400
- false,
401
- network_result['value'],
402
- network_result['rule_id'],
403
- )
404
- end
405
350
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+
2
2
  module Statsig
3
3
  class UninitializedError < StandardError
4
4
  def initialize(msg="Must call initialize first.")
data/lib/statsig_event.rb CHANGED
@@ -1,4 +1,4 @@
1
- # typed: true
1
+
2
2
  class StatsigEvent
3
3
  attr_accessor :value, :metadata, :statsig_metadata, :secondary_exposures
4
4
  attr_reader :user
@@ -21,13 +21,13 @@ class StatsigEvent
21
21
 
22
22
  def serialize
23
23
  {
24
- 'eventName' => @event_name,
25
- 'metadata' => @metadata,
26
- 'value' => @value,
27
- 'user' => @user,
28
- 'time' => @time,
29
- 'statsigMetadata' => @statsig_metadata,
30
- 'secondaryExposures' => @secondary_exposures
24
+ :eventName => @event_name,
25
+ :metadata => @metadata,
26
+ :value => @value,
27
+ :user => @user,
28
+ :time => @time,
29
+ :statsigMetadata => @statsig_metadata,
30
+ :secondaryExposures => @secondary_exposures
31
31
  }
32
32
  end
33
33
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ require 'constants'
2
2
  require 'statsig_event'
3
3
  require 'concurrent-ruby'
4
4
 
@@ -6,7 +6,7 @@ $gate_exposure_event = 'statsig::gate_exposure'
6
6
  $config_exposure_event = 'statsig::config_exposure'
7
7
  $layer_exposure_event = 'statsig::layer_exposure'
8
8
  $diagnostics_event = 'statsig::diagnostics'
9
- $ignored_metadata_keys = ['serverTime', 'configSyncTime', 'initTime', 'reason']
9
+ $ignored_metadata_keys = [:serverTime, :configSyncTime, :initTime, :reason]
10
10
  module Statsig
11
11
  class StatsigLogger
12
12
  def initialize(network, options, error_boundary)
@@ -41,9 +41,9 @@ module Statsig
41
41
  event = StatsigEvent.new($gate_exposure_event)
42
42
  event.user = user
43
43
  metadata = {
44
- 'gate' => gate_name,
45
- 'gateValue' => value.to_s,
46
- 'ruleID' => rule_id,
44
+ gate: gate_name,
45
+ gateValue: value.to_s,
46
+ ruleID: rule_id || Statsig::Const::EMPTY_STR,
47
47
  }
48
48
  return false if not is_unique_exposure(user, $gate_exposure_event, metadata)
49
49
  event.metadata = metadata
@@ -59,8 +59,8 @@ module Statsig
59
59
  event = StatsigEvent.new($config_exposure_event)
60
60
  event.user = user
61
61
  metadata = {
62
- 'config' => config_name,
63
- 'ruleID' => rule_id,
62
+ config: config_name,
63
+ ruleID: rule_id || Statsig::Const::EMPTY_STR,
64
64
  }
65
65
  return false if not is_unique_exposure(user, $config_exposure_event, metadata)
66
66
  event.metadata = metadata
@@ -72,8 +72,8 @@ module Statsig
72
72
  end
73
73
 
74
74
  def log_layer_exposure(user, layer, parameter_name, config_evaluation, context = nil)
75
- exposures = config_evaluation.undelegated_sec_exps
76
- allocated_experiment = ''
75
+ exposures = config_evaluation.undelegated_sec_exps || []
76
+ allocated_experiment = Statsig::Const::EMPTY_STR
77
77
  is_explicit = (config_evaluation.explicit_parameters&.include? parameter_name) || false
78
78
  if is_explicit
79
79
  allocated_experiment = config_evaluation.config_delegate
@@ -83,13 +83,13 @@ module Statsig
83
83
  event = StatsigEvent.new($layer_exposure_event)
84
84
  event.user = user
85
85
  metadata = {
86
- 'config' => layer.name,
87
- 'ruleID' => layer.rule_id,
88
- 'allocatedExperiment' => allocated_experiment,
89
- 'parameterName' => parameter_name,
90
- 'isExplicitParameter' => String(is_explicit),
86
+ config: layer.name,
87
+ ruleID: layer.rule_id || Statsig::Const::EMPTY_STR,
88
+ allocatedExperiment: allocated_experiment,
89
+ parameterName: parameter_name,
90
+ isExplicitParameter: String(is_explicit)
91
91
  }
92
- return false if not is_unique_exposure(user, $layer_exposure_event, metadata)
92
+ return false unless is_unique_exposure(user, $layer_exposure_event, metadata)
93
93
  event.metadata = metadata
94
94
  event.secondary_exposures = exposures.is_a?(Array) ? exposures : []
95
95
 
@@ -98,18 +98,21 @@ module Statsig
98
98
  log_event(event)
99
99
  end
100
100
 
101
- def log_diagnostics_event(diagnostics, user = nil)
102
- return if @options.disable_diagnostics_logging
101
+ def log_diagnostics_event(diagnostics, context, user = nil)
103
102
  return if diagnostics.nil?
103
+ if @options.disable_diagnostics_logging
104
+ diagnostics.clear_markers(context)
105
+ return
106
+ end
104
107
 
105
108
  event = StatsigEvent.new($diagnostics_event)
106
109
  event.user = user
107
- serialized = diagnostics.serialize_with_sampling
110
+ serialized = diagnostics.serialize_with_sampling(context)
111
+ diagnostics.clear_markers(context)
108
112
  return if serialized[:markers].empty?
109
113
 
110
114
  event.metadata = serialized
111
115
  log_event(event)
112
- diagnostics.clear_markers
113
116
  end
114
117
 
115
118
  def periodic_flush
@@ -164,10 +167,10 @@ module Statsig
164
167
  return
165
168
  end
166
169
 
167
- event.metadata['reason'] = eval_details.reason
168
- event.metadata['configSyncTime'] = eval_details.config_sync_time
169
- event.metadata['initTime'] = eval_details.init_time
170
- event.metadata['serverTime'] = eval_details.server_time
170
+ event.metadata[:reason] = eval_details.reason
171
+ event.metadata[:configSyncTime] = eval_details.config_sync_time
172
+ event.metadata[:initTime] = eval_details.init_time
173
+ event.metadata[:serverTime] = eval_details.server_time
171
174
  end
172
175
 
173
176
  def safe_add_exposure_context(context, event)
@@ -175,8 +178,8 @@ module Statsig
175
178
  return
176
179
  end
177
180
 
178
- if context['is_manual_exposure']
179
- event.metadata['isManualExposure'] = 'true'
181
+ if context[:is_manual_exposure]
182
+ event.metadata[:isManualExposure] = 'true'
180
183
  end
181
184
  end
182
185
 
@@ -204,4 +207,4 @@ module Statsig
204
207
  true
205
208
  end
206
209
  end
207
- end
210
+ end
@@ -1,142 +1,92 @@
1
- # typed: true
2
-
3
- require 'sorbet-runtime'
4
1
  require_relative 'interfaces/data_store'
5
2
  require_relative 'interfaces/user_persistent_storage'
6
3
 
7
4
  ##
8
5
  # Configuration options for the Statsig SDK.
9
6
  class StatsigOptions
10
- extend T::Sig
11
7
 
12
- sig { returns(T.any(T::Hash[String, String], NilClass)) }
13
8
  # Hash you can use to set environment variables that apply to all of your users in
14
9
  # the same session and will be used for targeting purposes.
15
10
  # eg. { "tier" => "development" }
16
11
  attr_accessor :environment
17
12
 
18
- sig { returns(String) }
19
13
  # The base url used to make network calls to Statsig.
20
14
  # default: https://statsigapi.net/v1
21
15
  attr_accessor :api_url_base
22
16
 
23
17
  # The base url used specifically to call download_config_specs.
24
18
  # Takes precedence over api_url_base
25
- sig { returns(String) }
26
19
  attr_accessor :api_url_download_config_specs
27
20
 
28
- sig { returns(T.any(Float, Integer)) }
29
21
  # The interval (in seconds) to poll for changes to your Statsig configuration
30
22
  # default: 10s
31
23
  attr_accessor :rulesets_sync_interval
32
24
 
33
- sig { returns(T.any(Float, Integer)) }
34
25
  # The interval (in seconds) to poll for changes to your id lists
35
26
  # default: 60s
36
27
  attr_accessor :idlists_sync_interval
37
28
 
38
29
  # Disable background syncing for rulesets
39
- sig { returns(T::Boolean) }
40
30
  attr_accessor :disable_rulesets_sync
41
31
 
42
32
  # Disable background syncing for id lists
43
- sig { returns(T::Boolean) }
44
33
  attr_accessor :disable_idlists_sync
45
34
 
46
- sig { returns(T.any(Float, Integer)) }
47
35
  # How often to flush logs to Statsig
48
36
  # default: 60s
49
37
  attr_accessor :logging_interval_seconds
50
38
 
51
- sig { returns(Integer) }
52
39
  # The maximum number of events to batch before flushing logs to the server
53
40
  # default: 1000
54
41
  attr_accessor :logging_max_buffer_size
55
42
 
56
- sig { returns(T::Boolean) }
57
43
  # Restricts the SDK to not issue any network requests and only respond with default values (or local overrides)
58
44
  # default: false
59
45
  attr_accessor :local_mode
60
46
 
61
- sig { returns(T.any(String, NilClass)) }
62
47
  # A string that represents all rules for all feature gates, dynamic configs and experiments.
63
48
  # It can be provided to bootstrap the Statsig server SDK at initialization in case your server runs
64
49
  # into network issue or Statsig is down temporarily.
65
50
  attr_accessor :bootstrap_values
66
51
 
67
- sig { returns(T.any(Method, Proc, NilClass)) }
68
52
  # A callback function that will be called anytime the rulesets are updated.
69
53
  attr_accessor :rules_updated_callback
70
54
 
71
- sig { returns(T.any(Statsig::Interfaces::IDataStore, NilClass)) }
72
55
  # A class that extends IDataStore. Can be used to provide values from a
73
56
  # common data store (like Redis) to initialize the Statsig SDK.
74
57
  attr_accessor :data_store
75
58
 
76
- sig { returns(Integer) }
77
59
  # The number of threads allocated to syncing IDLists.
78
60
  # default: 3
79
61
  attr_accessor :idlist_threadpool_size
80
62
 
81
- sig { returns(Integer) }
82
63
  # The number of threads allocated to posting event logs.
83
64
  # default: 3
84
65
  attr_accessor :logger_threadpool_size
85
66
 
86
- sig { returns(T::Boolean) }
87
67
  # Should diagnostics be logged. These include performance metrics for initialize.
88
68
  # default: false
89
69
  attr_accessor :disable_diagnostics_logging
90
70
 
91
- sig { returns(T::Boolean) }
92
71
  # Statsig utilizes Sorbet (https://sorbet.org) to ensure type safety of the SDK. This includes logging
93
72
  # to console when errors are detected. You can disable this logging by setting this flag to true.
94
73
  # default: false
95
74
  attr_accessor :disable_sorbet_logging_handlers
96
75
 
97
- sig { returns(T.any(Integer, NilClass)) }
98
76
  # Number of seconds before a network call is timed out
99
77
  attr_accessor :network_timeout
100
78
 
101
- sig { returns(Integer) }
102
79
  # Number of times to retry sending a batch of failed log events
103
80
  attr_accessor :post_logs_retry_limit
104
81
 
105
- sig { returns(T.any(Method, Proc, Integer, NilClass)) }
106
82
  # The number of seconds, or a function that returns the number of seconds based on the number of retries remaining
107
83
  # which overrides the default backoff time between retries
108
84
  attr_accessor :post_logs_retry_backoff
109
85
 
110
- sig { returns(T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass)) }
111
86
  # A storage adapter for persisted values. Can be used for sticky bucketing users in experiments.
112
87
  # Implements Statsig::Interfaces::IUserPersistentStorage.
113
88
  attr_accessor :user_persistent_storage
114
89
 
115
- sig do
116
- params(
117
- environment: T.any(T::Hash[String, String], NilClass),
118
- api_url_base: T.nilable(String),
119
- api_url_download_config_specs: T.any(String, NilClass),
120
- rulesets_sync_interval: T.any(Float, Integer),
121
- idlists_sync_interval: T.any(Float, Integer),
122
- disable_rulesets_sync: T::Boolean,
123
- disable_idlists_sync: T::Boolean,
124
- logging_interval_seconds: T.any(Float, Integer),
125
- logging_max_buffer_size: Integer,
126
- local_mode: T::Boolean,
127
- bootstrap_values: T.any(String, NilClass),
128
- rules_updated_callback: T.any(Method, Proc, NilClass),
129
- data_store: T.any(Statsig::Interfaces::IDataStore, NilClass),
130
- idlist_threadpool_size: Integer,
131
- logger_threadpool_size: Integer,
132
- disable_diagnostics_logging: T::Boolean,
133
- disable_sorbet_logging_handlers: T::Boolean,
134
- network_timeout: T.any(Integer, NilClass),
135
- post_logs_retry_limit: Integer,
136
- post_logs_retry_backoff: T.any(Method, Proc, Integer, NilClass),
137
- user_persistent_storage: T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass)
138
- ).void
139
- end
140
90
  def initialize(
141
91
  environment = nil,
142
92
  api_url_base = nil,