splitclient-rb 3.1.0.pre.rc9 → 3.1.0.pre.rc10

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
  SHA1:
3
- metadata.gz: 3037157b7408479db6d29868df4005078bf344c4
4
- data.tar.gz: 20b2c1ef05f4ab0ea4114a748ef513e0b95fcf51
3
+ metadata.gz: 37a7aea4e576c0285c8fe0b52407263314b3dbe1
4
+ data.tar.gz: 0dfcf521a72a8eeac66bf8a1e2a4bcb45ab7b6be
5
5
  SHA512:
6
- metadata.gz: 8894fab929d077ee1ab8906e0326076944a0bb4de41514dc8672e6d0ec0e21ffc9dc3394d6d66367c611304e4d6f81a4c4b9442acff078444e0391e490dc4577
7
- data.tar.gz: '01656839c7ca92686ee5b0623de195ce42caa66673cc7873baf010b08d5e5c5b71b018f1f4d17b2997f3dae2f4a4ef7944e2df081a8596d22360861414fa55c6'
6
+ metadata.gz: 01234be503798df68a17b5ac3182736a446cfe4c35fdad405a719e33d748adc1158f312e591601082fd52a7cec543ae5b76de09b1aa383db16152d162095cd37
7
+ data.tar.gz: 8baf6f0b69c26309421282d9c331abb94eae269be202742fd308cf7df8941ff07fd5f1c0c3d85ade401e84025305ae2715f085de57c3d0aca8ec0142a10d3466
@@ -6,6 +6,8 @@ module SplitIoClient
6
6
  module Adapters
7
7
  # Redis adapter used to provide interface to Redis
8
8
  class RedisAdapter
9
+ attr_reader :redis
10
+
9
11
  def initialize(redis_url)
10
12
  connection = redis_url.is_a?(Hash) ? redis_url : { url: redis_url }
11
13
 
@@ -58,6 +60,10 @@ module SplitIoClient
58
60
  Hash[keys.zip(@redis.mget(keys))]
59
61
  end
60
62
 
63
+ def append_to_string(key, val)
64
+ @redis.append(key, val)
65
+ end
66
+
61
67
  # Bool
62
68
  def set_bool(key, val)
63
69
  @redis.set(key, val.to_s)
@@ -111,6 +117,10 @@ module SplitIoClient
111
117
 
112
118
  @redis.del(key)
113
119
  end
120
+
121
+ def inc(key, inc = 1)
122
+ @redis.incrby(key, inc)
123
+ end
114
124
  end
115
125
  end
116
126
  end
@@ -18,6 +18,12 @@ module SplitIoClient
18
18
  end
19
19
  end
20
20
 
21
+ def add_bulk(key, treatments, time)
22
+ treatments.each do |split_name, treatment|
23
+ add(split_name, 'key_name' => key, 'treatment' => treatment, 'time' => time)
24
+ end
25
+ end
26
+
21
27
  # Get everything from the queue and leave it empty
22
28
  def clear
23
29
  @adapter.clear
@@ -3,6 +3,8 @@ module SplitIoClient
3
3
  module Repositories
4
4
  module Impressions
5
5
  class RedisRepository < Repository
6
+ IMPRESSIONS_SLICE = 1000
7
+
6
8
  def initialize(adapter, config)
7
9
  @adapter = adapter
8
10
  @config = config
@@ -15,6 +17,16 @@ module SplitIoClient
15
17
  )
16
18
  end
17
19
 
20
+ def add_bulk(key, treatments, time)
21
+ @adapter.redis.pipelined do
22
+ treatments.each_slice(IMPRESSIONS_SLICE) do |treatments_slice|
23
+ treatments_slice.each do |split_name, treatment|
24
+ add(split_name, 'key_name' => key, 'treatment' => treatment, 'time' => time)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
18
30
  # Get random impressions from redis in batches of size @config.impressions_queue_size,
19
31
  # delete fetched impressions afterwards
20
32
  def clear
@@ -4,7 +4,7 @@ module SplitIoClient
4
4
  # Repository which forwards impressions interface to the selected adapter
