statsig 1.18.0 → 1.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/statsig.rb +90 -1
- data/lib/statsig_driver.rb +62 -16
- data/lib/statsig_logger.rb +16 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 354a77a658a3232a8695d82136d3e84e5bf0ce2199d06af9fee216eaae7d5dcd
|
4
|
+
data.tar.gz: 3be67ca270e61eedd92fb3aaa96b4f28ff1b79feee3ec4b1a33bdc2d000f8c2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f2461d11144a2e822178d69dad1ff50ebb2a4cd14f7b5dc46704b9c285a56d494f512b8058361f0a3ba3c71d899a6b9afc2fe51618abbe73784c6a937c39125
|
7
|
+
data.tar.gz: 45ac2d3a06f60c1cb0a81b109df9d06e1f479d384023e2009343b6d6f74b5d806fdf86e85b5d09ad8f1e55b07ca8c1b010cb23f7c8de2e9594b1092b323c8708
|
data/lib/statsig.rb
CHANGED
@@ -35,6 +35,28 @@ module Statsig
|
|
35
35
|
@shared_instance&.check_gate(user, gate_name)
|
36
36
|
end
|
37
37
|
|
38
|
+
sig { params(user: StatsigUser, gate_name: String).returns(T::Boolean) }
|
39
|
+
##
|
40
|
+
# Gets the boolean result of a gate, evaluated against the given user.
|
41
|
+
#
|
42
|
+
# @param user A StatsigUser object used for the evaluation
|
43
|
+
# @param gate_name The name of the gate being checked
|
44
|
+
def self.check_gate_with_exposure_logging_disabled(user, gate_name)
|
45
|
+
ensure_initialized
|
46
|
+
@shared_instance&.check_gate(user, gate_name, StatsigDriver::CheckGateOptions.new(log_exposure: false))
|
47
|
+
end
|
48
|
+
|
49
|
+
sig { params(user: StatsigUser, gate_name: String).void }
|
50
|
+
##
|
51
|
+
# Logs an exposure event for the gate
|
52
|
+
#
|
53
|
+
# @param user A StatsigUser object used for the evaluation
|
54
|
+
# @param gate_name The name of the gate being checked
|
55
|
+
def self.manually_log_gate_exposure(user, gate_name)
|
56
|
+
ensure_initialized
|
57
|
+
@shared_instance&.manually_log_gate_exposure(user, gate_name)
|
58
|
+
end
|
59
|
+
|
38
60
|
sig { params(user: StatsigUser, dynamic_config_name: String).returns(DynamicConfig) }
|
39
61
|
##
|
40
62
|
# Get the values of a dynamic config, evaluated against the given user. An exposure event will automatically be logged for the dynamic config.
|
@@ -46,6 +68,28 @@ module Statsig
|
|
46
68
|
@shared_instance&.get_config(user, dynamic_config_name)
|
47
69
|
end
|
48
70
|
|
71
|
+
sig { params(user: StatsigUser, dynamic_config_name: String).returns(DynamicConfig) }
|
72
|
+
##
|
73
|
+
# Get the values of a dynamic config, evaluated against the given user.
|
74
|
+
#
|
75
|
+
# @param user A StatsigUser object used for the evaluation
|
76
|
+
# @param dynamic_config_name The name of the dynamic config
|
77
|
+
def self.get_config_with_exposure_logging_disabled(user, dynamic_config_name)
|
78
|
+
ensure_initialized
|
79
|
+
@shared_instance&.get_config(user, dynamic_config_name, StatsigDriver::GetConfigOptions.new(log_exposure: false))
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { params(user: StatsigUser, dynamic_config: String).void }
|
83
|
+
##
|
84
|
+
# Logs an exposure event for the dynamic config
|
85
|
+
#
|
86
|
+
# @param user A StatsigUser object used for the evaluation
|
87
|
+
# @param dynamic_config_name The name of the dynamic config
|
88
|
+
def self.manually_log_config_exposure(user, dynamic_config)
|
89
|
+
ensure_initialized
|
90
|
+
@shared_instance&.manually_log_config_exposure(user, dynamic_config)
|
91
|
+
end
|
92
|
+
|
49
93
|
sig { params(user: StatsigUser, experiment_name: String).returns(DynamicConfig) }
|
50
94
|
##
|
51
95
|
# Get the values of an experiment, evaluated against the given user. An exposure event will automatically be logged for the experiment.
|
@@ -57,6 +101,28 @@ module Statsig
|
|
57
101
|
@shared_instance&.get_experiment(user, experiment_name)
|
58
102
|
end
|
59
103
|
|
104
|
+
sig { params(user: StatsigUser, experiment_name: String).returns(DynamicConfig) }
|
105
|
+
##
|
106
|
+
# Get the values of an experiment, evaluated against the given user.
|
107
|
+
#
|
108
|
+
# @param user A StatsigUser object used for the evaluation
|
109
|
+
# @param experiment_name The name of the experiment
|
110
|
+
def self.get_experiment_with_exposure_logging_disabled(user, experiment_name)
|
111
|
+
ensure_initialized
|
112
|
+
@shared_instance&.get_experiment(user, experiment_name, StatsigDriver::GetExperimentOptions.new(log_exposure: false))
|
113
|
+
end
|
114
|
+
|
115
|
+
sig { params(user: StatsigUser, experiment_name: String).void }
|
116
|
+
##
|
117
|
+
# Logs an exposure event for the experiment
|
118
|
+
#
|
119
|
+
# @param user A StatsigUser object used for the evaluation
|
120
|
+
# @param experiment_name The name of the experiment
|
121
|
+
def self.manually_log_experiment_exposure(user, experiment_name)
|
122
|
+
ensure_initialized
|
123
|
+
@shared_instance&.manually_log_config_exposure(user, experiment_name)
|
124
|
+
end
|
125
|
+
|
60
126
|
sig { params(user: StatsigUser, layer_name: String).returns(Layer) }
|
61
127
|
##
|
62
128
|
# Get the values of a layer, evaluated against the given user.
|
@@ -69,6 +135,29 @@ module Statsig
|
|
69
135
|
@shared_instance&.get_layer(user, layer_name)
|
70
136
|
end
|
71
137
|
|
138
|
+
sig { params(user: StatsigUser, layer_name: String).returns(Layer) }
|
139
|
+
##
|
140
|
+
# Get the values of a layer, evaluated against the given user.
|
141
|
+
#
|
142
|
+
# @param user A StatsigUser object used for the evaluation
|
143
|
+
# @param layer_name The name of the layer
|
144
|
+
def self.get_layer_with_exposure_logging_disabled(user, layer_name)
|
145
|
+
ensure_initialized
|
146
|
+
@shared_instance&.get_layer(user, layer_name, StatsigDriver::GetLayerOptions.new(log_exposure: false))
|
147
|
+
end
|
148
|
+
|
149
|
+
sig { params(user: StatsigUser, layer_name: String, parameter_name: String).returns(Layer) }
|
150
|
+
##
|
151
|
+
# Logs an exposure event for the parameter in the given layer
|
152
|
+
#
|
153
|
+
# @param user A StatsigUser object used for the evaluation
|
154
|
+
# @param layer_name The name of the layer
|
155
|
+
# @param parameter_name The name of the parameter in the layer
|
156
|
+
def self.manually_log_layer_parameter_exposure(user, layer_name, parameter_name)
|
157
|
+
ensure_initialized
|
158
|
+
@shared_instance&.manually_log_layer_parameter_exposure(user, layer_name, parameter_name)
|
159
|
+
end
|
160
|
+
|
72
161
|
sig { params(user: StatsigUser,
|
73
162
|
event_name: String,
|
74
163
|
value: T.any(String, Integer, Float, NilClass),
|
@@ -136,7 +225,7 @@ module Statsig
|
|
136
225
|
def self.get_statsig_metadata
|
137
226
|
{
|
138
227
|
'sdkType' => 'ruby-server',
|
139
|
-
'sdkVersion' => '1.
|
228
|
+
'sdkVersion' => '1.19.0',
|
140
229
|
}
|
141
230
|
end
|
142
231
|
|
data/lib/statsig_driver.rb
CHANGED
@@ -45,9 +45,13 @@ class StatsigDriver
|
|
45
45
|
})
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
class CheckGateOptions < T::Struct
|
49
|
+
prop :log_exposure, T::Boolean, default: true
|
50
|
+
end
|
51
|
+
|
52
|
+
sig { params(user: StatsigUser, gate_name: String, options: CheckGateOptions).returns(T::Boolean) }
|
49
53
|
|
50
|
-
def check_gate(user, gate_name)
|
54
|
+
def check_gate(user, gate_name, options = CheckGateOptions.new)
|
51
55
|
@err_boundary.capture(-> {
|
52
56
|
user = verify_inputs(user, gate_name, "gate_name")
|
53
57
|
|
@@ -60,7 +64,9 @@ class StatsigDriver
|
|
60
64
|
res = check_gate_fallback(user, gate_name)
|
61
65
|
# exposure logged by the server
|
62
66
|
else
|
63
|
-
|
67
|
+
if options.log_exposure
|
68
|
+
@logger.log_gate_exposure(user, res.name, res.gate_value, res.rule_id, res.secondary_exposures, res.evaluation_details)
|
69
|
+
end
|
64
70
|
end
|
65
71
|
|
66
72
|
res.gate_value
|
@@ -68,27 +74,55 @@ class StatsigDriver
|
|
68
74
|
|
69
75
|
end
|
70
76
|
|
71
|
-
sig { params(user: StatsigUser,
|
77
|
+
sig { params(user: StatsigUser, gate_name: String).void }
|
72
78
|
|
73
|
-
def
|
79
|
+
def manually_log_gate_exposure(user, gate_name)
|
80
|
+
res = @evaluator.check_gate(user, gate_name)
|
81
|
+
context = {'is_manual_exposure' => true}
|
82
|
+
@logger.log_gate_exposure(user, gate_name, res.gate_value, res.rule_id, res.secondary_exposures, res.evaluation_details, context)
|
83
|
+
end
|
84
|
+
|
85
|
+
class GetConfigOptions < T::Struct
|
86
|
+
prop :log_exposure, T::Boolean, default: true
|
87
|
+
end
|
88
|
+
|
89
|
+
sig { params(user: StatsigUser, dynamic_config_name: String, options: GetConfigOptions).returns(DynamicConfig) }
|
90
|
+
|
91
|
+
def get_config(user, dynamic_config_name, options = GetConfigOptions.new)
|
74
92
|
@err_boundary.capture(-> {
|
75
93
|
user = verify_inputs(user, dynamic_config_name, "dynamic_config_name")
|
76
|
-
get_config_impl(user, dynamic_config_name)
|
94
|
+
get_config_impl(user, dynamic_config_name, options)
|
77
95
|
}, -> { DynamicConfig.new(dynamic_config_name) })
|
78
96
|
end
|
79
97
|
|
80
|
-
|
98
|
+
class GetExperimentOptions < T::Struct
|
99
|
+
prop :log_exposure, T::Boolean, default: true
|
100
|
+
end
|
81
101
|
|
82
|
-
|
102
|
+
sig { params(user: StatsigUser, experiment_name: String, options: GetExperimentOptions).returns(DynamicConfig) }
|
103
|
+
|
104
|
+
def get_experiment(user, experiment_name, options = GetExperimentOptions.new)
|
83
105
|
@err_boundary.capture(-> {
|
84
106
|
user = verify_inputs(user, experiment_name, "experiment_name")
|
85
|
-
get_config_impl(user, experiment_name)
|
107
|
+
get_config_impl(user, experiment_name, options)
|
86
108
|
}, -> { DynamicConfig.new(experiment_name) })
|
87
109
|
end
|
88
110
|
|
89
|
-
sig { params(user: StatsigUser,
|
111
|
+
sig { params(user: StatsigUser, config_name: String).void }
|
90
112
|
|
91
|
-
def
|
113
|
+
def manually_log_config_exposure(user, config_name)
|
114
|
+
res = @evaluator.get_config(user, config_name)
|
115
|
+
context = {'is_manual_exposure' => true}
|
116
|
+
@logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.evaluation_details, context)
|
117
|
+
end
|
118
|
+
|
119
|
+
class GetLayerOptions < T::Struct
|
120
|
+
prop :log_exposure, T::Boolean, default: true
|
121
|
+
end
|
122
|
+
|
123
|
+
sig { params(user: StatsigUser, layer_name: String, options: GetLayerOptions).returns(Layer) }
|
124
|
+
|
125
|
+
def get_layer(user, layer_name, options = GetLayerOptions.new)
|
92
126
|
@err_boundary.capture(-> {
|
93
127
|
user = verify_inputs(user, layer_name, "layer_name")
|
94
128
|
|
@@ -104,15 +138,25 @@ class StatsigDriver
|
|
104
138
|
res = get_config_fallback(user, res.config_delegate)
|
105
139
|
# exposure logged by the server
|
106
140
|
end
|
107
|
-
|
108
|
-
|
141
|
+
|
142
|
+
exposure_log_func = options.log_exposure ? lambda { |layer, parameter_name|
|
109
143
|
@logger.log_layer_exposure(user, layer, parameter_name, res)
|
110
|
-
}
|
144
|
+
} : nil
|
145
|
+
Layer.new(res.name, res.json_value, res.rule_id, exposure_log_func)
|
111
146
|
}, -> {
|
112
147
|
Layer.new(layer_name)
|
113
148
|
})
|
114
149
|
end
|
115
150
|
|
151
|
+
sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void }
|
152
|
+
|
153
|
+
def manually_log_layer_parameter_exposure(user, layer_name, parameter_name)
|
154
|
+
res = @evaluator.get_layer(user, layer_name)
|
155
|
+
layer = Layer.new(layer_name, res.json_value, res.rule_id)
|
156
|
+
context = {'is_manual_exposure' => true}
|
157
|
+
@logger.log_layer_exposure(user, layer, parameter_name, res, context)
|
158
|
+
end
|
159
|
+
|
116
160
|
def log_event(user, event_name, value = nil, metadata = nil)
|
117
161
|
@err_boundary.capture(-> {
|
118
162
|
if !user.nil? && !user.instance_of?(StatsigUser)
|
@@ -186,7 +230,7 @@ class StatsigDriver
|
|
186
230
|
normalize_user(user)
|
187
231
|
end
|
188
232
|
|
189
|
-
def get_config_impl(user, config_name)
|
233
|
+
def get_config_impl(user, config_name, options)
|
190
234
|
res = @evaluator.get_config(user, config_name)
|
191
235
|
if res.nil?
|
192
236
|
res = Statsig::ConfigResult.new(config_name)
|
@@ -196,7 +240,9 @@ class StatsigDriver
|
|
196
240
|
res = get_config_fallback(user, config_name)
|
197
241
|
# exposure logged by the server
|
198
242
|
else
|
199
|
-
|
243
|
+
if options.log_exposure
|
244
|
+
@logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.evaluation_details)
|
245
|
+
end
|
200
246
|
end
|
201
247
|
|
202
248
|
DynamicConfig.new(res.name, res.json_value, res.rule_id)
|
data/lib/statsig_logger.rb
CHANGED
@@ -32,7 +32,7 @@ module Statsig
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def log_gate_exposure(user, gate_name, value, rule_id, secondary_exposures, eval_details)
|
35
|
+
def log_gate_exposure(user, gate_name, value, rule_id, secondary_exposures, eval_details, context = nil)
|
36
36
|
event = StatsigEvent.new($gate_exposure_event)
|
37
37
|
event.user = user
|
38
38
|
event.metadata = {
|
@@ -44,10 +44,11 @@ module Statsig
|
|
44
44
|
event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
|
45
45
|
|
46
46
|
safe_add_eval_details(eval_details, event)
|
47
|
+
safe_add_exposure_context(context, event)
|
47
48
|
log_event(event)
|
48
49
|
end
|
49
50
|
|
50
|
-
def log_config_exposure(user, config_name, rule_id, secondary_exposures, eval_details)
|
51
|
+
def log_config_exposure(user, config_name, rule_id, secondary_exposures, eval_details, context = nil)
|
51
52
|
event = StatsigEvent.new($config_exposure_event)
|
52
53
|
event.user = user
|
53
54
|
event.metadata = {
|
@@ -58,10 +59,11 @@ module Statsig
|
|
58
59
|
event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
|
59
60
|
|
60
61
|
safe_add_eval_details(eval_details, event)
|
62
|
+
safe_add_exposure_context(context, event)
|
61
63
|
log_event(event)
|
62
64
|
end
|
63
65
|
|
64
|
-
def log_layer_exposure(user, layer, parameter_name, config_evaluation)
|
66
|
+
def log_layer_exposure(user, layer, parameter_name, config_evaluation, context = nil)
|
65
67
|
exposures = config_evaluation.undelegated_sec_exps
|
66
68
|
allocated_experiment = ''
|
67
69
|
is_explicit = (config_evaluation.explicit_parameters&.include? parameter_name) || false
|
@@ -83,6 +85,7 @@ module Statsig
|
|
83
85
|
event.secondary_exposures = exposures.is_a?(Array) ? exposures : []
|
84
86
|
|
85
87
|
safe_add_eval_details(config_evaluation.evaluation_details, event)
|
88
|
+
safe_add_exposure_context(context, event)
|
86
89
|
log_event(event)
|
87
90
|
end
|
88
91
|
|
@@ -144,5 +147,15 @@ module Statsig
|
|
144
147
|
event.metadata['initTime'] = eval_details.init_time
|
145
148
|
event.metadata['serverTime'] = eval_details.server_time
|
146
149
|
end
|
150
|
+
|
151
|
+
def safe_add_exposure_context(context, event)
|
152
|
+
if context.nil?
|
153
|
+
return
|
154
|
+
end
|
155
|
+
|
156
|
+
if context['is_manual_exposure']
|
157
|
+
event.metadata['isManualExposure'] = 'true'
|
158
|
+
end
|
159
|
+
end
|
147
160
|
end
|
148
161
|
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.
|
4
|
+
version: 1.19.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-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -215,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
215
215
|
- !ruby/object:Gem::Version
|
216
216
|
version: '0'
|
217
217
|
requirements: []
|
218
|
-
rubygems_version: 3.3.
|
218
|
+
rubygems_version: 3.3.7
|
219
219
|
signing_key:
|
220
220
|
specification_version: 4
|
221
221
|
summary: Statsig server SDK for Ruby
|