statsig 2.0.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27afba91b3e46ea8661d399ef0dc2696c6372bb214dbb993ea986e5b456edb7e
4
- data.tar.gz: c06043637e4ce2ae3bbdef95ccc8a0713717b04e8149b46a0f70da502aa729db
3
+ metadata.gz: dd554df4ba15f0d1addaecc5e76502c1218c1b08842152eeeffd0f6e121dbcba
4
+ data.tar.gz: b1d19d91608685488db9705e213559c4a36c21731b0822137b55fab0693a871d
5
5
  SHA512:
6
- metadata.gz: ac429df53886c94abbd1b801adb96a8bab92e6c8c73aa4f910a2a505b5a3bf65ba3d3b844cca6014f6dbac0b17ce05d7a967d5fde260f0bc6f3021e60c84e8af
7
- data.tar.gz: 14d9c181b6093d56ca7bba00873ff1806cc063ac43608d9ff3cde9e2396423faf58fe50b4096ac4faf7806bcfaec4c946c325f9be20a83b4f311e521162958bb
6
+ metadata.gz: b360f7fb18b06e87b538eb005ce0f7344f8a633a1cb9915d3e6f74e5b0fab3b7d87d46ab4b4498548e66766d00a4f60a9bb5f502c270e09925e67c24575da7ca
7
+ data.tar.gz: 337e0fd5ecfc11fa5565980df91d21ee17cc6586d49f1a18b333eaa4de1da29094c453a00daf1671ce8e6872d03882b85c169df6709aa41e543500cdc5c78057
@@ -92,12 +92,26 @@ module Statsig
92
92
  result[:rule_id] = eval_result.rule_id
93
93
 
94
94
  if include_exposures
95
- result[:secondary_exposures] = eval_result.secondary_exposures
95
+ result[:secondary_exposures] = hash_exposures(eval_result.secondary_exposures, hash_algo)
96
96
  end
97
97
 
98
98
  [hashed_name, result]
99
99
  end
100
100
 
101
+ def self.hash_exposures(exposures, hash_algo)
102
+ return nil if exposures.nil?
103
+ hashed_exposures = []
104
+ exposures.each do |exp|
105
+ hashed_exposures << {
106
+ gate: hash_name(exp[:gate], hash_algo),
107
+ gateValue: exp[:gateValue],
108
+ ruleID: exp[:ruleID]
109
+ }
110
+ end
111
+
112
+ hashed_exposures
113
+ end
114
+
101
115
  def self.populate_experiment_fields(config_name, config_spec, eval_result, result, evaluator)
102
116
  result[:is_user_in_experiment] = eval_result.is_experiment_group
103
117
  result[:is_experiment_active] = config_spec[:isActive] == true
@@ -132,7 +146,7 @@ module Statsig
132
146
  end
133
147
 
134
148
  if include_exposures
135
- result[:undelegated_secondary_exposures] = eval_result.undelegated_sec_exps || []
149
+ result[:undelegated_secondary_exposures] = hash_exposures(eval_result.undelegated_sec_exps || [], hash_algo)
136
150
  end
137
151
  end
138
152
 
data/lib/constants.rb CHANGED
@@ -123,5 +123,11 @@ module Statsig
123
123
  # API Operators (Segments)
124
124
  OP_IN_SEGMENT_LIST = 'in_segment_list'.freeze
125
125
  OP_NOT_IN_SEGMENT_LIST = 'not_in_segment_list'.freeze
126
+
127
+ # API Operators (Array)
128
+ OP_ARRAY_CONTAINS_ANY = 'array_contains_any'.freeze
129
+ OP_ARRAY_CONTAINS_NONE = 'array_contains_none'.freeze
130
+ OP_ARRAY_CONTAINS_ALL = 'array_contains_all'.freeze
131
+ OP_NOT_ARRAY_CONTAINS_ALL = 'not_array_contains_all'.freeze
126
132
  end
127
133
  end
@@ -53,7 +53,19 @@ class DynamicConfig
53
53
  index_sym = index.to_sym
54
54
  return default_value unless @value.key?(index_sym)
55
55
 
56
- return default_value if @value[index_sym].class != default_value.class and default_value.class != TrueClass and default_value.class != FalseClass
57
- @value[index_sym]
56
+ value = @value[index_sym]
57
+
58
+ case default_value
59
+ when Integer
60
+ return value.to_i if value.is_a?(Numeric) && default_value.is_a?(Integer)
61
+ when Float
62
+ return value.to_f if value.is_a?(Numeric) && default_value.is_a?(Float)
63
+ when TrueClass, FalseClass
64
+ return value if [true, false].include?(value)
65
+ else
66
+ return value if value.class == default_value.class
67
+ end
68
+
69
+ default_value
58
70
  end
59
71
  end
@@ -58,6 +58,18 @@ module EvaluationHelpers
58
58
  end
59
59
  end
60
60
 