5
5
  class ImpressionsRepository < Repository
6
6
  extend Forwardable
7
- def_delegators :@adapter, :add, :clear, :empty?
7
+ def_delegators :@adapter, :add, :add_bulk, :clear, :empty?
8
8
 
9
9
  def initialize(adapter, config)
10
10
  @adapter = case adapter.class.to_s
@@ -0,0 +1,123 @@
1
+ module SplitIoClient
2
+ module Cache
3
+ module Repositories
4
+ module Metrics
5
+ class MemoryRepository
6
+ def initialize(_ = nil, adapter, config)
7
+ @counts = []
8
+ @latencies = []
9
+ @gauges = []
10
+
11
+ @config = config
12
+ end
13
+
14
+ def add_count(counter, delta)
15
+ counter_hash = @counts.find { |c| c[:name] == counter }
16
+ if counter_hash.nil?
17
+ counter_delta = SumAndCount.new
18
+ counter_delta.add_delta(delta)
19
+ @counts << { name: counter, delta: counter_delta }
20
+ else
21
+ counter_hash[:delta].add_delta(delta)
22
+ end
23
+ end
24
+
25
+ def add_latency(operation, time_in_ms, binary_search)
26
+ operation_hash = @latencies.find { |l| l[:operation] == operation }
27
+ if operation_hash.nil?
28
+ latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : [time_in_ms]
29
+ @latencies << { operation: operation, latencies: latencies_for_op }
30
+ else
31
+ latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : operation_hash[:latencies].push(time_in_ms)
32
+ end
33
+ end
34
+
35
+ def add_gauge(gauge, value)
36
+ gauge_hash = @gauges.find { |g| g[:name] == gauge }
37
+ if gauge_hash.nil?
38
+ gauge_value = ValueAndCount.new
39
+ gauge_value.set_value(value)
40
+ @gauges << { name: gauge, value: gauge_value }
41
+ else
42
+ gauge_hash[:value].set_value(value)
43
+ end
44
+ end
45
+
46
+ def counts
47
+ @counts.each_with_object({}) do |count, memo|
48
+ memo[count[:name]] = count[:delta].sum
49
+ end
50
+ end
51
+
52
+ def latencies
53
+ @latencies.each_with_object({}) do |latency, memo|
54
+ memo[latency[:operation]] = latency[:latencies]
55
+ end
56
+ end
57
+
58
+ def gauges
59
+ # TODO
60
+ end
61
+
62
+ def clear_counts
63
+ @counts = []
64
+ end
65
+
66
+ def clear_latencies
67
+ @latencies = []
68
+ end
69
+
70
+ def clear_gauges
71
+ @gauges = []
72
+ end
73
+
74
+ #
75
+ # small class to act as DTO for counts
76
+ #
77
+ class SumAndCount
78
+ attr_reader :count
79
+ attr_reader :sum
80
+
81
+ def initialize
82
+ @count = 0
83
+ @sum = 0
84
+ end
85
+
86
+ def add_delta(delta)
87
+ @count += 1
88
+ @sum += delta
89
+ end
90
+
91
+ def clear
92
+ @count = 0
93
+ @sum = 0
94
+ end
95
+ end
96
+
97
+ #
98
+ # small class to act as DTO for gauges
99
+ #
100
+ class ValueAndCount
101
+ attr_reader :count
102
+ attr_reader :value
103
+
104
+ def initialize
105
+ @count = 0
106
+ @value = 0
107
+ end
108
+
109
+ def set_value(value)
110
+ @count += 1
111
+ @value = value
112
+ end
113
+
114
+ def clear
115
+ @count = 0
116
+ @value = 0
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,92 @@
1
+ module SplitIoClient
2
+ module Cache
3
+ module Repositories
4
+ module Metrics
5
+ class RedisRepository < Repository
6
+ def initialize(adapter = nil, config)
7
+ @config = config
8
+ @adapter = adapter
9
+ end
10
+
11
+ def add_count(counter, delta)
12
+ prefixed_name = namespace_key("count.#{counter}")
13
+ counts = @adapter.find_strings_by_prefix(prefixed_name)
14
+
15
+ @adapter.inc(prefixed_name, delta)
16
+ end
17
+
18
+ def add_latency(operation, time_in_ms, binary_search)
19
+ prefixed_name = namespace_key("latency.#{operation}")
20
+ latencies = @adapter.find_strings_by_prefix(prefixed_name)
21
+
22
+ if operation == 'sdk.get_treatment'
23
+ @adapter.inc("#{prefixed_name}.#{binary_search.add_latency_millis(time_in_ms, true)}")
24
+ return
25
+ end
26
+
27
+ @adapter.append_to_string(prefixed_name, "#{time_in_ms},")
28
+ end
29
+
30
+ def add_gauge(gauge, value)
31
+ # TODO
32
+ end
33
+
34
+ def counts
35
+ keys = @adapter.find_strings_by_prefix(namespace_key('count'))
36
+
37
+ return [] if keys.empty?
38
+
39
+ @adapter.multiple_strings(keys).map do |name, data|
40
+ [name.gsub(namespace_key('count.'), ''), data]
41
+ end.to_h
42
+ end
43
+
44
+ def latencies
45
+ collected_latencies = {}
46
+ latencies_array = Array.new(BinarySearchLatencyTracker::BUCKETS.length, 0)
47
+ keys = @adapter.find_strings_by_prefix(namespace_key('latency'))
48
+
49
+ return [] if keys.empty?
50
+
51
+ found_latencies = @adapter.multiple_strings(keys).map do |name, data|
52
+ [name.gsub(namespace_key('latency.'), ''), data]
53
+ end.to_h
54
+
55
+ found_latencies.each do |key, value|
56
+ if key.start_with?('sdk.get_treatment')
57
+ index = key.gsub('sdk.get_treatment.', '').to_i
58
+ latencies_array[index] = value.to_i
59
+
60
+ next
61
+ end
62
+
63
+ collected_latencies[key] = value.split(',').map(&:to_f)
64
+ end
65
+
66
+ collected_latencies['sdk.get_treatment'] = latencies_array
67
+
68
+ collected_latencies
69
+ end
70
+
71
+ def gauges
72
+ # TODO
73
+ end
74
+
75
+ def clear_counts
76
+ keys = @adapter.find_strings_by_prefix(namespace_key('count'))
77
+ @adapter.delete(keys)
78
+ end
79
+
80
+ def clear_latencies
81
+ keys = @adapter.find_strings_by_prefix(namespace_key('latency'))
82
+ @adapter.delete(keys)
83
+ end
84
+
85
+ def clear_gauges
86
+ # TODO
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,21 @@
1
+ module SplitIoClient
2
+ module Cache
3
+ module Repositories
4
+ # Repository which forwards impressions interface to the selected adapter
5
+ class MetricsRepository < Repository
6
+ extend Forwardable
7
+ def_delegators :@adapter, :add_count, :add_latency, :add_gauge, :counts, :latencies, :gauges,
8
+ :clear_counts, :clear_latencies, :clear_gauges
9
+
10
+ def initialize(adapter, config)
11
+ @adapter = case adapter.class.to_s
12
+ when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
13
+ Repositories::Metrics::MemoryRepository.new(adapter, config)
14
+ when 'SplitIoClient::Cache::Adapters::RedisAdapter'
15
+ Repositories::Metrics::RedisRepository.new(adapter, config)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -52,16 +52,22 @@ module SplitIoClient
52
52
  # Increment the internal counter for the bucket this latency falls into.
