statsig 0.1.1 → 0.1.2
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/evaluator.rb +9 -11
- data/lib/network.rb +2 -2
- data/lib/statsig_driver.rb +134 -134
- data/lib/statsig_logger.rb +3 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4fea4ebc3c58a51b2f2e9ccc9d0d85cb613ff24ac9ffa1f20033c1a8243a6a7
|
4
|
+
data.tar.gz: cf87e74ffa0eaae65a9873dac7fcb7b4fdd054526fe160064edafcf6f5721ce7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 172dc804df678405ac485ffe1b3faba2555c341f3ea37c7ee2b024e1f19e1389c62e042b9763537e940a3876b8a8348f73ea7f6ca4bbb0cd2c4be2506ee2023e
|
7
|
+
data.tar.gz: '092e5e9ba16538bd424c7dc44a9eea5f581ddb24c9813a4d29b73adadf5207f9ac789bce7c1855eea8e3967f1e01d11b5cbcd9fc9888b25418ce2b6caa2a262a'
|
data/lib/evaluator.rb
CHANGED
@@ -8,8 +8,6 @@ $fetch_from_server = :fetch_from_server
|
|
8
8
|
$type_dynamic_config = 'dynamic_config'
|
9
9
|
|
10
10
|
class Evaluator
|
11
|
-
include EvaluationHelpers
|
12
|
-
|
13
11
|
def initialize(store)
|
14
12
|
@spec_store = store
|
15
13
|
@initialized = true
|
@@ -102,13 +100,13 @@ class Evaluator
|
|
102
100
|
case operator
|
103
101
|
# numerical comparison
|
104
102
|
when 'gt'
|
105
|
-
return compare_numbers(value, target, ->(a, b) { a > b })
|
103
|
+
return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a > b })
|
106
104
|
when 'gte'
|
107
|
-
return compare_numbers(value, target, ->(a, b) { a >= b })
|
105
|
+
return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a >= b })
|
108
106
|
when 'lt'
|
109
|
-
return compare_numbers(value, target, ->(a, b) { a < b })
|
107
|
+
return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a < b })
|
110
108
|
when 'lte'
|
111
|
-
return compare_numbers(value, target, ->(a, b) { a <= b })
|
109
|
+
return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a <= b })
|
112
110
|
|
113
111
|
# version comparison
|
114
112
|
when 'version_gt'
|
@@ -126,17 +124,17 @@ class Evaluator
|
|
126
124
|
|
127
125
|
# array operations
|
128
126
|
when 'any'
|
129
|
-
return array_contains(target, value)
|
127
|
+
return EvaluationHelpers::array_contains(target, value)
|
130
128
|
when 'none'
|
131
|
-
return !array_contains(target, value)
|
129
|
+
return !EvaluationHelpers::array_contains(target, value)
|
132
130
|
|
133
131
|
#string
|
134
132
|
when 'str_starts_with_any'
|
135
|
-
return match_string_in_array(target, value, ->(a, b) { a.start_with?(b) })
|
133
|
+
return EvaluationHelpers::match_string_in_array(target, value, ->(a, b) { a.start_with?(b) })
|
136
134
|
when 'str_ends_with_any'
|
137
|
-
return match_string_in_array(target, value, ->(a, b) { a.end_with?(b) })
|
135
|
+
return EvaluationHelpers::match_string_in_array(target, value, ->(a, b) { a.end_with?(b) })
|
138
136
|
when 'str_contains_any'
|
139
|
-
return match_string_in_array(target, value, ->(a, b) { a.include?(b) })
|
137
|
+
return EvaluationHelpers::match_string_in_array(target, value, ->(a, b) { a.include?(b) })
|
140
138
|
when 'str_matches'
|
141
139
|
return (value.is_a?(String) && !(value =~ Regexp.new(target)).nil? rescue false)
|
142
140
|
when 'eq'
|
data/lib/network.rb
CHANGED
@@ -17,7 +17,7 @@ class Network
|
|
17
17
|
|
18
18
|
def check_gate(user, gate_name)
|
19
19
|
begin
|
20
|
-
request_body = JSON.generate({'user' => user&.serialize
|
20
|
+
request_body = JSON.generate({'user' => user&.serialize, 'gateName' => gate_name})
|
21
21
|
response = @http.post(@api + 'check_gate', body: request_body)
|
22
22
|
return JSON.parse(response.body)
|
23
23
|
rescue
|
@@ -27,7 +27,7 @@ class Network
|
|
27
27
|
|
28
28
|
def get_config(user, dynamic_config_name)
|
29
29
|
begin
|
30
|
-
request_body = JSON.generate({'user' => user&.serialize
|
30
|
+
request_body = JSON.generate({'user' => user&.serialize, 'configName' => dynamic_config_name})
|
31
31
|
response = @http.post(@api + 'get_config', body: request_body)
|
32
32
|
return JSON.parse(response.body)
|
33
33
|
rescue
|
data/lib/statsig_driver.rb
CHANGED
@@ -7,137 +7,137 @@ require 'statsig_user'
|
|
7
7
|
require 'spec_store'
|
8
8
|
|
9
9
|
class StatsigDriver
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
10
|
+
def initialize(secret_key)
|
11
|
+
super()
|
12
|
+
if !secret_key.is_a?(String) || !secret_key.start_with?('secret-')
|
13
|
+
raise 'Invalid secret key provided. Provide your project secret key from the Statsig console'
|
14
|
+
end
|
15
|
+
@shutdown = false
|
16
|
+
@secret_key = secret_key
|
17
|
+
@net = Network.new(secret_key, 'https://api.statsig.com/v1/')
|
18
|
+
@statsig_metadata = {
|
19
|
+
'sdkType' => 'ruby-server',
|
20
|
+
'sdkVersion' => Gem::Specification::load('statsig.gemspec')&.version,
|
21
|
+
}
|
22
|
+
@logger = StatsigLogger.new(@net, @statsig_metadata)
|
23
|
+
|
24
|
+
downloaded_specs = @net.download_config_specs
|
25
|
+
unless downloaded_specs.nil?
|
26
|
+
@initialized = true
|
27
|
+
end
|
28
|
+
|
29
|
+
@store = SpecStore.new(downloaded_specs)
|
30
|
+
@evaluator = Evaluator.new(@store)
|
31
|
+
|
32
|
+
@polling_thread = @net.poll_for_changes(-> (config_specs) { @store.process(config_specs) })
|
33
|
+
end
|
34
|
+
|
35
|
+
def check_gate(user, gate_name)
|
36
|
+
if !user.nil? && !user.instance_of?(StatsigUser)
|
37
|
+
raise 'Must provide a valid StatsigUser'
|
38
|
+
end
|
39
|
+
if !gate_name.is_a?(String) || gate_name.empty?
|
40
|
+
raise 'Invalid gate_name provided'
|
41
|
+
end
|
42
|
+
check_shutdown
|
43
|
+
unless @initialized
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
res = @evaluator.check_gate(user, gate_name)
|
48
|
+
if res.nil?
|
49
|
+
res = ConfigResult.new(gate_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
if res == $fetch_from_server
|
53
|
+
res = check_gate_fallback(user, gate_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
@logger.log_gate_exposure(user, res.name, res.gate_value, res.rule_id)
|
57
|
+
res.gate_value
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_config(user, dynamic_config_name)
|
61
|
+
if !user.nil? && !user.instance_of?(StatsigUser)
|
62
|
+
raise 'Must provide a valid StatsigUser or nil'
|
63
|
+
end
|
64
|
+
if !dynamic_config_name.is_a?(String) || dynamic_config_name.empty?
|
65
|
+
raise "Invalid dynamic_config_name provided"
|
66
|
+
end
|
67
|
+
check_shutdown
|
68
|
+
unless @initialized
|
69
|
+
return DynamicConfig.new(dynamic_config_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
res = @evaluator.get_config(user, dynamic_config_name)
|
73
|
+
if res.nil?
|
74
|
+
res = ConfigResult.new(dynamic_config_name)
|
75
|
+
end
|
76
|
+
|
77
|
+
if res == $fetch_from_server
|
78
|
+
res = get_config_fallback(user, dynamic_config_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
result_config = DynamicConfig.new(res.name, res.json_value, res.rule_id)
|
82
|
+
@logger.log_config_exposure(user, result_config.name, result_config.rule_id)
|
83
|
+
result_config
|
84
|
+
end
|
85
|
+
|
86
|
+
def log_event(user, event_name, value = nil, metadata = nil)
|
87
|
+
if !user.nil? && !user.instance_of?(StatsigUser)
|
88
|
+
raise 'Must provide a valid StatsigUser or nil'
|
89
|
+
end
|
90
|
+
check_shutdown
|
91
|
+
|
92
|
+
event = StatsigEvent.new(event_name)
|
93
|
+
event.user = user&.serialize
|
94
|
+
event.value = value
|
95
|
+
event.metadata = metadata
|
96
|
+
event.statsig_metadata = @statsig_metadata
|
97
|
+
@logger.log_event(event)
|
98
|
+
end
|
99
|
+
|
100
|
+
def shutdown
|
101
|
+
@shutdown = true
|
102
|
+
@logger.flush
|
103
|
+
@polling_thread&.exit
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def check_shutdown
|
109
|
+
if @shutdown
|
110
|
+
puts 'SDK has been shutdown. Updates in the Statsig Console will no longer reflect.'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_gate_fallback(user, gate_name)
|
115
|
+
network_result = @net.check_gate(user, gate_name)
|
116
|
+
if network_result.nil?
|
117
|
+
config_result = ConfigResult.new(gate_name)
|
118
|
+
return config_result
|
119
|
+
end
|
120
|
+
|
121
|
+
ConfigResult.new(
|
122
|
+
network_result['name'],
|
123
|
+
network_result['value'],
|
124
|
+
{},
|
125
|
+
network_result['rule_id'],
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_config_fallback(user, dynamic_config_name)
|
130
|
+
network_result = @net.get_config(user, dynamic_config_name)
|
131
|
+
if network_result.nil?
|
132
|
+
config_result = ConfigResult.new(dynamic_config_name)
|
133
|
+
return config_result
|
134
|
+
end
|
135
|
+
|
136
|
+
ConfigResult.new(
|
137
|
+
network_result['name'],
|
138
|
+
false,
|
139
|
+
network_result['value'],
|
140
|
+
network_result['rule_id'],
|
141
|
+
)
|
142
|
+
end
|
143
|
+
end
|
data/lib/statsig_logger.rb
CHANGED
@@ -13,11 +13,11 @@ class StatsigLogger
|
|
13
13
|
def log_event(event)
|
14
14
|
@events.push(event)
|
15
15
|
if @events.length >= 500
|
16
|
-
flush
|
16
|
+
flush
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def log_gate_exposure(user, gate_name, value, rule_id)
|
21
21
|
event = StatsigEvent.new($gate_exposure_event)
|
22
22
|
event.user = user
|
23
23
|
event.metadata = {
|
@@ -29,7 +29,7 @@ class StatsigLogger
|
|
29
29
|
log_event(event)
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def log_config_exposure(user, config_name, rule_id)
|
33
33
|
event = StatsigEvent.new($config_exposure_event)
|
34
34
|
event.user = user
|
35
35
|
event.metadata = {
|