statsig 1.24.5 → 1.24.6

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 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