61
+ def self.array_contains_any(value, target)
62
+ return false if value.nil? || target.nil?
63
+ value_set = value.to_set
64
+ return target.any? { |item| value_set.include?(item) || value_set.include?(item.to_i) }
65
+ end
66
+
67
+ def self.array_contains_all(value, target)
68
+ return false if value.nil? || target.nil?
69
+ value_set = value.to_set
70
+ return target.all? { |item| value_set.include?(item) || value_set.include?(item.to_i) }
71
+ end
72
+
61
73
  private
62
74
 
63
75
  def self.is_numeric(v)
@@ -73,4 +85,4 @@ module EvaluationHelpers
73
85
  end
74
86
  return time.to_i
75
87
  end
76
- end
88
+ end
data/lib/evaluator.rb CHANGED
@@ -246,7 +246,7 @@ module Statsig
246
246
  evaluated_keys: evaluated_keys,
247
247
  time: @spec_store.last_config_sync_time,
248
248
  hash_used: hash_algo,
249
- user: user.serialize(false),
249
+ user: user.serialize(true),
250
250
  sdkInfo: {sdkType: meta["sdkType"], sdkVersion: meta["sdkVersion"]},
251
251
  }
252
252
  end
@@ -542,6 +542,24 @@ module Statsig
542
542
  a.year == b.year && a.month == b.month && a.day == b.day
543
543
  })
544
544
 
545
+ # array
546
+ when Const::OP_ARRAY_CONTAINS_ANY
547
+ if value.is_a?(Array) && target.is_a?(Array)
548
+ return EvaluationHelpers.array_contains_any(value, target)
549
+ end
550
+ when Const::OP_ARRAY_CONTAINS_NONE
551
+ if value.is_a?(Array) && target.is_a?(Array)
552
+ return !EvaluationHelpers.array_contains_any(value, target)
553
+ end
554
+ when Const::OP_ARRAY_CONTAINS_ALL
555
+ if value.is_a?(Array) && target.is_a?(Array)
556
+ return EvaluationHelpers.array_contains_all(value, target)
557
+ end
558
+ when Const::OP_NOT_ARRAY_CONTAINS_ALL
559
+ if value.is_a?(Array) && target.is_a?(Array)
560
+ return !EvaluationHelpers.array_contains_all(value, target)
561
+ end
562
+
545
563
  # segments
546
564
  when Const::OP_IN_SEGMENT_LIST, Const::OP_NOT_IN_SEGMENT_LIST
547
565
  begin
@@ -670,10 +688,14 @@ module Statsig
670
688
  end
671
689
 
672
690
  def eval_pass_percent(user, rule, config_salt)
691
+ pass_percentage = rule[:passPercentage]
692
+ return true if pass_percentage == 100.0
693
+ return false if pass_percentage == 0.0
694
+
673
695
  unit_id = user.get_unit_id(rule[:idType]) || Const::EMPTY_STR
674
696
  rule_salt = rule[:salt] || rule[:id] || Const::EMPTY_STR
675
697
  hash = compute_user_hash("#{config_salt}.#{rule_salt}.#{unit_id}")
676
- return (hash % 10_000) < (rule[:passPercentage] * 100)
698
+ return (hash % 10_000) < (pass_percentage * 100)
677
699
  end
678
700
 
679
701
  def compute_user_hash(user_hash)
data/lib/layer.rb CHANGED
@@ -52,12 +52,31 @@ class Layer
52
52
  index_sym = index.to_sym
53
53
  return default_value unless @value.key?(index_sym)
54
54
 
55
- return default_value if @value[index_sym].class != default_value.class and default_value.class != TrueClass and default_value.class != FalseClass
55
+ value = @value[index_sym]
56
56
 
57
- if @exposure_log_func.is_a? Proc
58
- @exposure_log_func.call(self, index)
57
+ case default_value
58
+ when Integer
59
+ if @exposure_log_func.is_a? Proc
60
+ @exposure_log_func.call(self, index)
61
+ end
62
+ return value.to_i if value.is_a?(Numeric) && default_value.is_a?(Integer)
63
+ when Float
64
+ if @exposure_log_func.is_a? Proc
65
+ @exposure_log_func.call(self, index)
66
+ end
67
+ return value.to_f if value.is_a?(Numeric) && default_value.is_a?(Float)
68
+ when TrueClass, FalseClass
69
+ if @exposure_log_func.is_a? Proc
70
+ @exposure_log_func.call(self, index)
71
+ end
72
+ return value if [true, false].include?(value)
73
+ else
74
+ if @exposure_log_func.is_a? Proc
75
+ @exposure_log_func.call(self, index)
76
+ end
77
+ return value if value.class == default_value.class
59
78
  end
60
79
 
61
- @value[index_sym]
80
+ default_value
62
81
  end
63
82
  end
data/lib/statsig.rb CHANGED
@@ -363,7 +363,7 @@ module Statsig
363
363
  def self.get_statsig_metadata
364
364
  {
365
365
  'sdkType' => 'ruby-server',
366
- 'sdkVersion' => '2.0.0',
366
+ 'sdkVersion' => '2.1.0',
367
367
  'languageVersion' => RUBY_VERSION
368
368
  }
369
369
  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: 2.0.0
4
+ version: 2.1.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: 2024-08-01 00:00:00.000000000 Z
11
+ date: 2024-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler