statsig 1.24.5 → 1.24.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1565b50f9e48bfcd6c456bc8e1681a9adbd523287f656b042c3cce803063d3b6
4
- data.tar.gz: 8dbf5c5879173b3c44e0e155c8e6e649af5e0cb184e1fdd18a47cc8875fb32c0
3
+ metadata.gz: 29818b483f3950c841a00a05ee3007414cc759498d7656703049417c43cbbae5
4
+ data.tar.gz: 36c190613ab7fded21de40e82c238c3c8374e6efba502a6774752a15d796e07d
5
5
  SHA512:
6
- metadata.gz: f8c6e02873f9274b49a42fe94f21d67eec6d2ba720841d107d1b0b3e7f39b3a208fc4bae478337829359e25d109f5e7409dffbd143e802ab5e1f1c2b0d08fcf0
7
- data.tar.gz: f75079d1ba3837d66a8386aa106d2bb4f75e78371dcc53cf09e1921610841d81a958e351e1f1a2f5786ebf0c44c43215a709edcb1e21dd45b563f8b2f4f8004d
6
+ metadata.gz: 30e3d1941bb46e4eb21469f82d2f398e1380fc144b1076f28e521081a9de052bf96ad27821ca93c515e3e308ca8d793dff75a504435a792c008b4623effeb6a5
7
+ data.tar.gz: 80eb7090f03d1dcb2a8e78492c6d80fe33e364fea1446330ad30c17eb06dbe8486f7ab1d2776e53e9f3b058f7c4925d4d89ce1f08494e3fd814928c3ac4bd537
data/lib/evaluator.rb CHANGED
@@ -447,16 +447,18 @@ module Statsig
447
447
  ua = get_value_from_user(user, 'userAgent')
448
448
  return nil unless ua.is_a?(String)
449
449
 
450
- parsed = @ua_parser.parse ua
451
- os = parsed.os
452
450
  case field.downcase
453
451
  when 'os_name', 'osname'
452
+ os = @ua_parser.parse_os(ua)
454
453
  return os&.family
455
454
  when 'os_version', 'osversion'
455
+ os = @ua_parser.parse_os(ua)
456
456
  return os&.version unless os&.version.nil?
457
457
  when 'browser_name', 'browsername'
458
+ parsed = @ua_parser.parse_ua(ua)
458
459
  return parsed.family
459
460
  when 'browser_version', 'browserversion'
461
+ parsed = @ua_parser.parse_ua(ua)
460
462
  return parsed.version.to_s
461
463
  else
462
464
  nil
data/lib/layer.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # typed: false
2
2
 
3
+ require 'sorbet-runtime'
3
4
  ##
4
5
  # Contains the current values from Statsig.
5
6
  # Will contain layer default values for all shared parameters in that layer.
data/lib/network.rb CHANGED
@@ -33,6 +33,7 @@ module Statsig
33
33
  @local_mode = options.local_mode
34
34
  @timeout = options.network_timeout
35
35
  @backoff_multiplier = backoff_mult
36
+ @post_logs_retry_limit = options.post_logs_retry_limit
36
37
  @session_id = SecureRandom.uuid
37
38
  end
38
39
 
@@ -57,18 +58,19 @@ module Statsig
57
58
  if @timeout
58
59
  http = http.timeout(@timeout)
59
60
  end
61
+ backoff_adjusted = backoff > 10 ? backoff += Random.rand(10) : backoff # to deter overlap
60
62
  begin
61
63
  res = http.post(@api + endpoint, body: body)
62
64
  rescue StandardError => e
63
65
  ## network error retry
64
66
  return nil, e unless retries > 0
65
- sleep backoff
67
+ sleep backoff_adjusted
66
68
  return post_helper(endpoint, body, retries - 1, backoff * @backoff_multiplier)
67
69
  end
68
70
  return res, nil if res.status.success?
69
71
  return nil, NetworkError.new("Got an exception when making request to #{@api + endpoint}: #{res.to_s}", res.status.to_i) unless retries > 0 && $retry_codes.include?(res.code)
70
72
  ## status code retry
71
- sleep backoff
73
+ sleep backoff_adjusted
72
74
  post_helper(endpoint, body, retries - 1, backoff * @backoff_multiplier)
73
75
  end
74
76
 
@@ -97,7 +99,7 @@ module Statsig
97
99
  def post_logs(events)
98
100
  begin
99
101
  json_body = JSON.generate({ 'events' => events, 'statsigMetadata' => Statsig.get_statsig_metadata })
100
- post_helper('log_event', json_body, 5)
102
+ post_helper('log_event', json_body, @post_logs_retry_limit)
101
103
  rescue
102
104
  end
103
105
  end
data/lib/statsig.rb CHANGED
@@ -148,7 +148,7 @@ module Statsig
148
148
  @shared_instance&.get_layer(user, layer_name, StatsigDriver::GetLayerOptions.new(log_exposure: false))
149
149
  end
150
150
 
151
- sig { params(user: StatsigUser, layer_name: String, parameter_name: String).returns(Layer) }
151
+ sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void }
152
152
  ##
153
153
  # Logs an exposure event for the parameter in the given layer
154
154
  #
@@ -227,7 +227,7 @@ module Statsig
227
227
  def self.get_statsig_metadata
228
228
  {
229
229
  'sdkType' => 'ruby-server',
230
- 'sdkVersion' => '1.24.5',
230
+ 'sdkVersion' => '1.24.6',
231
231
  }
232
232
  end
233
233
 
@@ -170,7 +170,6 @@ class StatsigDriver
170
170
  event.user = user
171
171
  event.value = value
172
172
  event.metadata = metadata
173
- event.statsig_metadata = Statsig.get_statsig_metadata
174
173
  @logger.log_event(event)
