statsig 1.9.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afbf6d972c5aeead4eeaa8c352155c41b02a3710f55d80309939d5acc0fd1e80
4
- data.tar.gz: c83f0399868af1d7978aeb2d2723f4bfbc860646de3ea0a7aaf840903489b92a
3
+ metadata.gz: 1590d900487869f3cbd76aae50f38ccb535b372ba0468a446ab5574ccfc782eb
4
+ data.tar.gz: 1e94c594d470d0baa21a073177677d6c631297aa1fe51747853ef25106b55c6e
5
5
  SHA512:
6
- metadata.gz: babe4ac6dc398bd87df7537ea7c9391e72e4a32c4ec80944895adb507351a02042dd2bfc28deb2336e706fcf531ba4d30dfdeeb280404b108a25505fcd749ed8
7
- data.tar.gz: c1bad8f27c2675b7dbc125090a56062e71c5fddb6f0cc8464c0e9ea03b910f9ca918a9ccf4e6c8db99815b7964aaf543d0cc69db5a873bcf58ddc806ef8932cc
6
+ metadata.gz: 7b2ceb928a74c83e00b783aa46ea45010dbd9daa4a8932a29528e7edc10d9393a6cad9139c26bcd98b13509957565637593c4d0115bd5f929425dc7872f54260
7
+ data.tar.gz: db7812f360b4e68b402107fedea8f7d7c591bdb83ad206265b871d22b837c6be04e867c51d879a1730dbcc8cec76097879e47f601d42d8e1c456018dda5dd44e
@@ -13,4 +13,10 @@ class DynamicConfig
13
13
  return default_value if @value.nil? || !@value.key?(index)
14
14
  @value[index]
15
15
  end
16
+
17
+ def get_typed(index, default_value)
18
+ return default_value if @value.nil? || !@value.key?(index)
19
+ return default_value if @value[index].class != default_value.class and default_value.class != TrueClass and default_value.class != FalseClass
20
+ @value[index]
21
+ end
16
22
  end
data/lib/evaluator.rb CHANGED
@@ -12,19 +12,34 @@ $type_dynamic_config = 'dynamic_config'
12
12
 
13
13
  module Statsig
14
14
  class Evaluator
15
- def initialize(network, error_callback)
16
- @spec_store = Statsig::SpecStore.new(network, error_callback)
15
+ def initialize(network, options, error_callback)
16
+ @spec_store = Statsig::SpecStore.new(network, error_callback, options.rulesets_sync_interval, options.idlists_sync_interval)
17
17
  @ua_parser = UserAgentParser::Parser.new
18
18
  CountryLookup.initialize
19
19
  @initialized = true
20
+
21
+ @gate_overrides = {}
22
+ @config_overrides = {}
20
23
  end
21
24
 
22
25
  def check_gate(user, gate_name)
26
+ return Statsig::ConfigResult.new(
27
+ gate_name,
28
+ @gate_overrides[gate_name],
29
+ @gate_overrides[gate_name],
30
+ 'override',
31
+ []) unless !@gate_overrides.has_key?(gate_name)
23
32
  return nil unless @initialized && @spec_store.has_gate?(gate_name)
24
33
  eval_spec(user, @spec_store.get_gate(gate_name))
25
34
  end
26
35
 
27
36
  def get_config(user, config_name)
37
+ return Statsig::ConfigResult.new(
38
+ config_name,
39
+ false,
40
+ @config_overrides[config_name],
41
+ 'override',
42
+ []) unless !@config_overrides.has_key?(config_name)
28
43
  return nil unless @initialized && @spec_store.has_config?(config_name)
29
44
  eval_spec(user, @spec_store.get_config(config_name))
30
45
  end
@@ -38,6 +53,14 @@ module Statsig
38
53
  @spec_store.shutdown
39
54
  end
40
55
 
56
+ def override_gate(gate, value)
57
+ @gate_overrides[gate] = value
58
+ end
59
+
60
+ def override_config(config, value)
61
+ @config_overrides[config] = value
62
+ end
63
+
41
64
  private
42
65
 
43
66
  def eval_spec(user, config)
data/lib/layer.rb CHANGED
@@ -18,4 +18,15 @@ class Layer
18
18
 
19
19
  @value[index]
20
20
  end
21
+
22
+ def get_typed(index, default_value)
23
+ return default_value if @value.nil? || !@value.key?(index)
24
+ return default_value if @value[index].class != default_value.class and default_value.class != TrueClass and default_value.class != FalseClass
25
+
26
+ if @exposure_log_func.is_a? Proc
27
+ @exposure_log_func.call(self, index)
28
+ end
29
+
30
+ @value[index]
31
+ end
21
32
  end
data/lib/network.rb CHANGED
@@ -6,18 +6,20 @@ $retry_codes = [408, 500, 502, 503, 504, 522, 524, 599]
6
6
 
7
7
  module Statsig
8
8
  class Network
9
- def initialize(server_secret, api, backoff_mult = 10)
9
+ def initialize(server_secret, api, local_mode, backoff_mult = 10)
10
10
  super()
11
11
  unless api.end_with?('/')
12
12
  api += '/'
13
13
  end
14
14
  @server_secret = server_secret
15
15
  @api = api
16
+ @local_mode = local_mode
16
17
  @backoff_multiplier = backoff_mult
17
18
  @session_id = SecureRandom.uuid
18
19
  end
19
20
 
20
21
  def post_helper(endpoint, body, retries = 0, backoff = 1)
22
+ return nil unless !@local_mode
21
23
  http = HTTP.headers(
22
24
  {"STATSIG-API-KEY" => @server_secret,
23
25
  "STATSIG-CLIENT-TIME" => (Time.now.to_f * 1000).to_s,
data/lib/spec_store.rb CHANGED
@@ -5,10 +5,10 @@ require 'id_list'
5
5
 
6
6
  module Statsig
7
7
  class SpecStore
8
- def initialize(network, error_callback = nil, config_sync_interval = 10, id_lists_sync_interval = 60)
8
+ def initialize(network, error_callback = nil, rulesets_sync_interval = 10, id_lists_sync_interval = 60)
9
9
  @network = network
10
10
  @last_sync_time = 0
11
- @config_sync_interval = config_sync_interval
11
+ @rulesets_sync_interval = rulesets_sync_interval
12
12
  @id_lists_sync_interval = id_lists_sync_interval
13
13
  @store = {
14
14
  :gates => {},
@@ -16,8 +16,8 @@ module Statsig
16
16
  :layers => {},
17
17
  :id_lists => {},
18
18
  }
19
- e = download_config_specs
20
- error_callback.call(e) unless error_callback.nil?
19
+ @error_callback = error_callback
20
+ download_config_specs
21
21
  get_id_lists
22
22
 
23
23
  @config_sync_thread = sync_config_specs
@@ -65,7 +65,7 @@ module Statsig
65
65
  def sync_config_specs
66
66
  Thread.new do
67
67
  loop do
68
- sleep @config_sync_interval
68
+ sleep @rulesets_sync_interval
69
69
  download_config_specs
70
70
  end
71
71
  end
@@ -81,10 +81,16 @@ module Statsig
81
81
  end
82
82
 
83
83
  def download_config_specs
84
+ e = get_config_specs_from_network
85
+ @error_callback.call(e) unless e.nil? or @error_callback.nil?
86
+ end
87
+
88
+ def get_config_specs_from_network
84
89
  begin
85
90
  response, e = @network.post_helper('download_config_specs', JSON.generate({'sinceTime' => @last_sync_time}))
86
91
  if e.nil?
87
92
  process(JSON.parse(response.body))
93
+ nil
88
94
  else
89
95
  e
90
96
  end
@@ -145,7 +151,7 @@ module Statsig
145
151
  next
146
152
  end
147
153
 
148
- # skip if server list returns a newer file
154
+ # reset local list if server list returns a newer file
149
155
  if server_list.file_id != local_list.file_id && server_list.creation_time >= local_list.creation_time
150
156
  local_list = IDList.new(list)
151
157
  local_list.size = 0
data/lib/statsig.rb CHANGED
@@ -30,7 +30,7 @@ module Statsig
30
30
  @shared_instance&.get_layer(user, layer_name)
31
31
  end
32
32
 
33
- def self.log_event(user, event_name, value, metadata)
33
+ def self.log_event(user, event_name, value = nil, metadata = nil)
34
34
  ensure_initialized
35
35
  @shared_instance&.log_event(user, event_name, value, metadata)
36
36
  end
@@ -42,10 +42,20 @@ module Statsig
42
42
  @shared_instance = nil
43
43
  end
44
44
 
45
+ def self.override_gate(gate_name, gate_value)
46
+ ensure_initialized
47
+ @shared_instance&.override_gate(gate_name, gate_value)
48
+ end
49
+
50
+ def self.override_config(config_name, config_value)
51
+ ensure_initialized
52
+ @shared_instance&.override_config(config_name, config_value)
53
+ end
54
+
45
55
  def self.get_statsig_metadata
46
56
  {
47
57
  'sdkType' => 'ruby-server',
48
- 'sdkVersion' => '1.9.2',
58
+ 'sdkVersion' => '1.12.0',
49
59
  }
50
60
  end
51
61
 
@@ -22,9 +22,9 @@ class StatsigDriver
22
22
  @options = options || StatsigOptions.new
23
23
  @shutdown = false
24
24
  @secret_key = secret_key
25
- @net = Statsig::Network.new(secret_key, @options.api_url_base)
26
- @logger = Statsig::StatsigLogger.new(@net)
27
- @evaluator = Statsig::Evaluator.new(@net, error_callback)
25
+ @net = Statsig::Network.new(secret_key, @options.api_url_base, @options.local_mode)
26
+ @logger = Statsig::StatsigLogger.new(@net, @options)
27
+ @evaluator = Statsig::Evaluator.new(@net, @options, error_callback)
28
28
  end
29
29
 
30
30
  def check_gate(user, gate_name)
@@ -98,6 +98,14 @@ class StatsigDriver
98
98
  @evaluator.shutdown
99
99
  end
100
100
 
101
+ def override_gate(gate_name, gate_value)
102
+ @evaluator.override_gate(gate_name, gate_value)
103
+ end
104
+
105
+ def override_config(config_name, config_value)
106
+ @evaluator.override_config(config_name, config_value)
107
+ end
108
+
101
109
  private
102
110
 
103
111
  def verify_inputs(user, config_name, variable_name)
@@ -127,8 +135,14 @@ class StatsigDriver
127
135
  end
128
136
 
129
137
  def validate_user(user)
130
- if user.nil? || !user.instance_of?(StatsigUser) || !user.user_id.is_a?(String)
131
- raise 'Must provide a valid StatsigUser with a user_id to use the server SDK. See https://docs.statsig.com/messages/serverRequiredUserID/ for more details.'
138
+ if user.nil? ||
139
+ !user.instance_of?(StatsigUser) ||
140
+ (
141
+ # user_id is nil and custom_ids is not a hash with entries
142
+ !user.user_id.is_a?(String) &&
143
+ (!user.custom_ids.is_a?(Hash) || user.custom_ids.size == 0)
144
+ )
145
+ raise 'Must provide a valid StatsigUser with a user_id or at least a custom ID. See https://docs.statsig.com/messages/serverRequiredUserID/ for more details.'
132
146
  end
133
147
  end
134
148
 
@@ -6,15 +6,16 @@ $layer_exposure_event = 'statsig::layer_exposure'
6
6
 
7
7
  module Statsig
8
8
  class StatsigLogger
9
- def initialize(network)
9
+ def initialize(network, options)
10
10
  @network = network
11
11
  @events = []
12
12
  @background_flush = periodic_flush
13
+ @options = options
13
14
  end
14
15
 
15
16
  def log_event(event)
16
17
  @events.push(event)
17
- if @events.length >= 500
18
+ if @events.length >= @options.logging_max_buffer_size
18
19
  flush
19
20
  end
20
21
  end
@@ -70,7 +71,7 @@ module Statsig
70
71
  def periodic_flush
71
72
  Thread.new do
72
73
  loop do
73
- sleep 60
74
+ sleep @options.logging_interval_seconds
74
75
  flush
75
76
  end
76
77
  end
@@ -83,8 +84,9 @@ module Statsig
83
84
  if @events.length == 0
84
85
  return
85
86
  end
86
- flush_events = @events.map { |e| e.serialize }
87
+ events_clone = @events
87
88
  @events = []
89
+ flush_events = events_clone.map { |e| e.serialize }
88
90
 
89
91
  @network.post_logs(flush_events)
90
92
  end
@@ -1,9 +1,26 @@
1
1
  class StatsigOptions
2
- attr_reader :environment
3
- attr_reader :api_url_base
2
+ attr_accessor :environment
3
+ attr_accessor :api_url_base
4
+ attr_accessor :rulesets_sync_interval
5
+ attr_accessor :idlists_sync_interval
6
+ attr_accessor :logging_interval_seconds
7
+ attr_accessor :logging_max_buffer_size
8
+ attr_accessor :local_mode
4
9
 
5
- def initialize(environment = nil, api_url_base = 'https://statsigapi.net/v1')
10
+ def initialize(
11
+ environment=nil,
12
+ api_url_base='https://statsigapi.net/v1',
13
+ rulesets_sync_interval: 10,
14
+ idlists_sync_interval: 60,
15
+ logging_interval_seconds: 60,
16
+ logging_max_buffer_size: 1000,
17
+ local_mode: false)
6
18
  @environment = environment.is_a?(Hash) ? environment : nil
7
19
  @api_url_base = api_url_base
20
+ @rulesets_sync_interval = rulesets_sync_interval
21
+ @idlists_sync_interval = idlists_sync_interval
22
+ @logging_interval_seconds = logging_interval_seconds
23
+ @logging_max_buffer_size = [logging_max_buffer_size, 1000].min
24
+ @local_mode = local_mode
8
25
  end
9
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statsig
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.2
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Statsig, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-29 00:00:00.000000000 Z
11
+ date: 2022-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
155
  requirements: []
156
- rubygems_version: 3.2.3
156
+ rubygems_version: 3.2.32
157
157
  signing_key:
158
158
  specification_version: 4
159
159
  summary: Statsig server SDK for Ruby