53
53
  # @param millis
54
54
  #
55
- def add_latency_millis(millis)
55
+ def add_latency_millis(millis, return_index = false)
56
56
  index = find_bucket_index(millis * 1000)
57
+
58
+ return index if return_index
59
+
57
60
  @latencies[index] += 1
58
61
  @latencies
59
62
  end
60
63
 
61
64
  # Increment the internal counter for the bucket this latency falls into.
62
65
  # @param micros
63
- def add_latency_micros(micros)
66
+ def add_latency_micros(micros, return_index = false)
64
67
  index = find_bucket_index(micros)
68
+
69
+ return index if return_index
70
+
65
71
  @latencies[index] += 1
66
72
  @latencies
67
73
  end
@@ -32,12 +32,13 @@ module SplitIoClient
32
32
  # @return [int] queue size
33
33
  attr_accessor :queue_size
34
34
 
35
- def initialize(queue_size)
36
- @latencies = []
37
- @counts = []
38
- @gauges = []
35
+ def initialize(queue_size, config, repository)
39
36
  @queue_size = queue_size
40
37
  @binary_search = SplitIoClient::BinarySearchLatencyTracker.new
38
+
39
+ @config = config
40
+
41
+ @repository = repository
41
42
  end
42
43
 
43
44
  #
@@ -48,18 +49,9 @@ module SplitIoClient
48
49
  #
49
50
  # @return void
50
51
  def count(counter, delta)
51
- return if delta <= 0
52
+ return if (delta <= 0) || counter.nil? || counter.strip.empty?
52
53
 
53
- return if (counter.nil? || counter.strip.empty?)
54
-
55
- counter_hash = @counts.find { |c| c[:name] == counter }
56
- if counter_hash.nil?
57
- counter_delta = SumAndCount.new
58
- counter_delta.add_delta(delta)
59
- @counts << {name: counter, delta: counter_delta}
60
- else
61
- counter_hash[:delta].add_delta(delta)
62
- end
54
+ @repository.add_count(counter, delta)
63
55
  end
64
56
 
65
57
  #
@@ -70,18 +62,9 @@ module SplitIoClient
70
62
  #
71
63
  # @return void
72
64
  def time(operation, time_in_ms)
65
+ return if operation.nil? || operation.empty? || time_in_ms < 0
73
66
 
74
- if operation.nil? || operation.empty? || time_in_ms < 0
75
- return;
76
- end
77
-
78
- operation_hash = @latencies.find { |l| l[:operation] == operation }
79
- if operation_hash.nil?
80
- latencies_for_op = (operation == 'sdk.get_treatment') ? @binary_search.add_latency_millis(time_in_ms) : [time_in_ms]
81
- @latencies << {operation: operation, latencies: latencies_for_op}
82
- else
83
- latencies_for_op = (operation == 'sdk.get_treatment') ? @binary_search.add_latency_millis(time_in_ms) : operation_hash[:latencies].push(time_in_ms)
84
- end
67
+ @repository.add_latency(operation, time_in_ms, @binary_search)
85
68
  end
86
69
 
87
70
  #
@@ -92,67 +75,9 @@ module SplitIoClient
92
75
  #
93
76
  # @return void
94
77
  def gauge(gauge, value)
95
- if gauge.nil? || gauge.empty?
96
- return
97
- end
78
+ return if gauge.nil? || gauge.empty?
98
79
 
99
- gauge_hash = @gauges.find { |g| g[:name] == gauge }
100
- if gauge_hash.nil?
101
- gauge_value = ValueAndCount.new
102
- gauge_value.set_value(value)
103
- @gauges << {name: gauge, value: gauge_value}
104
- else
105
- gauge_hash[:value].set_value(value)
106
- end
80
+ @repository.add_gauge(gauge, value)
107
81
  end
108
-
109
82
  end
110
-
111
- #
112
- # small class to act as DTO for counts
113
- #
114
- class SumAndCount
115
- attr_reader :count
116
- attr_reader :sum
117
-
118
- def initialize
119
- @count = 0
120
- @sum = 0
121
- end
122
-
123
- def add_delta(delta)
124
- @count++
125
- @sum += delta
126
- end
127
-
128
- def clear
129
- @count = 0
130
- @sum = 0
131
- end
132
- end
133
-
134
- #
135
- # small class to act as DTO for gauges
136
- #
137
- class ValueAndCount
138
- attr_reader :count
139
- attr_reader :value
140
-
141
- def initialize
142
- @count = 0
143
- @value = 0
144
- end
145
-
146
- def set_value(value)
147
- @count += 1
148
- @value = value
149
- end
150
-
151
- def clear
152
- @count = 0
153
- @value = 0
154
- end
155
-
156
- end
157
-
158
83
  end
