statsig 1.6.2 → 1.6.3

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: 325d5430e48a3d71b68d2e284e20b66b0052bf1a4d9e99e7a92a84069b680ab8
4
- data.tar.gz: b227e1fede44928035b1a03ebc8e8c006425466b50b007f89c452f6a47b51cd6
3
+ metadata.gz: 9192f1c9886d3a3b18c0a2e70599e998b4784b23245e9064018ec31c98881b25
4
+ data.tar.gz: eb329d5f742ce2f77391f3f33ba4229852c2c68827643159b51fd870c1fb21d9
5
5
  SHA512:
6
- metadata.gz: 28017886b1a5d3f5c37e36680f0dfbd300cf5a0f6e0678430af69631486bc88689a622d74a63da1687ef7d610d612227d68cb58b85a7572b7cc5cfcaee0794dd
7
- data.tar.gz: 10a66e7674df116a65351b97b8d27055bacd46f021309c3256bc5605fe3a972416e2c595135262fc9d18117e447a5038db3ebe1b89cb71495f308430fe4d2a32
6
+ metadata.gz: e8a090dc289fe6994b08578b2d2884f9196f37f4104120c546dd11b3036bc939b84a343a643f15f8e12ca01a494f920206ee01a2302de5bcb71a94efb3048b76
7
+ data.tar.gz: 995f91cb599608d0691e8f598d7bc2aa50f0f1b652ad1fac83f3afdb9e950132e21a34aaee44c57797849fb99005cc9dea9d4664f3f4f0ba13afb75dd120c251
data/lib/config_result.rb CHANGED
@@ -3,11 +3,13 @@ class ConfigResult
3
3
  attr_accessor :gate_value
4
4
  attr_accessor :json_value
5
5
  attr_accessor :rule_id
6
+ attr_accessor :secondary_exposures
6
7
 
7
- def initialize(name, gate_value = false, json_value = {}, rule_id = '')
8
+ def initialize(name, gate_value = false, json_value = {}, rule_id = '', secondary_exposures = [])
8
9
  @name = name
9
10
  @gate_value = gate_value
10
11
  @json_value = json_value
11
12
  @rule_id = rule_id
13
+ @secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
12
14
  end
13
15
  end
data/lib/evaluator.rb CHANGED
@@ -32,18 +32,21 @@ class Evaluator
32
32
 
33
33
  def eval_spec(user, config)
34
34
  if config['enabled']
35
+ exposures = []
35
36
  i = 0
36
37
  until i >= config['rules'].length do
37
38
  rule = config['rules'][i]
38
39
  result = self.eval_rule(user, rule)
39
40
  return $fetch_from_server if result == $fetch_from_server
40
- if result
41
+ exposures = exposures + result["exposures"] if result["exposures"].is_a? Array
42
+ if result['value']
41
43
  pass = self.eval_pass_percent(user, rule, config['salt'])
42
44
  return ConfigResult.new(
43
45
  config['name'],
44
46
  pass,
45
47
  pass ? rule['returnValue'] : config['defaultValue'],
46
48
  rule['id'],
49
+ exposures
47
50
  )
48
51
  end
49
52
 
@@ -51,17 +54,28 @@ class Evaluator
51
54
  end
52
55
  end
53
56
 
54
- ConfigResult.new(config['name'], false, config['defaultValue'], 'default')
57
+ ConfigResult.new(config['name'], false, config['defaultValue'], 'default', [])
55
58
  end
56
59
 
57
60
  def eval_rule(user, rule)
61
+ exposures = []
62
+ pass = true
58
63
  i = 0
59
64
  until i >= rule['conditions'].length do
60
65
  result = self.eval_condition(user, rule['conditions'][i])
61
- return result unless result == true
66
+ if result == $fetch_from_server
67
+ return $fetch_from_server
68
+ end
69
+
70
+ if result.is_a?(Hash)
71
+ exposures = exposures + result["exposures"] if result["exposures"].is_a? Array
72
+ pass = false if result["value"] == false
73
+ elsif result == false
74
+ pass = false
75
+ end
62
76
  i += 1
63
77
  end
64
- true
78
+ { "value" => pass, "exposures" => exposures }
65
79
  end
66
80
 
67
81
  def eval_condition(user, condition)
@@ -82,7 +96,18 @@ class Evaluator
82
96
  when 'fail_gate', 'pass_gate'
83
97
  other_gate_result = self.check_gate(user, target)
84
98
  return $fetch_from_server if other_gate_result == $fetch_from_server