175
174
  })
176
175
  end
@@ -199,6 +198,7 @@ class StatsigDriver
199
198
  # @return [Hash]
200
199
  def get_client_initialize_response(user)
201
200
  @err_boundary.capture(-> {
201
+ validate_user(user)
202
202
  normalize_user(user)
203
203
  @evaluator.get_client_initialize_response(user)
204
204
  }, -> { nil })
data/lib/statsig_event.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  # typed: true
2
2
  class StatsigEvent
3
- attr_accessor :value
4
- attr_accessor :metadata
5
- attr_accessor :statsig_metadata
6
- attr_accessor :secondary_exposures
3
+ attr_accessor :value, :metadata, :statsig_metadata, :secondary_exposures
7
4
  attr_reader :user
8
5
 
9
6
  def initialize(event_name)
@@ -13,6 +10,7 @@ class StatsigEvent
13
10
  @secondary_exposures = nil
14
11
  @user = nil
15
12
  @time = (Time.now.to_f * 1000).to_i
13
+ @statsig_metadata = Statsig.get_statsig_metadata
16
14
  end
17
15
 
18
16
  def user=(value)
@@ -16,10 +16,10 @@ module Statsig
16
16
 
17
17
  @logging_pool = Concurrent::ThreadPoolExecutor.new(
18
18
  min_threads: [2, Concurrent.processor_count].min,
19
- max_threads: [2, Concurrent.processor_count].max,
19
+ max_threads: [5, Concurrent.processor_count].min,
20
20
  # max jobs pending before we start dropping
21
- max_queue: [2, Concurrent.processor_count].max * 5,
22
- fallback_policy: :discard,
21
+ max_queue: [5, Concurrent.processor_count].min * 5,
22
+ fallback_policy: :discard
23
23
  )
24
24
 
25
25
  @background_flush = periodic_flush
@@ -44,7 +44,6 @@ module Statsig
44
44
  }
45
45
  return false if not is_unique_exposure(user, $gate_exposure_event, metadata)
46
46
  event.metadata = metadata
47
- event.statsig_metadata = Statsig.get_statsig_metadata
48
47
 
49
48
  event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
50
49
 
@@ -62,7 +61,6 @@ module Statsig
62
61
  }
63
62
  return false if not is_unique_exposure(user, $config_exposure_event, metadata)
64
63
  event.metadata = metadata
65
- event.statsig_metadata = Statsig.get_statsig_metadata
66
64
  event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
67
65
 
68
66
  safe_add_eval_details(eval_details, event)
@@ -90,7 +88,6 @@ module Statsig
90
88
  }
91
89
  return false if not is_unique_exposure(user, $layer_exposure_event, metadata)
92
90
  event.metadata = metadata
93
- event.statsig_metadata = Statsig.get_statsig_metadata
94
91
  event.secondary_exposures = exposures.is_a?(Array) ? exposures : []
95
92
 
96
93
  safe_add_eval_details(config_evaluation.evaluation_details, event)
@@ -79,6 +79,10 @@ class StatsigOptions
79
79
  # Number of seconds before a network call is timed out
80
80
  attr_accessor :network_timeout
81
81
 
82
+ sig { returns(Integer) }
83
+ # Number of times to retry sending a batch of failed log events
84
+ attr_accessor :post_logs_retry_limit
85
+
82
86
  sig do
83
87
  params(
84
88
  environment: T.any(T::Hash[String, String], NilClass),
@@ -94,7 +98,8 @@ class StatsigOptions
94
98
  idlist_threadpool_size: Integer,
95
99
  disable_diagnostics_logging: T::Boolean,
96
100
  disable_sorbet_logging_handlers: T::Boolean,
97
- network_timeout: T.any(Integer, NilClass)
101
+ network_timeout: T.any(Integer, NilClass),
102
+ post_logs_retry_limit: Integer
98
103
  ).void
99
104
  end
100
105
 
@@ -112,7 +117,8 @@ class StatsigOptions
112
117
  idlist_threadpool_size: 3,
113
118
  disable_diagnostics_logging: false,
114
119
  disable_sorbet_logging_handlers: false,
115
- network_timeout: nil)
120
+ network_timeout: nil,
121
+ post_logs_retry_limit: 3)
116
122
  @environment = environment.is_a?(Hash) ? environment : nil
117
123
  @api_url_base = api_url_base
118
124
  @rulesets_sync_interval = rulesets_sync_interval
@@ -127,5 +133,6 @@ class StatsigOptions
127
133
  @disable_diagnostics_logging = disable_diagnostics_logging
128
134
  @disable_sorbet_logging_handlers = disable_sorbet_logging_handlers
129
135
  @network_timeout = network_timeout
136
+ @post_logs_retry_limit = post_logs_retry_limit
130
137
  end
131
138
  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.24.5
4
+ version: 1.24.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Statsig, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-03 00:00:00.000000000 Z
11
+ date: 2023-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.14'
47
+ version: 5.14.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.14'
54
+ version: 5.14.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: spy
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -123,19 +123,89 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '6.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: user_agent_parser
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.28.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.28.2
139
+ - !ruby/object:Gem::Dependency
140
+ name: parallel_tests
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
145
  version: '2.7'
132
- type: :runtime
146
+ type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
152
  version: '2.7'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.21'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.21'
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov-lcov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 0.7.0
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 0.7.0
181
+ - !ruby/object:Gem::Dependency
182
+ name: simplecov-cobertura
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '2.1'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '2.1'
195
+ - !ruby/object:Gem::Dependency
196
+ name: user_agent_parser
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: 2.15.0
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: 2.15.0
139
209
  - !ruby/object:Gem::Dependency
140
210
  name: http
141
211
  requirement: !ruby/object:Gem::Requirement