statsig 1.30.0 → 1.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/api_config.rb +128 -0
- data/lib/client_initialize_helpers.rb +79 -108
- data/lib/config_result.rb +17 -32
- data/lib/constants.rb +60 -0
- data/lib/diagnostics.rb +21 -70
- data/lib/dynamic_config.rb +1 -24
- data/lib/error_boundary.rb +0 -5
- data/lib/evaluation_details.rb +5 -1
- data/lib/evaluation_helpers.rb +35 -3
- data/lib/evaluator.rb +332 -316
- data/lib/feature_gate.rb +0 -24
- data/lib/id_list.rb +1 -1
- data/lib/interfaces/data_store.rb +1 -1
- data/lib/interfaces/user_persistent_storage.rb +1 -1
- data/lib/layer.rb +1 -20
- data/lib/network.rb +6 -53
- data/lib/spec_store.rb +124 -115
- data/lib/statsig.rb +72 -97
- data/lib/statsig_driver.rb +73 -128
- data/lib/statsig_errors.rb +1 -1
- data/lib/statsig_event.rb +8 -8
- data/lib/statsig_logger.rb +29 -26
- data/lib/statsig_options.rb +0 -50
- data/lib/statsig_user.rb +27 -68
- data/lib/ua_parser.rb +1 -1
- data/lib/uri_helper.rb +1 -9
- data/lib/user_persistent_storage_utils.rb +0 -17
- metadata +4 -2
data/lib/feature_gate.rb
CHANGED
@@ -1,42 +1,19 @@
|
|
1
|
-
# typed: false
|
2
|
-
|
3
|
-
require 'sorbet-runtime'
|
4
|
-
|
5
1
|
class FeatureGate
|
6
|
-
extend T::Sig
|
7
2
|
|
8
|
-
sig { returns(String) }
|
9
3
|
attr_accessor :name
|
10
4
|
|
11
|
-
sig { returns(T::Boolean) }
|
12
5
|
attr_accessor :value
|
13
6
|
|
14
|
-
sig { returns(String) }
|
15
7
|
attr_accessor :rule_id
|
16
8
|
|
17
|
-
sig { returns(T.nilable(String)) }
|
18
9
|
attr_accessor :group_name
|
19
10
|
|
20
|
-
sig { returns(String) }
|
21
11
|
attr_accessor :id_type
|
22
12
|
|
23
|
-
sig { returns(T.nilable(Statsig::EvaluationDetails)) }
|
24
13
|
attr_accessor :evaluation_details
|
25
14
|
|
26
|
-
sig { returns(T.nilable(T::Array[String])) }
|
27
15
|
attr_accessor :target_app_ids
|
28
16
|
|
29
|
-
sig do
|
30
|
-
params(
|
31
|
-
name: String,
|
32
|
-
value: T::Boolean,
|
33
|
-
rule_id: String,
|
34
|
-
group_name: T.nilable(String),
|
35
|
-
id_type: String,
|
36
|
-
evaluation_details: T.nilable(Statsig::EvaluationDetails),
|
37
|
-
target_app_ids: T.nilable(T::Array[String])
|
38
|
-
).void
|
39
|
-
end
|
40
17
|
def initialize(
|
41
18
|
name,
|
42
19
|
value: false,
|
@@ -55,7 +32,6 @@ class FeatureGate
|
|
55
32
|
@target_app_ids = target_app_ids
|
56
33
|
end
|
57
34
|
|
58
|
-
sig { params(res: Statsig::ConfigResult).returns(FeatureGate) }
|
59
35
|
def self.from_config_result(res)
|
60
36
|
new(
|
61
37
|
res.name,
|
data/lib/id_list.rb
CHANGED
data/lib/layer.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
# typed: false
|
2
|
-
|
3
|
-
require 'sorbet-runtime'
|
4
1
|
##
|
5
2
|
# Contains the current values from Statsig.
|
6
3
|
# Will contain layer default values for all shared parameters in that layer.
|
@@ -9,37 +6,22 @@ require 'sorbet-runtime'
|
|
9
6
|
#
|
10
7
|
# Layers Documentation: https://docs.statsig.com/layers
|
11
8
|
class Layer
|
12
|
-
extend T::Sig
|
13
9
|
|
14
|
-
sig { returns(String) }
|
15
10
|
attr_accessor :name
|
16
11
|
|
17
|
-
sig { returns(String) }
|
18
12
|
attr_accessor :rule_id
|
19
13
|
|
20
|
-
sig { returns(String) }
|
21
14
|
attr_accessor :group_name
|
22
15
|
|
23
|
-
sig do
|
24
|
-
params(
|
25
|
-
name: String,
|
26
|
-
value: T::Hash[String, T.untyped],
|
27
|
-
rule_id: String,
|
28
|
-
group_name: T.nilable(String),
|
29
|
-
allocated_experiment: T.nilable(String),
|
30
|
-
exposure_log_func: T.any(Method, Proc, NilClass)
|
31
|
-
).void
|
32
|
-
end
|
33
16
|
def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_experiment = nil, exposure_log_func = nil)
|
34
17
|
@name = name
|
35
|
-
@value = value
|
18
|
+
@value = value || {}
|
36
19
|
@rule_id = rule_id
|
37
20
|
@group_name = group_name
|
38
21
|
@allocated_experiment = allocated_experiment
|
39
22
|
@exposure_log_func = exposure_log_func
|
40
23
|
end
|
41
24
|
|
42
|
-
sig { params(index: String, default_value: T.untyped).returns(T.untyped) }
|
43
25
|
##
|
44
26
|
# Get the value for the given key (index), falling back to the default_value if it cannot be found.
|
45
27
|
#
|
@@ -55,7 +37,6 @@ class Layer
|
|
55
37
|
@value[index]
|
56
38
|
end
|
57
39
|
|
58
|
-
sig { params(index: String, default_value: T.untyped).returns(T.untyped) }
|
59
40
|
##
|
60
41
|
# Get the value for the given key (index), falling back to the default_value if it cannot be found
|
61
42
|
# or is found to have a different type from the default_value.
|
data/lib/network.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
# typed: true
|
2
|
-
|
3
1
|
require 'http'
|
4
2
|
require 'json'
|
5
3
|
require 'securerandom'
|
6
|
-
|
4
|
+
|
7
5
|
require 'uri_helper'
|
8
6
|
require 'connection_pool'
|
9
7
|
|
@@ -20,9 +18,7 @@ module Statsig
|
|
20
18
|
end
|
21
19
|
|
22
20
|
class Network
|
23
|
-
extend T::Sig
|
24
21
|
|
25
|
-
sig { params(server_secret: String, options: StatsigOptions, backoff_mult: Integer).void }
|
26
22
|
def initialize(server_secret, options, backoff_mult = 10)
|
27
23
|
super()
|
28
24
|
URIHelper.initialize(options)
|
@@ -54,41 +50,18 @@ module Statsig
|
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
57
|
-
sig do
|
58
|
-
params(since_time: Integer)
|
59
|
-
.returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
|
60
|
-
end
|
61
53
|
def download_config_specs(since_time)
|
62
54
|
get("download_config_specs/#{@server_secret}.json?sinceTime=#{since_time}")
|
63
55
|
end
|
64
56
|
|
65
|
-
class HttpMethod < T::Enum
|
66
|
-
enums do
|
67
|
-
GET = new
|
68
|
-
POST = new
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
sig do
|
73
|
-
params(endpoint: String, retries: Integer, backoff: Integer)
|
74
|
-
.returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
|
75
|
-
end
|
76
57
|
def get(endpoint, retries = 0, backoff = 1)
|
77
|
-
request(
|
58
|
+
request(:GET, endpoint, nil, retries, backoff)
|
78
59
|
end
|
79
60
|
|
80
|
-
sig do
|
81
|
-
params(endpoint: String, body: String, retries: Integer, backoff: Integer)
|
82
|
-
.returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
|
83
|
-
end
|
84
61
|
def post(endpoint, body, retries = 0, backoff = 1)
|
85
|
-
request(
|
62
|
+
request(:POST, endpoint, body, retries, backoff)
|
86
63
|
end
|
87
64
|
|
88
|
-
sig do
|
89
|
-
params(method: HttpMethod, endpoint: String, body: T.nilable(String), retries: Integer, backoff: Integer)
|
90
|
-
.returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
|
91
|
-
end
|
92
65
|
def request(method, endpoint, body, retries = 0, backoff = 1)
|
93
66
|
if @local_mode
|
94
67
|
return nil, nil
|
@@ -107,9 +80,9 @@ module Statsig
|
|
107
80
|
res = @connection_pool.with do |conn|
|
108
81
|
request = conn.headers('STATSIG-CLIENT-TIME' => (Time.now.to_f * 1000).to_i.to_s)
|
109
82
|
case method
|
110
|
-
when
|
83
|
+
when :GET
|
111
84
|
request.get(url)
|
112
|
-
when
|
85
|
+
when :POST
|
113
86
|
request.post(url, body: body)
|
114
87
|
end
|
115
88
|
end
|
@@ -132,28 +105,8 @@ module Statsig
|
|
132
105
|
request(method, endpoint, body, retries - 1, backoff * @backoff_multiplier)
|
133
106
|
end
|
134
107
|
|
135
|
-
def check_gate(user, gate_name)
|
136
|
-
request_body = JSON.generate({ 'user' => user&.serialize(false), 'gateName' => gate_name })
|
137
|
-
response, = post('check_gate', request_body)
|
138
|
-
return JSON.parse(response.body) unless response.nil?
|
139
|
-
|
140
|
-
false
|
141
|
-
rescue StandardError
|
142
|
-
false
|
143
|
-
end
|
144
|
-
|
145
|
-
def get_config(user, dynamic_config_name)
|
146
|
-
request_body = JSON.generate({ 'user' => user&.serialize(false), 'configName' => dynamic_config_name })
|
147
|
-
response, = post('get_config', request_body)
|
148
|
-
return JSON.parse(response.body) unless response.nil?
|
149
|
-
|
150
|
-
nil
|
151
|
-
rescue StandardError
|
152
|
-
nil
|
153
|
-
end
|
154
|
-
|
155
108
|
def post_logs(events)
|
156
|
-
json_body = JSON.generate({
|
109
|
+
json_body = JSON.generate({ events: events, statsigMetadata: Statsig.get_statsig_metadata })
|
157
110
|
post('log_event', json_body, @post_logs_retry_limit)
|
158
111
|
rescue StandardError
|
159
112
|
|