85
- return type == 'pass_gate' ? other_gate_result.gate_value : !other_gate_result.gate_value
99
+
100
+ gate_value = other_gate_result&.gate_value == true
101
+ new_exposure = {
102
+ "gate" => target,
103
+ "gateValue" => gate_value ? "true" : "false",
104
+ "ruleID" => other_gate_result&.rule_id
105
+ }
106
+ exposures = other_gate_result&.secondary_exposures&.append(new_exposure)
107
+ return {
108
+ "value" => type == 'pass_gate' ? gate_value : !gate_value,
109
+ "exposures" => exposures
110
+ }
86
111
  when 'ip_based'
87
112
  value = get_value_from_user(user, field) || get_value_from_ip(user, field)
88
113
  return $fetch_from_server if value == $fetch_from_server
@@ -58,7 +58,7 @@ class StatsigDriver
58
58
  res = check_gate_fallback(user, gate_name)
59
59
  # exposure logged by the server
60
60
  else
61
- @logger.log_gate_exposure(user, res.name, res.gate_value, res.rule_id)
61
+ @logger.log_gate_exposure(user, res.name, res.gate_value, res.rule_id, res.secondary_exposures)
62
62
  end
63
63
 
64
64
  res.gate_value
@@ -84,12 +84,19 @@ class StatsigDriver
84
84
  res = get_config_fallback(user, dynamic_config_name)
85
85
  # exposure logged by the server
86
86
  else
87
- @logger.log_config_exposure(user, res.name, res.rule_id)
87
+ @logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures)
88
88
  end
89
89
 
90
90
  DynamicConfig.new(res.name, res.json_value, res.rule_id)
91
91
  end
92
92
 
93
+ def get_experiment(user, experiment_name)
94
+ if !experiment_name.is_a?(String) || experiment_name.empty?
95
+ raise "Invalid experiment_name provided"
96
+ end
97
+ get_config(user, experiment_name)
98
+ end
99
+
93
100
  def log_event(user, event_name, value = nil, metadata = nil)
94
101
  if !user.nil? && !user.instance_of?(StatsigUser)
95
102
  raise 'Must provide a valid StatsigUser or nil'
data/lib/statsig_event.rb CHANGED
@@ -2,6 +2,7 @@ class StatsigEvent
2
2
  attr_accessor :value
3
3
  attr_accessor :metadata
4
4
  attr_accessor :statsig_metadata
5
+ attr_accessor :secondary_exposures
5
6
  attr_reader :user
6
7
 
7
8
  def initialize(event_name)
@@ -23,6 +24,7 @@ class StatsigEvent
23
24
  'user' => @user,
24
25
  'time' => @time,
25
26
  'statsigMetadata' => @statsig_metadata,
27
+ 'secondaryExposures' => @secondary_exposures
26
28
  }
27
29
  end
28
30
  end
@@ -21,7 +21,7 @@ class StatsigLogger
21
21
  end
22
22
  end
23
23
 
24
- def log_gate_exposure(user, gate_name, value, rule_id)
24
+ def log_gate_exposure(user, gate_name, value, rule_id, secondary_exposures)
25
25
  event = StatsigEvent.new($gate_exposure_event)
26
26
  event.user = user
27
27
  event.metadata = {
@@ -30,10 +30,11 @@ class StatsigLogger
30
30
  'ruleID' => rule_id
31
31
  }
32
32
  event.statsig_metadata = @statsig_metadata
33
+ event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
33
34
  log_event(event)
34
35
  end
35
36
 
36
- def log_config_exposure(user, config_name, rule_id)
37
+ def log_config_exposure(user, config_name, rule_id, secondary_exposures)
37
38
  event = StatsigEvent.new($config_exposure_event)
38
39
  event.user = user
39
40
  event.metadata = {
@@ -41,6 +42,7 @@ class StatsigLogger
41
42
  'ruleID' => rule_id
42
43
  }
43
44
  event.statsig_metadata = @statsig_metadata
45
+ event.secondary_exposures = secondary_exposures.is_a?(Array) ? secondary_exposures : []
44
46
  log_event(event)
45
47
  end
46
48
 
@@ -51,7 +53,7 @@ class StatsigLogger
51
53
  if @events.length == 0
52
54
  return
53
55
  end
54
- flush_events = @events.map { |e| e.serialize() }
56
+ flush_events = @events.map { |e| e.serialize }
55
57
  @events = []
56
58
 
57
59
  @network.post_logs(flush_events, @statsig_metadata)
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.6.2
4
+ version: 1.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Statsig, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-14 00:00:00.000000000 Z
11
+ date: 2021-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler