statsig 1.8.4 → 1.9.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 +4 -4
- data/lib/config_result.rb +3 -1
- data/lib/evaluator.rb +21 -6
- data/lib/layer.rb +15 -0
- data/lib/network.rb +0 -1
- data/lib/spec_store.rb +15 -1
- data/lib/statsig.rb +6 -1
- data/lib/statsig_driver.rb +46 -24
- data/lib/statsig_logger.rb +14 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a832901a7d272c5b27408418836ded1042f720bfc0a374489ed0a81c476a1606
|
4
|
+
data.tar.gz: c89426f15ab949980299bfc21931466d076e8b23fbe26ddc290e13d1d92cb948
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c92f462bf372241bdd214a9a153b597792970b70631b8631be3df01b189953b6574016eedf437e397e07f62c8ef8f1c3e7ab7834f10080febe9843514cb059e0
|
7
|
+
data.tar.gz: 228deaad6a9c224c80321ddc6bd33ab13a4cd6eae86cc83f822f5d8325f25aaa13bfd0903369468b3664d28847b3239df27a446b32b349e5b3d987f77ef3fb74
|
data/lib/config_result.rb
CHANGED
@@ -6,13 +6,15 @@ module Statsig
|
|
6
6
|
attr_accessor :json_value
|
7
7
|
attr_accessor :rule_id
|
8
8
|
attr_accessor :secondary_exposures
|
9
|
+
attr_accessor :config_delegate
|
9
10
|
|
10
|
-
def initialize(name, gate_value = false, json_value = {}, rule_id = '', secondary_exposures = [])
|
11
|
+
def initialize(name, gate_value = false, json_value = {}, rule_id = '', secondary_exposures = [], config_delegate = '')
|
11
12
|
@name = name
|
12
13
|
@gate_value = gate_value
|
13
14
|
@json_value = json_value
|
14
15
|
@rule_id = rule_id
|
15
16
|
@secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
|
17
|
+
@config_delegate = config_delegate
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
data/lib/evaluator.rb
CHANGED
@@ -29,6 +29,11 @@ module Statsig
|
|
29
29
|
eval_spec(user, @spec_store.get_config(config_name))
|
30
30
|
end
|
31
31
|
|
32
|
+
def get_layer(user, layer_name)
|
33
|
+
return nil unless @initialized && @spec_store.has_layer?(layer_name)
|
34
|
+
eval_spec(user, @spec_store.get_layer(layer_name))
|
35
|
+
end
|
36
|
+
|
32
37
|
def shutdown
|
33
38
|
@spec_store.shutdown
|
34
39
|
end
|
@@ -44,15 +49,16 @@ module Statsig
|
|
44
49
|
rule = config['rules'][i]
|
45
50
|
result = eval_rule(user, rule)
|
46
51
|
return $fetch_from_server if result == $fetch_from_server
|
47
|
-
exposures = exposures + result
|
48
|
-
if result
|
52
|
+
exposures = exposures + result.secondary_exposures
|
53
|
+
if result.gate_value
|
49
54
|
pass = eval_pass_percent(user, rule, config['salt'])
|
50
55
|
return Statsig::ConfigResult.new(
|
51
56
|
config['name'],
|
52
57
|
pass,
|
53
|
-
pass ?
|
54
|
-
|
55
|
-
exposures
|
58
|
+
pass ? result.json_value : config['defaultValue'],
|
59
|
+
result.rule_id,
|
60
|
+
exposures,
|
61
|
+
result.config_delegate
|
56
62
|
)
|
57
63
|
end
|
58
64
|
|
@@ -83,7 +89,16 @@ module Statsig
|
|
83
89
|
end
|
84
90
|
i += 1
|
85
91
|
end
|
86
|
-
|
92
|
+
|
93
|
+
delegate = rule['configDelegate']
|
94
|
+
if pass and @spec_store.get_config(delegate)
|
95
|
+
delegated_result = self.eval_spec(user, @spec_store.get_config(delegate))
|
96
|
+
delegated_result.config_delegate = delegate
|
97
|
+
delegated_result.secondary_exposures = exposures + delegated_result.secondary_exposures
|
98
|
+
return delegated_result
|
99
|
+
end
|
100
|
+
|
101
|
+
Statsig::ConfigResult.new('', pass, rule['returnValue'], rule['id'], exposures)
|
87
102
|
end
|
88
103
|
|
89
104
|
def eval_condition(user, condition)
|
data/lib/layer.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Layer
|
2
|
+
attr_accessor :name
|
3
|
+
attr_accessor :rule_id
|
4
|
+
|
5
|
+
def initialize(name, value = {}, rule_id = '')
|
6
|
+
@name = name
|
7
|
+
@value = value
|
8
|
+
@rule_id = rule_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(index, default_value)
|
12
|
+
return default_value if @value.nil? || !@value.key?(index)
|
13
|
+
@value[index]
|
14
|
+
end
|
15
|
+
end
|
data/lib/network.rb
CHANGED
data/lib/spec_store.rb
CHANGED
@@ -11,6 +11,7 @@ module Statsig
|
|
11
11
|
@store = {
|
12
12
|
:gates => {},
|
13
13
|
:configs => {},
|
14
|
+
:layers => {},
|
14
15
|
:id_lists => {},
|
15
16
|
}
|
16
17
|
e = download_config_specs
|
@@ -34,6 +35,10 @@ module Statsig
|
|
34
35
|
@store[:configs].key?(config_name)
|
35
36
|
end
|
36
37
|
|
38
|
+
def has_layer?(layer_name)
|
39
|
+
@store[:layers].key?(layer_name)
|
40
|
+
end
|
41
|
+
|
37
42
|
def get_gate(gate_name)
|
38
43
|
return nil unless has_gate?(gate_name)
|
39
44
|
@store[:gates][gate_name]
|
@@ -44,6 +49,11 @@ module Statsig
|
|
44
49
|
@store[:configs][config_name]
|
45
50
|
end
|
46
51
|
|
52
|
+
def get_layer(layer_name)
|
53
|
+
return nil unless has_layer?(layer_name)
|
54
|
+
@store[:layers][layer_name]
|
55
|
+
end
|
56
|
+
|
47
57
|
def get_id_list(list_name)
|
48
58
|
@store[:id_lists][list_name]
|
49
59
|
end
|
@@ -89,15 +99,19 @@ module Statsig
|
|
89
99
|
@last_sync_time = specs_json['time'] || @last_sync_time
|
90
100
|
return unless specs_json['has_updates'] == true &&
|
91
101
|
!specs_json['feature_gates'].nil? &&
|
92
|
-
!specs_json['dynamic_configs'].nil?
|
102
|
+
!specs_json['dynamic_configs'].nil? &&
|
103
|
+
!specs_json['layer_configs'].nil?
|
93
104
|
|
94
105
|
new_gates = {}
|
95
106
|
new_configs = {}
|
107
|
+
new_layers = {}
|
96
108
|
|
97
109
|
specs_json['feature_gates'].map{|gate| new_gates[gate['name']] = gate }
|
98
110
|
specs_json['dynamic_configs'].map{|config| new_configs[config['name']] = config }
|
111
|
+
specs_json['layer_configs'].map{|layer| new_layers[layer['name']] = layer }
|
99
112
|
@store[:gates] = new_gates
|
100
113
|
@store[:configs] = new_configs
|
114
|
+
@store[:layers] = new_layers
|
101
115
|
|
102
116
|
new_id_lists = specs_json['id_lists']
|
103
117
|
if new_id_lists.is_a? Hash
|
data/lib/statsig.rb
CHANGED
@@ -25,6 +25,11 @@ module Statsig
|
|
25
25
|
@shared_instance&.get_config(user, experiment_name)
|
26
26
|
end
|
27
27
|
|
28
|
+
def self.get_layer(user, layer_name)
|
29
|
+
ensure_initialized
|
30
|
+
@shared_instance&.get_config(user, layer_name)
|
31
|
+
end
|
32
|
+
|
28
33
|
def self.log_event(user, event_name, value, metadata)
|
29
34
|
ensure_initialized
|
30
35
|
@shared_instance&.log_event(user, event_name, value, metadata)
|
@@ -40,7 +45,7 @@ module Statsig
|
|
40
45
|
def self.get_statsig_metadata
|
41
46
|
{
|
42
47
|
'sdkType' => 'ruby-server',
|
43
|
-
'sdkVersion' => '1.
|
48
|
+
'sdkVersion' => '1.9.0',
|
44
49
|
}
|
45
50
|
end
|
46
51
|
|
data/lib/statsig_driver.rb
CHANGED
@@ -26,12 +26,7 @@ class StatsigDriver
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def check_gate(user, gate_name)
|
29
|
-
|
30
|
-
user = normalize_user(user)
|
31
|
-
if !gate_name.is_a?(String) || gate_name.empty?
|
32
|
-
raise 'Invalid gate_name provided'
|
33
|
-
end
|
34
|
-
check_shutdown
|
29
|
+
user = verify_inputs(user, gate_name, "gate_name")
|
35
30
|
|
36
31
|
res = @evaluator.check_gate(user, gate_name)
|
37
32
|
if res.nil?
|
@@ -49,33 +44,34 @@ class StatsigDriver
|
|
49
44
|
end
|
50
45
|
|
51
46
|
def get_config(user, dynamic_config_name)
|
52
|
-
|
53
|
-
user
|
54
|
-
|
55
|
-
raise "Invalid dynamic_config_name provided"
|
56
|
-
end
|
57
|
-
check_shutdown
|
47
|
+
user = verify_inputs(user, dynamic_config_name, "dynamic_config_name")
|
48
|
+
get_config_impl(user, dynamic_config_name)
|
49
|
+
end
|
58
50
|
|
59
|
-
|
51
|
+
def get_experiment(user, experiment_name)
|
52
|
+
user = verify_inputs(user, experiment_name, "experiment_name")
|
53
|
+
get_config_impl(user, experiment_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_layer(user, layer_name)
|
57
|
+
user = verify_inputs(user, layer_name, "layer_name")
|
58
|
+
|
59
|
+
res = @evaluator.get_layer(user, layer_name)
|
60
60
|
if res.nil?
|
61
|
-
res = Statsig::ConfigResult.new(
|
61
|
+
res = Statsig::ConfigResult.new(layer_name)
|
62
62
|
end
|
63
63
|
|
64
64
|
if res == $fetch_from_server
|
65
|
-
res
|
65
|
+
if res.config_delegate.empty?
|
66
|
+
return Layer.new(layer_name)
|
67
|
+
end
|
68
|
+
res = get_config_fallback(user, res.config_delegate)
|
66
69
|
# exposure logged by the server
|
67
70
|
else
|
68
|
-
@logger.
|
71
|
+
@logger.log_layer_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.config_delegate)
|
69
72
|
end
|
70
73
|
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
def get_experiment(user, experiment_name)
|
75
|
-
if !experiment_name.is_a?(String) || experiment_name.empty?
|
76
|
-
raise "Invalid experiment_name provided"
|
77
|
-
end
|
78
|
-
get_config(user, experiment_name)
|
74
|
+
Layer.new(res.name, res.json_value, res.rule_id)
|
79
75
|
end
|
80
76
|
|
81
77
|
def log_event(user, event_name, value = nil, metadata = nil)
|
@@ -102,6 +98,32 @@ class StatsigDriver
|
|
102
98
|
|
103
99
|
private
|
104
100
|
|
101
|
+
def verify_inputs(user, config_name, variable_name)
|
102
|
+
validate_user(user)
|
103
|
+
if !config_name.is_a?(String) || config_name.empty?
|
104
|
+
raise "Invalid " + variable_name +" provided"
|
105
|
+
end
|
106
|
+
|
107
|
+
check_shutdown
|
108
|
+
normalize_user(user)
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_config_impl(user, config_name)
|
112
|
+
res = @evaluator.get_config(user, config_name)
|
113
|
+
if res.nil?
|
114
|
+
res = Statsig::ConfigResult.new(config_name)
|
115
|
+
end
|
116
|
+
|
117
|
+
if res == $fetch_from_server
|
118
|
+
res = get_config_fallback(user, config_name)
|
119
|
+
# exposure logged by the server
|
120
|
+
else
|
121
|
+
@logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures)
|
122
|
+
end
|
123
|
+
|
124
|
+
DynamicConfig.new(res.name, res.json_value, res.rule_id)
|
125
|
+
end
|
126
|
+
|
105
127
|
def validate_user(user)
|
106
128
|
if user.nil? || !user.instance_of?(StatsigUser) || !user.user_id.is_a?(String)
|
107
129
|
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.'
|
data/lib/statsig_logger.rb
CHANGED
@@ -2,6 +2,7 @@ require 'statsig_event'
|
|
2
2
|
|
3
3
|
$gate_exposure_event = 'statsig::gate_exposure'
|
4
4
|
$config_exposure_event = 'statsig::config_exposure'
|
5
|
+
$layer_exposure_event = 'statsig::layer_exposure'
|
5
6
|
|
6
7
|
module Statsig
|
7
8
|
class StatsigLogger
|
@@ -43,6 +44,19 @@ module Statsig
|
|
43
44
|
log_event(event)
|
44
45
|
end
|
45
46
|
|
47
|
+
def log_layer_exposure(user, config_name, rule_id, secondary_exposures, allocated_experiment)
|
48
|
+
event = StatsigEvent.new($layer_exposure_event)
|
49
|
+
event.user = user
|
50
|
+
event.metadata = {
|
51
|
+
'config' => config_name,
|
52
|
+
'ruleID' => rule_id,
|
53
|
+
'allocatedExperiment' => allocated_experiment
|
54
|
+
}
|
55
|
+
event.statsig_metadata = Statsig.get_statsig_metadata
|
56
|
+
event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
|
57
|
+
log_event(event)
|
58
|
+
end
|
59
|
+
|
46
60
|
def periodic_flush
|
47
61
|
Thread.new do
|
48
62
|
loop do
|
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.
|
4
|
+
version: 1.9.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-
|
11
|
+
date: 2022-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/dynamic_config.rb
|
119
119
|
- lib/evaluation_helpers.rb
|
120
120
|
- lib/evaluator.rb
|
121
|
+
- lib/layer.rb
|
121
122
|
- lib/network.rb
|
122
123
|
- lib/spec_store.rb
|
123
124
|
- lib/statsig.rb
|
@@ -145,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
146
|
- !ruby/object:Gem::Version
|
146
147
|
version: '0'
|
147
148
|
requirements: []
|
148
|
-
rubygems_version: 3.
|
149
|
+
rubygems_version: 3.3.7
|
149
150
|
signing_key:
|
150
151
|
specification_version: 4
|
151
152
|
summary: Statsig server SDK for Ruby
|