statsig 1.25.2 → 1.27.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/client_initialize_helpers.rb +29 -3
- data/lib/diagnostics.rb +51 -24
- data/lib/error_boundary.rb +30 -44
- data/lib/evaluator.rb +6 -5
- data/lib/hash_utils.rb +17 -0
- data/lib/network.rb +54 -43
- data/lib/spec_store.rb +97 -53
- data/lib/statsig.rb +16 -4
- data/lib/statsig_driver.rb +101 -59
- data/lib/statsig_errors.rb +1 -0
- data/lib/statsig_logger.rb +26 -17
- data/lib/statsig_options.rb +14 -0
- data/lib/ua_parser.rb +1 -0
- metadata +55 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4d0e32be6be9e6110bf6237eb4ba33728dfde66385272bb9a15412662455873
|
4
|
+
data.tar.gz: '03408269143b235e02fc8be9f650ed2d4fc778ddf3cc7ffb7242ed9b9494ab73'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dac08983696816714e346ff1381fa2e83847375d5cee5bd33eb533a83e92be53f33a8fc5217a63b6856f723ca9063a631d4beee260bff95673329f6bfcdd5097
|
7
|
+
data.tar.gz: 8ad5c492697b2b8cb7c06eac670b03230190dbbe9210f4f8ab9bd951bd73ed0c3c91f45353fc4466d2d1295c09366ae95cae109521d98d1041c629d61202c092
|
@@ -1,4 +1,7 @@
|
|
1
1
|
# typed: true
|
2
|
+
|
3
|
+
require_relative 'hash_utils'
|
4
|
+
|
2
5
|
$empty_eval_result = {
|
3
6
|
:gate_value => false,
|
4
7
|
:json_value => {},
|
@@ -9,10 +12,12 @@ $empty_eval_result = {
|
|
9
12
|
|
10
13
|
module ClientInitializeHelpers
|
11
14
|
class ResponseFormatter
|
12
|
-
def initialize(evaluator, user)
|
15
|
+
def initialize(evaluator, user, hash, client_sdk_key)
|
13
16
|
@evaluator = evaluator
|
14
17
|
@user = user
|
15
18
|
@specs = evaluator.spec_store.get_raw_specs
|
19
|
+
@hash = hash
|
20
|
+
@client_sdk_key = client_sdk_key
|
16
21
|
end
|
17
22
|
|
18
23
|
def get_responses(key)
|
@@ -24,6 +29,13 @@ module ClientInitializeHelpers
|
|
24
29
|
private
|
25
30
|
|
26
31
|
def to_response(config_name, config_spec)
|
32
|
+
target_app_id = @evaluator.spec_store.get_app_id_for_sdk_key(@client_sdk_key)
|
33
|
+
config_target_apps = config_spec['targetAppIDs']
|
34
|
+
|
35
|
+
unless target_app_id.nil? || config_target_apps.nil? || config_target_apps.include?(target_app_id)
|
36
|
+
return nil
|
37
|
+
end
|
38
|
+
|
27
39
|
eval_result = @evaluator.eval_spec(@user, config_spec)
|
28
40
|
if eval_result.nil?
|
29
41
|
return nil
|
@@ -33,6 +45,8 @@ module ClientInitializeHelpers
|
|
33
45
|
:gate_value => eval_result.gate_value,
|
34
46
|
:json_value => eval_result.json_value,
|
35
47
|
:rule_id => eval_result.rule_id,
|
48
|
+
:group_name => eval_result.group_name,
|
49
|
+
:id_type => eval_result.id_type,
|
36
50
|
:config_delegate => eval_result.config_delegate,
|
37
51
|
:is_experiment_group => eval_result.is_experiment_group,
|
38
52
|
:secondary_exposures => eval_result.secondary_exposures,
|
@@ -52,10 +66,14 @@ module ClientInitializeHelpers
|
|
52
66
|
end
|
53
67
|
|
54
68
|
result['value'] = safe_eval_result[:gate_value]
|
69
|
+
result["group_name"] = safe_eval_result[:group_name]
|
70
|
+
result["id_type"] = safe_eval_result[:id_type]
|
55
71
|
when 'dynamic_config'
|
56
72
|
id_type = config_spec['idType']
|
57
73
|
result['value'] = safe_eval_result[:json_value]
|
58
74
|
result["group"] = safe_eval_result[:rule_id]
|
75
|
+
result["group_name"] = safe_eval_result[:group_name]
|
76
|
+
result["id_type"] = safe_eval_result[:id_type]
|
59
77
|
result["is_device_based"] = id_type.is_a?(String) && id_type.downcase == 'stableid'
|
60
78
|
else
|
61
79
|
return nil
|
@@ -67,6 +85,7 @@ module ClientInitializeHelpers
|
|
67
85
|
|
68
86
|
if entity_type == 'layer'
|
69
87
|
populate_layer_fields(config_spec, safe_eval_result, result)
|
88
|
+
result.delete('id_type') # not exposed for layer configs in /initialize
|
70
89
|
end
|
71
90
|
|
72
91
|
hashed_name = hash_name(config_name)
|
@@ -126,7 +145,14 @@ module ClientInitializeHelpers
|
|
126
145
|
end
|
127
146
|
|
128
147
|
def hash_name(name)
|
129
|
-
|
148
|
+
case @hash
|
149
|
+
when 'none'
|
150
|
+
return name
|
151
|
+
when 'sha256'
|
152
|
+
return Statsig::HashUtils.sha256(name)
|
153
|
+
when 'djb2'
|
154
|
+
return Statsig::HashUtils.djb2(name)
|
155
|
+
end
|
130
156
|
end
|
131
157
|
end
|
132
|
-
end
|
158
|
+
end
|
data/lib/diagnostics.rb
CHANGED
@@ -7,14 +7,18 @@ module Statsig
|
|
7
7
|
extend T::Sig
|
8
8
|
|
9
9
|
sig { returns(String) }
|
10
|
-
|
10
|
+
attr_accessor :context
|
11
11
|
|
12
12
|
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
13
13
|
attr_reader :markers
|
14
14
|
|
15
|
+
sig { returns(T::Hash[String, Numeric]) }
|
16
|
+
attr_accessor :sample_rates
|
17
|
+
|
15
18
|
def initialize(context)
|
16
19
|
@context = context
|
17
20
|
@markers = []
|
21
|
+
@sample_rates = {}
|
18
22
|
end
|
19
23
|
|
20
24
|
sig do
|
@@ -22,33 +26,37 @@ module Statsig
|
|
22
26
|
key: String,
|
23
27
|
action: String,
|
24
28
|
step: T.any(String, NilClass),
|
25
|
-
|
26
|
-
metadata: T.any(T::Hash[Symbol, T.untyped], NilClass)
|
29
|
+
tags: T::Hash[Symbol, T.untyped]
|
27
30
|
).void
|
28
31
|
end
|
29
32
|
|
30
|
-
def mark(key, action, step
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
def mark(key, action, step, tags)
|
34
|
+
marker = {
|
35
|
+
key: key,
|
36
|
+
action: action,
|
37
|
+
timestamp: (Time.now.to_f * 1000).to_i
|
38
|
+
}
|
39
|
+
if !step.nil?
|
40
|
+
marker[:step] = step
|
41
|
+
end
|
42
|
+
tags.each do |key, val|
|
43
|
+
unless val.nil?
|
44
|
+
marker[key] = val
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@markers.push(marker)
|
39
48
|
end
|
40
49
|
|
41
50
|
sig do
|
42
51
|
params(
|
43
52
|
key: String,
|
44
53
|
step: T.any(String, NilClass),
|
45
|
-
|
46
|
-
metadata: T.any(T::Hash[Symbol, T.untyped], NilClass)
|
54
|
+
tags: T::Hash[Symbol, T.untyped]
|
47
55
|
).returns(Tracker)
|
48
56
|
end
|
49
|
-
def track(key, step = nil,
|
50
|
-
tracker = Tracker.new(self, key, step,
|
51
|
-
tracker.start(
|
57
|
+
def track(key, step = nil, tags = {})
|
58
|
+
tracker = Tracker.new(self, key, step, tags)
|
59
|
+
tracker.start(**tags)
|
52
60
|
tracker
|
53
61
|
end
|
54
62
|
|
@@ -61,10 +69,29 @@ module Statsig
|
|
61
69
|
}
|
62
70
|
end
|
63
71
|
|
72
|
+
def serialize_with_sampling
|
73
|
+
marker_keys = @markers.map { |e| e[:key] }
|
74
|
+
unique_marker_keys = marker_keys.uniq { |e| e }
|
75
|
+
sampled_marker_keys = unique_marker_keys.select do |key|
|
76
|
+
@sample_rates.key?(key) && !self.class.sample(@sample_rates[key])
|
77
|
+
end
|
78
|
+
final_markers = @markers.select do |marker|
|
79
|
+
!sampled_marker_keys.include?(marker[:key])
|
80
|
+
end
|
81
|
+
{
|
82
|
+
context: @context.clone,
|
83
|
+
markers: final_markers
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
64
87
|
def clear_markers
|
65
88
|
@markers.clear
|
66
89
|
end
|
67
90
|
|
91
|
+
def self.sample(rate_over_ten_thousand)
|
92
|
+
rand * 10_000 < rate_over_ten_thousand
|
93
|
+
end
|
94
|
+
|
68
95
|
class Context
|
69
96
|
INITIALIZE = 'initialize'.freeze
|
70
97
|
CONFIG_SYNC = 'config_sync'.freeze
|
@@ -81,22 +108,22 @@ module Statsig
|
|
81
108
|
diagnostics: Diagnostics,
|
82
109
|
key: String,
|
83
110
|
step: T.any(String, NilClass),
|
84
|
-
|
111
|
+
tags: T::Hash[Symbol, T.untyped]
|
85
112
|
).void
|
86
113
|
end
|
87
|
-
def initialize(diagnostics, key, step,
|
114
|
+
def initialize(diagnostics, key, step, tags = {})
|
88
115
|
@diagnostics = diagnostics
|
89
116
|
@key = key
|
90
117
|
@step = step
|
91
|
-
@
|
118
|
+
@tags = tags
|
92
119
|
end
|
93
120
|
|
94
|
-
def start(
|
95
|
-
@diagnostics.mark(@key, 'start', @step,
|
121
|
+
def start(**tags)
|
122
|
+
@diagnostics.mark(@key, 'start', @step, tags.nil? ? {} : tags.merge(@tags))
|
96
123
|
end
|
97
124
|
|
98
|
-
def end(
|
99
|
-
@diagnostics.mark(@key, 'end', @step,
|
125
|
+
def end(**tags)
|
126
|
+
@diagnostics.mark(@key, 'end', @step, tags.nil? ? {} : tags.merge(@tags))
|
100
127
|
end
|
101
128
|
end
|
102
129
|
end
|
data/lib/error_boundary.rb
CHANGED
@@ -9,70 +9,56 @@ module Statsig
|
|
9
9
|
class ErrorBoundary
|
10
10
|
extend T::Sig
|
11
11
|
|
12
|
-
sig { returns(T.any(StatsigLogger, NilClass)) }
|
13
|
-
attr_accessor :logger
|
14
|
-
|
15
12
|
sig { params(sdk_key: String).void }
|
16
13
|
def initialize(sdk_key)
|
17
14
|
@sdk_key = sdk_key
|
18
15
|
@seen = Set.new
|
19
16
|
end
|
20
17
|
|
21
|
-
def sample_diagnostics
|
22
|
-
rand(10_000).zero?
|
23
|
-
end
|
24
|
-
|
25
18
|
def capture(task:, recover: -> {}, caller: nil)
|
26
|
-
if !caller.nil? && Diagnostics::API_CALL_KEYS.include?(caller) && sample_diagnostics
|
27
|
-
diagnostics = Diagnostics.new('api_call')
|
28
|
-
tracker = diagnostics.track(caller)
|
29
|
-
end
|
30
19
|
begin
|
31
20
|
res = task.call
|
32
|
-
|
33
|
-
|
34
|
-
tracker&.end(false)
|
35
|
-
if e.is_a?(Statsig::UninitializedError) or e.is_a?(Statsig::ValueError)
|
21
|
+
rescue StandardError, SystemStackError => e
|
22
|
+
if e.is_a?(Statsig::UninitializedError) || e.is_a?(Statsig::ValueError)
|
36
23
|
raise e
|
37
24
|
end
|
25
|
+
|
38
26
|
puts '[Statsig]: An unexpected exception occurred.'
|
39
|
-
log_exception(e)
|
27
|
+
log_exception(e, tag: caller)
|
40
28
|
res = recover.call
|
41
29
|
end
|
42
|
-
@logger&.log_diagnostics_event(diagnostics)
|
43
30
|
return res
|
44
31
|
end
|
45
32
|
|
46
33
|
private
|
47
34
|
|
48
|
-
def log_exception(exception)
|
49
|
-
|
50
|
-
|
51
|
-
if @seen.include?(name)
|
52
|
-
return
|
53
|
-
end
|
54
|
-
|
55
|
-
@seen << name
|
56
|
-
meta = Statsig.get_statsig_metadata
|
57
|
-
http = HTTP.headers(
|
58
|
-
{
|
59
|
-
'STATSIG-API-KEY' => @sdk_key,
|
60
|
-
'STATSIG-SDK-TYPE' => meta['sdkType'],
|
61
|
-
'STATSIG-SDK-VERSION' => meta['sdkVersion'],
|
62
|
-
'Content-Type' => 'application/json; charset=UTF-8'
|
63
|
-
}).accept(:json)
|
64
|
-
body = {
|
65
|
-
'exception' => name,
|
66
|
-
'info' => {
|
67
|
-
'trace' => exception.backtrace.to_s,
|
68
|
-
'message' => exception.message
|
69
|
-
}.to_s,
|
70
|
-
'statsigMetadata' => meta
|
71
|
-
}
|
72
|
-
http.post($endpoint, body: JSON.generate(body))
|
73
|
-
rescue
|
35
|
+
def log_exception(exception, tag: nil)
|
36
|
+
name = exception.class.name
|
37
|
+
if @seen.include?(name)
|
74
38
|
return
|
75
39
|
end
|
40
|
+
|
41
|
+
@seen << name
|
42
|
+
meta = Statsig.get_statsig_metadata
|
43
|
+
http = HTTP.headers(
|
44
|
+
{
|
45
|
+
'STATSIG-API-KEY' => @sdk_key,
|
46
|
+
'STATSIG-SDK-TYPE' => meta['sdkType'],
|
47
|
+
'STATSIG-SDK-VERSION' => meta['sdkVersion'],
|
48
|
+
'Content-Type' => 'application/json; charset=UTF-8'
|
49
|
+
}).accept(:json)
|
50
|
+
body = {
|
51
|
+
'exception' => name,
|
52
|
+
'info' => {
|
53
|
+
'trace' => exception.backtrace.to_s,
|
54
|
+
'message' => exception.message
|
55
|
+
}.to_s,
|
56
|
+
'statsigMetadata' => meta,
|
57
|
+
'tag' => tag
|
58
|
+
}
|
59
|
+
http.post($endpoint, body: JSON.generate(body))
|
60
|
+
rescue StandardError
|
61
|
+
return
|
76
62
|
end
|
77
63
|
end
|
78
|
-
end
|
64
|
+
end
|
data/lib/evaluator.rb
CHANGED
@@ -17,8 +17,8 @@ module Statsig
|
|
17
17
|
class Evaluator
|
18
18
|
attr_accessor :spec_store
|
19
19
|
|
20
|
-
def initialize(network, options, error_callback, diagnostics)
|
21
|
-
@spec_store = Statsig::SpecStore.new(network, options, error_callback, diagnostics)
|
20
|
+
def initialize(network, options, error_callback, diagnostics, error_boundary, logger)
|
21
|
+
@spec_store = Statsig::SpecStore.new(network, options, error_callback, diagnostics, error_boundary, logger)
|
22
22
|
UAParser.initialize_async
|
23
23
|
CountryLookup.initialize_async
|
24
24
|
|
@@ -98,12 +98,12 @@ module Statsig
|
|
98
98
|
eval_spec(user, @spec_store.get_layer(layer_name))
|
99
99
|
end
|
100
100
|
|
101
|
-
def get_client_initialize_response(user)
|
101
|
+
def get_client_initialize_response(user, hash, client_sdk_key)
|
102
102
|
if @spec_store.is_ready_for_checks == false
|
103
103
|
return nil
|
104
104
|
end
|
105
105
|
|
106
|
-
formatter = ClientInitializeHelpers::ResponseFormatter.new(self, user)
|
106
|
+
formatter = ClientInitializeHelpers::ResponseFormatter.new(self, user, hash, client_sdk_key)
|
107
107
|
|
108
108
|
evaluated_keys = {}
|
109
109
|
if user.user_id.nil? == false
|
@@ -123,6 +123,7 @@ module Statsig
|
|
123
123
|
"generator" => "statsig-ruby-sdk",
|
124
124
|
"evaluated_keys" => evaluated_keys,
|
125
125
|
"time" => 0,
|
126
|
+
"hash_used" => hash
|
126
127
|
}
|
127
128
|
end
|
128
129
|
|
@@ -199,7 +200,7 @@ module Statsig
|
|
199
200
|
@spec_store.initial_config_sync_time,
|
200
201
|
@spec_store.init_reason
|
201
202
|
),
|
202
|
-
group_name:
|
203
|
+
group_name: 'default',
|
203
204
|
id_type: config['idType']
|
204
205
|
)
|
205
206
|
end
|
data/lib/hash_utils.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Statsig
|
2
|
+
class HashUtils
|
3
|
+
def self.djb2(input_str)
|
4
|
+
hash = 0
|
5
|
+
input_str.each_char.each do |c|
|
6
|
+
hash = (hash << 5) - hash + c.ord
|
7
|
+
hash &= hash
|
8
|
+
end
|
9
|
+
hash &= 0xFFFFFFFF # Convert to unsigned 32-bit integer
|
10
|
+
return hash.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.sha256(input_str)
|
14
|
+
return Digest::SHA256.base64digest(input_str)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/network.rb
CHANGED
@@ -5,8 +5,9 @@ require 'json'
|
|
5
5
|
require 'securerandom'
|
6
6
|
require 'sorbet-runtime'
|
7
7
|
require 'uri_helper'
|
8
|
+
require 'connection_pool'
|
8
9
|
|
9
|
-
|
10
|
+
RETRY_CODES = [408, 500, 502, 503, 504, 522, 524, 599].freeze
|
10
11
|
|
11
12
|
module Statsig
|
12
13
|
class NetworkError < StandardError
|
@@ -22,7 +23,6 @@ module Statsig
|
|
22
23
|
extend T::Sig
|
23
24
|
|
24
25
|
sig { params(server_secret: String, options: StatsigOptions, backoff_mult: Integer).void }
|
25
|
-
|
26
26
|
def initialize(server_secret, options, backoff_mult = 10)
|
27
27
|
super()
|
28
28
|
URIHelper.initialize(options)
|
@@ -33,29 +33,35 @@ module Statsig
|
|
33
33
|
@post_logs_retry_backoff = options.post_logs_retry_backoff
|
34
34
|
@post_logs_retry_limit = options.post_logs_retry_limit
|
35
35
|
@session_id = SecureRandom.uuid
|
36
|
-
|
36
|
+
@connection_pool = ConnectionPool.new(size: 3) do
|
37
|
+
meta = Statsig.get_statsig_metadata
|
38
|
+
client = HTTP.use(:auto_inflate).headers(
|
39
|
+
{
|
40
|
+
'STATSIG-API-KEY' => @server_secret,
|
41
|
+
'STATSIG-SERVER-SESSION-ID' => @session_id,
|
42
|
+
'Content-Type' => 'application/json; charset=UTF-8',
|
43
|
+
'STATSIG-SDK-TYPE' => meta['sdkType'],
|
44
|
+
'STATSIG-SDK-VERSION' => meta['sdkVersion'],
|
45
|
+
'Accept-Encoding' => 'gzip'
|
46
|
+
}
|
47
|
+
).accept(:json)
|
48
|
+
if @timeout
|
49
|
+
client = client.timeout(@timeout)
|
50
|
+
end
|
37
51
|
|
38
|
-
|
39
|
-
|
52
|
+
client
|
53
|
+
end
|
54
|
+
end
|
40
55
|
|
56
|
+
sig do
|
57
|
+
params(endpoint: String, body: String, retries: Integer, backoff: Integer)
|
58
|
+
.returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)])
|
59
|
+
end
|
41
60
|
def post_helper(endpoint, body, retries = 0, backoff = 1)
|
42
61
|
if @local_mode
|
43
62
|
return nil, nil
|
44
63
|
end
|
45
64
|
|
46
|
-
meta = Statsig.get_statsig_metadata
|
47
|
-
http = HTTP.headers(
|
48
|
-
{
|
49
|
-
"STATSIG-API-KEY" => @server_secret,
|
50
|
-
"STATSIG-CLIENT-TIME" => (Time.now.to_f * 1000).to_i.to_s,
|
51
|
-
"STATSIG-SERVER-SESSION-ID" => @session_id,
|
52
|
-
"Content-Type" => "application/json; charset=UTF-8",
|
53
|
-
"STATSIG-SDK-TYPE" => meta['sdkType'],
|
54
|
-
"STATSIG-SDK-VERSION" => meta['sdkVersion'],
|
55
|
-
}).accept(:json)
|
56
|
-
if @timeout
|
57
|
-
http = http.timeout(@timeout)
|
58
|
-
end
|
59
65
|
backoff_adjusted = backoff > 10 ? backoff += Random.rand(10) : backoff # to deter overlap
|
60
66
|
if @post_logs_retry_backoff
|
61
67
|
if @post_logs_retry_backoff.is_a? Integer
|
@@ -66,48 +72,53 @@ module Statsig
|
|
66
72
|
end
|
67
73
|
url = URIHelper.build_url(endpoint)
|
68
74
|
begin
|
69
|
-
res =
|
75
|
+
res = @connection_pool.with do |conn|
|
76
|
+
conn.headers('STATSIG-CLIENT-TIME' => (Time.now.to_f * 1000).to_i.to_s).post(url, body: body)
|
77
|
+
end
|
70
78
|
rescue StandardError => e
|
71
79
|
## network error retry
|
72
|
-
return nil, e unless retries
|
80
|
+
return nil, e unless retries.positive?
|
81
|
+
|
73
82
|
sleep backoff_adjusted
|
74
83
|
return post_helper(endpoint, body, retries - 1, backoff * @backoff_multiplier)
|
75
84
|
end
|
76
85
|
return res, nil if res.status.success?
|
77
|
-
|
86
|
+
|
87
|
+
unless retries.positive? && RETRY_CODES.include?(res.code)
|
88
|
+
return res, NetworkError.new("Got an exception when making request to #{url}: #{res.to_s}",
|
89
|
+
res.status.to_i)
|
90
|
+
end
|
91
|
+
|
78
92
|
## status code retry
|
79
93
|
sleep backoff_adjusted
|
80
94
|
post_helper(endpoint, body, retries - 1, backoff * @backoff_multiplier)
|
81
95
|
end
|
82
96
|
|
83
97
|
def check_gate(user, gate_name)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
98
|
+
request_body = JSON.generate({ 'user' => user&.serialize(false), 'gateName' => gate_name })
|
99
|
+
response, = post_helper('check_gate', request_body)
|
100
|
+
return JSON.parse(response.body) unless response.nil?
|
101
|
+
|
102
|
+
false
|
103
|
+
rescue StandardError
|
104
|
+
false
|
92
105
|
end
|
93
106
|
|
94
107
|
def get_config(user, dynamic_config_name)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
108
|
+
request_body = JSON.generate({ 'user' => user&.serialize(false), 'configName' => dynamic_config_name })
|
109
|
+
response, = post_helper('get_config', request_body)
|
110
|
+
return JSON.parse(response.body) unless response.nil?
|
111
|
+
|
112
|
+
nil
|
113
|
+
rescue StandardError
|
114
|
+
nil
|
103
115
|
end
|
104
116
|
|
105
117
|
def post_logs(events)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
118
|
+
json_body = JSON.generate({ 'events' => events, 'statsigMetadata' => Statsig.get_statsig_metadata })
|
119
|
+
post_helper('log_event', json_body, @post_logs_retry_limit)
|
120
|
+
rescue StandardError
|
121
|
+
|
111
122
|
end
|
112
123
|
end
|
113
|
-
end
|
124
|
+
end
|