@@ -35,14 +35,16 @@ module SplitIoClient
35
35
  # @param api_key [String] the API key for your split account
36
36
  #
37
37
  # @return [SplitIoClient] split.io client instance
38
- def initialize(api_key, config, splits_repository, segments_repository, impressions_repository, sdk_blocker)
38
+ def initialize(api_key, config, splits_repository, segments_repository, impressions_repository, metrics_repository, sdk_blocker)
39
39
  @api_key = api_key
40
40
  @config = config
41
- @metrics = Metrics.new(100)
42
41
 
43
42
  @splits_repository = splits_repository
44
43
  @segments_repository = segments_repository
45
44
  @impressions_repository = impressions_repository
45
+ @metrics_repository = metrics_repository
46
+
47
+ @metrics = Metrics.new(100, @config, @metrics_repository)
46
48
 
47
49
  @sdk_blocker = sdk_blocker
48
50
 
@@ -62,11 +64,12 @@ module SplitIoClient
62
64
  metrics_sender
63
65
  impressions_sender
64
66
  when :consumer
65
- metrics_sender
67
+ # Do nothing in background
66
68
  when :producer
67
69
  split_store
68
70
  segment_store
69
71
  impressions_sender
72
+ metrics_sender
70
73
 
71
74
  sleep unless ENV['SPLITCLIENT_ENV'] == 'test'
72
75
  end
@@ -248,53 +251,35 @@ module SplitIoClient
248
251
  #
249
252
  # @return [void]
250
253
  def post_metrics
251
- if @metrics.latencies.empty?
254
+ if @metrics_repository.latencies.empty?
252
255
  @config.logger.debug('No latencies to report.') if @config.debug_enabled
253
256
  else
254
- @metrics.latencies.each do |l|
255
- metrics_time = {}
256
- metrics_time = {name: l[:operation], latencies: l[:latencies]}
257
+ @metrics_repository.latencies.each do |name, latencies|
258
+ metrics_time = { name: name, latencies: latencies }
257
259
  res = post_api('/metrics/time', metrics_time)
258
260
  if res.status / 100 != 2
259
261
  @config.logger.error("Unexpected status code while posting time metrics: #{res.status}")
260
262
  else
261
- @config.logger.debug("Metric time reported: #{metrics_time.size()}") if @config.debug_enabled
263
+ @config.logger.debug("Metric time reported: #{metrics_time.size}") if @config.debug_enabled
262
264
  end
263
265
  end
264
266
  end
265
- @metrics.latencies.clear
267
+ @metrics_repository.clear_latencies
266
268
 
267
- if @metrics.counts.empty?
269
+ if @metrics_repository.counts.empty?
268
270
  @config.logger.debug('No counts to report.') if @config.debug_enabled
269
271
  else
270
- @metrics.counts.each do |c|
271
- metrics_count = {}
272
- metrics_count = {name: c[:name], delta: c[:delta].sum}
272
+ @metrics_repository.counts.each do |name, count|
273
+ metrics_count = { name: name, delta: count }
273
274
  res = post_api('/metrics/counter', metrics_count)
274
275
  if res.status / 100 != 2
275
276
  @config.logger.error("Unexpected status code while posting count metrics: #{res.status}")
276
277
  else
277
- @config.logger.debug("Metric counts reported: #{metrics_count.size()}") if @config.debug_enabled
278
- end
279
- end
280
- end
281
- @metrics.counts.clear
282
-
283
- if @metrics.gauges.empty?
284
- @config.logger.debug('No gauges to report.') if @config.debug_enabled
285
- else
286
- @metrics.gauges.each do |g|
287
- metrics_gauge = {}
288
- metrics_gauge = {name: g[:name], value: g[:gauge].value}
289
- res = post_api('/metrics/gauge', metrics_gauge)
290
- if res.status / 100 != 2
291
- @config.logger.error("Unexpected status code while posting gauge metrics: #{res.status}")
292
- else
293
- @config.logger.debug("Metric gauge reported: #{metrics_gauge.size()}") if @config.debug_enabled
278
+ @config.logger.debug("Metric counts reported: #{metrics_count.size}") if @config.debug_enabled
294
279
  end
295
280
  end
296
281
  end
297
- @metrics.gauges.clear
282
+ @metrics_repository.clear_counts
298
283
  end
299
284
 
300
285
  private
@@ -15,6 +15,9 @@ require 'cache/repositories/splits_repository'
15
15
  require 'cache/repositories/impressions_repository'
16
16
  require 'cache/repositories/impressions/memory_repository'
17
17
  require 'cache/repositories/impressions/redis_repository'
18
+ require 'cache/repositories/metrics_repository'
19
+ require 'cache/repositories/metrics/memory_repository'
20
+ require 'cache/repositories/metrics/redis_repository'
18
21
  require 'cache/stores/sdk_blocker'
19
22
  require 'cache/stores/segment_store'
20
23
  require 'cache/stores/split_store'
@@ -44,6 +44,10 @@ module SplitIoClient
44
44
  opts[:cache_adapter] || SplitConfig.default_cache_adapter, :sized_queue_adapter, @redis_url, @impressions_queue_size
45
45
  )
46
46
 
47
+ @metrics_adapter = SplitConfig.init_cache_adapter(
48
+ opts[:cache_adapter] || SplitConfig.default_cache_adapter, :map_adapter, @redis_url, false
49
+ )
50
+
47
51
  @logger = opts[:logger] || SplitConfig.default_logger
48
52
  @debug_enabled = opts[:debug_enabled] || SplitConfig.default_debug
49
53
  @transport_debug_enabled = opts[:transport_debug_enabled] || SplitConfig.default_debug
@@ -89,6 +93,12 @@ module SplitIoClient
89
93
  # @return [Object] Impressions adapter instance
90
94
  attr_reader :impressions_adapter
91
95
 
96
+ #
97
+ # The cache adapter to store metrics in
98
+ #
99
+ # @return [Symbol] Metrics adapter
100
+ attr_reader :metrics_adapter
101
+
92
102
  #
93
103
  # The connection timeout for network connections in seconds.
94
104
  #
@@ -179,6 +189,10 @@ module SplitIoClient
179
189
  :memory
180
190
  end
181
191
 
192
+ def self.default_metrics_adapter
193
+ :memory
194
+ end
195
+
182
196
  #
183
197
  # The default read timeout value
184
198
  #
@@ -131,7 +131,7 @@ module SplitIoClient
131
131
  # @param api_key [String] the API key for your split account
132
132
  #
133
133
  # @return [SplitIoClient] split.io client instance
134
- def initialize(api_key, config = {}, adapter = nil, localhost_mode = false, splits_repository, segments_repository, impressions_repository)
134
+ def initialize(api_key, config = {}, adapter = nil, localhost_mode = false, splits_repository, segments_repository, impressions_repository, metrics_repository)
135
135
  @localhost_mode = localhost_mode
136
136
  @localhost_mode_features = []
137
137
 
@@ -140,6 +140,7 @@ module SplitIoClient
140
140
  @splits_repository = splits_repository
141
141
  @segments_repository = segments_repository
142
142
  @impressions_repository = impressions_repository
143
+ @metrics_repository = metrics_repository
143
144
 
144
145
  if api_key == LOCALHOST_MODE
145
146
  @localhost_mode = true
@@ -150,17 +151,23 @@ module SplitIoClient
150
151
  end
151
152
 
152
153
  def get_treatments(key, split_names, attributes = nil)
153
-
154
154
  # This localhost behavior must live in in localhost_spit_factory#client
155
155
  if is_localhost_mode?
156
- return split_names.each_with_object({}) do | (name), memo|
156
+ return split_names.each_with_object({}) do |name, memo|
157
157
  memo.merge!(name => get_localhost_treatment(name))
158
158
  end
159
159
  end
160
160
 
161
- @splits_repository.get_splits(split_names).each_with_object({}) do |(name, data), memo|
162
- memo.merge!(name => get_treatment(key, name, attributes, data))
161
+ bucketing_key, matching_key = keys_from_key(key)
162
+ bucketing_key = matching_key if bucketing_key.nil?
163
+
164
+ treatments = @splits_repository.get_splits(split_names).each_with_object({}) do |(name, data), memo|
165
+ memo.merge!(name => get_treatment(matching_key, name, attributes, data, false))
163
166
  end
167
+
168
+ @impressions_repository.add_bulk(matching_key, treatments, (Time.now.to_f * 1000.0).to_i)
169
+
170
+ treatments
164
171
  end
165
172
 
166
173
  #
@@ -170,7 +177,7 @@ module SplitIoClient
170
177
  # @param split_name [String/Array] name of the feature that is being validated or array of them
171
178
  #
172
179
  # @return [String/Hash] Treatment as String or Hash of treatments in case of array of features
173
- def get_treatment(key, split_name, attributes = nil, split_data = nil)
180
+ def get_treatment(key, split_name, attributes = nil, split_data = nil, store_impressions = true)
174
181
  bucketing_key, matching_key = keys_from_key(key)
175
182
  bucketing_key = matching_key if bucketing_key.nil?
176
183
 
@@ -208,7 +215,7 @@ module SplitIoClient
208
215
 
209
216
  begin
210
217
  latency = (Time.now - start) * 1000.0
211
- if @config.impressions_queue_size > 0
218
+ if @config.impressions_queue_size > 0 && store_impressions
212
219
  # Disable impressions if @config.impressions_queue_size == -1
213
220
  @impressions_repository.add(split_name, 'key_name' => matching_key, 'treatment' => result, 'time' => (Time.now.to_f * 1000.0).to_i)
214
221
  end
@@ -288,9 +295,10 @@ module SplitIoClient
288
295
  @splits_repository = SplitIoClient::Cache::Repositories::SplitsRepository.new(@cache_adapter)
289
296
  @segments_repository = SplitIoClient::Cache::Repositories::SegmentsRepository.new(@cache_adapter)
290
297
  @impressions_repository = SplitIoClient::Cache::Repositories::ImpressionsRepository.new(@config.impressions_adapter, @config)
298
+ @metrics_repository = SplitIoClient::Cache::Repositories::MetricsRepository.new(@config.metrics_adapter, @config)
291
299
  @sdk_blocker = SplitIoClient::Cache::Stores::SDKBlocker.new(@config)
292
300
  @adapter = api_key != 'localhost' \
293
- ? SplitAdapter.new(api_key, @config, @splits_repository, @segments_repository, @impressions_repository, @sdk_blocker)
301
+ ? SplitAdapter.new(api_key, @config, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @sdk_blocker)
294
302
  : nil
295
303
  @localhost_mode = api_key == 'localhost'
296
304
 
@@ -317,7 +325,7 @@ module SplitIoClient
317
325
  attr_reader :adapter
318
326
 
319
327
  def init_client
320
- SplitClient.new(@api_key, @config, @adapter, @localhost_mode, @splits_repository, @segments_repository, @impressions_repository)
328
+ SplitClient.new(@api_key, @config, @adapter, @localhost_mode, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository)
321
329
  end
322
330
 
323
331
  def init_manager
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '3.1.0-rc9'
2
+ VERSION = '3.1.0-rc10'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: splitclient-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0.pre.rc9
4
+ version: 3.1.0.pre.rc10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Split Software
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-04 00:00:00.000000000 Z
11
+ date: 2016-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -257,6 +257,9 @@ files:
257
257
  - lib/cache/repositories/impressions/memory_repository.rb
258
258
  - lib/cache/repositories/impressions/redis_repository.rb
259
259
  - lib/cache/repositories/impressions_repository.rb
260
+ - lib/cache/repositories/metrics/memory_repository.rb
261
+ - lib/cache/repositories/metrics/redis_repository.rb
262
+ - lib/cache/repositories/metrics_repository.rb
260
263
  - lib/cache/repositories/repository.rb
261
264
  - lib/cache/repositories/segments_repository.rb
262
265
  - lib/cache/repositories/splits_repository.rb