splitclient-rb 5.1.0.pre.rc1-java → 5.1.1-java
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 +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +9 -5
- data/CHANGES.txt +12 -1
- data/Detailed-README.md +1 -1
- data/NEWS +10 -2
- data/exe/splitio +6 -6
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +3 -4
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +1 -2
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +6 -7
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +6 -7
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +9 -10
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +3 -4
- data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +1 -3
- data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +1 -3
- data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +3 -4
- data/lib/splitclient-rb/cache/repositories/repository.rb +2 -2
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +2 -4
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +12 -16
- data/lib/splitclient-rb/cache/routers/impression_router.rb +4 -5
- data/lib/splitclient-rb/cache/senders/events_sender.rb +6 -7
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +8 -9
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +6 -7
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +3 -4
- data/lib/splitclient-rb/cache/stores/segment_store.rb +11 -12
- data/lib/splitclient-rb/cache/stores/split_store.rb +12 -13
- data/lib/splitclient-rb/clients/localhost_split_client.rb +2 -2
- data/lib/splitclient-rb/clients/split_client.rb +20 -19
- data/lib/splitclient-rb/engine/api/client.rb +22 -22
- data/lib/splitclient-rb/engine/api/events.rb +6 -8
- data/lib/splitclient-rb/engine/api/impressions.rb +5 -6
- data/lib/splitclient-rb/engine/api/metrics.rb +8 -9
- data/lib/splitclient-rb/engine/api/segments.rb +2 -3
- data/lib/splitclient-rb/engine/api/splits.rb +2 -3
- data/lib/splitclient-rb/engine/metrics/metrics.rb +1 -4
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +8 -10
- data/lib/splitclient-rb/managers/split_manager.rb +1 -2
- data/lib/splitclient-rb/split_config.rb +47 -38
- data/lib/splitclient-rb/split_factory.rb +13 -14
- data/lib/splitclient-rb/split_logger.rb +3 -8
- data/lib/splitclient-rb/version.rb +1 -1
- data/splitclient-rb.gemspec +1 -1
- metadata +8 -8
@@ -2,9 +2,8 @@ module SplitIoClient
|
|
2
2
|
module Cache
|
3
3
|
module Senders
|
4
4
|
class EventsSender
|
5
|
-
def initialize(events_repository,
|
5
|
+
def initialize(events_repository, api_key)
|
6
6
|
@events_repository = events_repository
|
7
|
-
@config = config
|
8
7
|
@api_key = api_key
|
9
8
|
end
|
10
9
|
|
@@ -25,21 +24,21 @@ module SplitIoClient
|
|
25
24
|
private
|
26
25
|
|
27
26
|
def events_thread
|
28
|
-
|
29
|
-
|
27
|
+
SplitIoClient.configuration.threads[:events_sender] = Thread.new do
|
28
|
+
SplitIoClient.configuration.logger.info('Starting events service')
|
30
29
|
|
31
30
|
loop do
|
32
31
|
post_events
|
33
32
|
|
34
|
-
sleep(SplitIoClient::Utilities.randomize_interval(
|
33
|
+
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.events_push_rate))
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
38
|
def post_events
|
40
|
-
SplitIoClient::Api::Events.new(@api_key, @
|
39
|
+
SplitIoClient::Api::Events.new(@api_key, @events_repository.clear).post
|
41
40
|
rescue StandardError => error
|
42
|
-
|
41
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
@@ -2,15 +2,14 @@ module SplitIoClient
|
|
2
2
|
module Cache
|
3
3
|
module Senders
|
4
4
|
class ImpressionsSender
|
5
|
-
def initialize(impressions_repository,
|
5
|
+
def initialize(impressions_repository, api_key)
|
6
6
|
@impressions_repository = impressions_repository
|
7
|
-
@config = config
|
8
7
|
@api_key = api_key
|
9
8
|
end
|
10
9
|
|
11
10
|
def call
|
12
|
-
if
|
13
|
-
|
11
|
+
if SplitIoClient.configuration.disable_impressions
|
12
|
+
SplitIoClient.configuration.logger.info('Disabling impressions service by config')
|
14
13
|
return
|
15
14
|
end
|
16
15
|
|
@@ -30,14 +29,14 @@ module SplitIoClient
|
|
30
29
|
private
|
31
30
|
|
32
31
|
def impressions_thread
|
33
|
-
|
32
|
+
SplitIoClient.configuration.threads[:impressions_sender] = Thread.new do
|
34
33
|
begin
|
35
|
-
|
34
|
+
SplitIoClient.configuration.logger.info('Starting impressions service')
|
36
35
|
|
37
36
|
loop do
|
38
37
|
post_impressions
|
39
38
|
|
40
|
-
sleep(SplitIoClient::Utilities.randomize_interval(
|
39
|
+
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.impressions_refresh_rate))
|
41
40
|
end
|
42
41
|
rescue SplitIoClient::ImpressionShutdownException
|
43
42
|
post_impressions
|
@@ -50,7 +49,7 @@ module SplitIoClient
|
|
50
49
|
def post_impressions
|
51
50
|
impressions_client.post
|
52
51
|
rescue StandardError => error
|
53
|
-
|
52
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
54
53
|
end
|
55
54
|
|
56
55
|
def formatted_impressions(raw_impressions = nil)
|
@@ -58,7 +57,7 @@ module SplitIoClient
|
|
58
57
|
end
|
59
58
|
|
60
59
|
def impressions_client
|
61
|
-
SplitIoClient::Api::Impressions.new(@api_key,
|
60
|
+
SplitIoClient::Api::Impressions.new(@api_key, formatted_impressions)
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
@@ -2,9 +2,8 @@ module SplitIoClient
|
|
2
2
|
module Cache
|
3
3
|
module Senders
|
4
4
|
class MetricsSender
|
5
|
-
def initialize(metrics_repository,
|
5
|
+
def initialize(metrics_repository, api_key)
|
6
6
|
@metrics_repository = metrics_repository
|
7
|
-
@config = config
|
8
7
|
@api_key = api_key
|
9
8
|
end
|
10
9
|
|
@@ -23,13 +22,13 @@ module SplitIoClient
|
|
23
22
|
private
|
24
23
|
|
25
24
|
def metrics_thread
|
26
|
-
|
27
|
-
|
25
|
+
SplitIoClient.configuration.threads[:metrics_sender] = Thread.new do
|
26
|
+
SplitIoClient.configuration.logger.info('Starting metrics service')
|
28
27
|
|
29
28
|
loop do
|
30
29
|
post_metrics
|
31
30
|
|
32
|
-
sleep(SplitIoClient::Utilities.randomize_interval(
|
31
|
+
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.metrics_refresh_rate))
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
@@ -37,11 +36,11 @@ module SplitIoClient
|
|
37
36
|
def post_metrics
|
38
37
|
metrics_client.post
|
39
38
|
rescue StandardError => error
|
40
|
-
|
39
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
41
40
|
end
|
42
41
|
|
43
42
|
def metrics_client
|
44
|
-
SplitIoClient::Api::Metrics.new(@api_key, @
|
43
|
+
SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository)
|
45
44
|
end
|
46
45
|
end
|
47
46
|
end
|
@@ -8,8 +8,7 @@ module SplitIoClient
|
|
8
8
|
attr_reader :splits_repository
|
9
9
|
attr_writer :splits_thread, :segments_thread
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@config = config
|
11
|
+
def initialize(splits_repository, segments_repository)
|
13
12
|
@splits_repository = splits_repository
|
14
13
|
@segments_repository = segments_repository
|
15
14
|
|
@@ -27,14 +26,14 @@ module SplitIoClient
|
|
27
26
|
|
28
27
|
def block
|
29
28
|
begin
|
30
|
-
Timeout::timeout(
|
29
|
+
Timeout::timeout(SplitIoClient.configuration.block_until_ready) do
|
31
30
|
sleep 0.1 until ready?
|
32
31
|
end
|
33
32
|
rescue Timeout::Error
|
34
33
|
fail SDKBlockerTimeoutExpiredException, 'SDK start up timeout expired'
|
35
34
|
end
|
36
35
|
|
37
|
-
|
36
|
+
SplitIoClient.configuration.logger.info('SplitIO SDK is ready')
|
38
37
|
@splits_thread.run
|
39
38
|
@segments_thread.run
|
40
39
|
end
|
@@ -4,9 +4,8 @@ module SplitIoClient
|
|
4
4
|
class SegmentStore
|
5
5
|
attr_reader :segments_repository
|
6
6
|
|
7
|
-
def initialize(segments_repository,
|
7
|
+
def initialize(segments_repository, api_key, metrics, sdk_blocker = nil)
|
8
8
|
@segments_repository = segments_repository
|
9
|
-
@config = config
|
10
9
|
@api_key = api_key
|
11
10
|
@metrics = metrics
|
12
11
|
@sdk_blocker = sdk_blocker
|
@@ -29,9 +28,9 @@ module SplitIoClient
|
|
29
28
|
private
|
30
29
|
|
31
30
|
def segments_thread
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
SplitIoClient.configuration.threads[:segment_store] = @sdk_blocker.segments_thread = Thread.new do
|
32
|
+
SplitIoClient.configuration.logger.info('Starting segments fetcher service')
|
33
|
+
SplitIoClient.configuration.block_until_ready > 0 ? blocked_store : unblocked_store
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
@@ -40,15 +39,15 @@ module SplitIoClient
|
|
40
39
|
next unless @sdk_blocker.splits_repository.ready?
|
41
40
|
|
42
41
|
store_segments
|
43
|
-
|
42
|
+
SplitIoClient.configuration.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if SplitIoClient.configuration.debug_enabled
|
44
43
|
|
45
44
|
unless @sdk_blocker.ready?
|
46
45
|
@sdk_blocker.segments_ready!
|
47
|
-
|
46
|
+
SplitIoClient.configuration.logger.info('segments are ready')
|
48
47
|
end
|
49
48
|
|
50
|
-
sleep_for = random_interval(
|
51
|
-
|
49
|
+
sleep_for = random_interval(SplitIoClient.configuration.segments_refresh_rate)
|
50
|
+
SplitIoClient.configuration.logger.debug("Segments store is sleeping for: #{sleep_for} seconds") if SplitIoClient.configuration.debug_enabled
|
52
51
|
sleep(sleep_for)
|
53
52
|
end
|
54
53
|
end
|
@@ -57,14 +56,14 @@ module SplitIoClient
|
|
57
56
|
loop do
|
58
57
|
store_segments
|
59
58
|
|
60
|
-
sleep(random_interval(
|
59
|
+
sleep(random_interval(SplitIoClient.configuration.segments_refresh_rate))
|
61
60
|
end
|
62
61
|
end
|
63
62
|
|
64
63
|
def store_segments
|
65
64
|
segments_api.store_segments_by_names(@segments_repository.used_segment_names)
|
66
65
|
rescue StandardError => error
|
67
|
-
|
66
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
68
67
|
end
|
69
68
|
|
70
69
|
def random_interval(interval)
|
@@ -74,7 +73,7 @@ module SplitIoClient
|
|
74
73
|
end
|
75
74
|
|
76
75
|
def segments_api
|
77
|
-
SplitIoClient::Api::Segments.new(@api_key, @
|
76
|
+
SplitIoClient::Api::Segments.new(@api_key, @metrics, @segments_repository)
|
78
77
|
end
|
79
78
|
end
|
80
79
|
end
|
@@ -4,9 +4,8 @@ module SplitIoClient
|
|
4
4
|
class SplitStore
|
5
5
|
attr_reader :splits_repository
|
6
6
|
|
7
|
-
def initialize(splits_repository,
|
7
|
+
def initialize(splits_repository, api_key, metrics, sdk_blocker = nil)
|
8
8
|
@splits_repository = splits_repository
|
9
|
-
@config = config
|
10
9
|
@api_key = api_key
|
11
10
|
@metrics = metrics
|
12
11
|
@sdk_blocker = sdk_blocker
|
@@ -29,12 +28,12 @@ module SplitIoClient
|
|
29
28
|
private
|
30
29
|
|
31
30
|
def splits_thread
|
32
|
-
|
33
|
-
|
31
|
+
SplitIoClient.configuration.threads[:split_store] = @sdk_blocker.splits_thread = Thread.new do
|
32
|
+
SplitIoClient.configuration.logger.info('Starting splits fetcher service')
|
34
33
|
loop do
|
35
34
|
store_splits
|
36
35
|
|
37
|
-
sleep(random_interval(
|
36
|
+
sleep(random_interval(SplitIoClient.configuration.features_refresh_rate))
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end
|
@@ -49,15 +48,15 @@ module SplitIoClient
|
|
49
48
|
@splits_repository.set_segment_names(data[:segment_names])
|
50
49
|
@splits_repository.set_change_number(data[:till])
|
51
50
|
|
52
|
-
|
51
|
+
SplitIoClient.configuration.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if SplitIoClient.configuration.debug_enabled
|
53
52
|
|
54
|
-
if
|
53
|
+
if SplitIoClient.configuration.block_until_ready > 0 && !@sdk_blocker.ready?
|
55
54
|
@sdk_blocker.splits_ready!
|
56
|
-
|
55
|
+
SplitIoClient.configuration.logger.info('splits are ready')
|
57
56
|
end
|
58
57
|
|
59
58
|
rescue StandardError => error
|
60
|
-
|
59
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
61
60
|
end
|
62
61
|
|
63
62
|
def random_interval(interval)
|
@@ -67,12 +66,12 @@ module SplitIoClient
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def splits_since(since)
|
70
|
-
SplitIoClient::Api::Splits.new(@api_key, @
|
69
|
+
SplitIoClient::Api::Splits.new(@api_key, @metrics).since(since)
|
71
70
|
end
|
72
71
|
|
73
72
|
def add_split_unless_archived(split)
|
74
73
|
if Engine::Models::Split.archived?(split)
|
75
|
-
|
74
|
+
SplitIoClient.configuration.logger.debug("Seeing archived split #{split[:name]}") if SplitIoClient.configuration.debug_enabled
|
76
75
|
|
77
76
|
remove_archived_split(split)
|
78
77
|
else
|
@@ -81,13 +80,13 @@ module SplitIoClient
|
|
81
80
|
end
|
82
81
|
|
83
82
|
def remove_archived_split(split)
|
84
|
-
|
83
|
+
SplitIoClient.configuration.logger.debug("removing split from store(#{split})") if SplitIoClient.configuration.debug_enabled
|
85
84
|
|
86
85
|
@splits_repository.remove_split(split[:name])
|
87
86
|
end
|
88
87
|
|
89
88
|
def store_split(split)
|
90
|
-
|
89
|
+
SplitIoClient.configuration.logger.debug("storing split (#{split[:name]})") if SplitIoClient.configuration.debug_enabled
|
91
90
|
|
92
91
|
@splits_repository.add_split(split)
|
93
92
|
end
|
@@ -42,12 +42,12 @@ module SplitIoClient
|
|
42
42
|
# @return [Treatment] treatment constant value
|
43
43
|
def get_treatment(id, feature, attributes = nil)
|
44
44
|
unless id
|
45
|
-
|
45
|
+
SplitIoClient.configuration.logger.warn('id was null for feature: ' + feature)
|
46
46
|
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
47
47
|
end
|
48
48
|
|
49
49
|
unless feature
|
50
|
-
|
50
|
+
SplitIoClient.configuration.logger.warn('feature was null for id: ' + id)
|
51
51
|
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
52
52
|
end
|
53
53
|
|
@@ -6,9 +6,7 @@ module SplitIoClient
|
|
6
6
|
# @param api_key [String] the API key for your split account
|
7
7
|
#
|
8
8
|
# @return [SplitIoClient] split.io client instance
|
9
|
-
def initialize(api_key,
|
10
|
-
@config = config
|
11
|
-
|
9
|
+
def initialize(api_key, adapter = nil, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository)
|
12
10
|
@splits_repository = splits_repository
|
13
11
|
@segments_repository = segments_repository
|
14
12
|
@impressions_repository = impressions_repository
|
@@ -21,13 +19,16 @@ module SplitIoClient
|
|
21
19
|
def get_treatments(key, split_names, attributes = {})
|
22
20
|
bucketing_key, matching_key = keys_from_key(key)
|
23
21
|
evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, true)
|
24
|
-
|
22
|
+
start = Time.now
|
25
23
|
treatments_labels_change_numbers =
|
26
24
|
@splits_repository.get_splits(split_names).each_with_object({}) do |(name, data), memo|
|
27
25
|
memo.merge!(name => get_treatment(key, name, attributes, data, false, true, evaluator))
|
28
26
|
end
|
27
|
+
latency = (Time.now - start) * 1000.0
|
28
|
+
# Measure
|
29
|
+
@adapter.metrics.time('sdk.get_treatments', latency)
|
29
30
|
|
30
|
-
unless
|
31
|
+
unless SplitIoClient.configuration.disable_impressions
|
31
32
|
time = (Time.now.to_f * 1000.0).to_i
|
32
33
|
@impressions_repository.add_bulk(
|
33
34
|
matching_key, bucketing_key, treatments_labels_change_numbers, time
|
@@ -63,12 +64,12 @@ module SplitIoClient
|
|
63
64
|
evaluator ||= Engine::Parser::Evaluator.new(@segments_repository, @splits_repository)
|
64
65
|
|
65
66
|
if matching_key.nil?
|
66
|
-
|
67
|
+
SplitIoClient.configuration.logger.warn('matching_key was null for split_name: ' + split_name.to_s)
|
67
68
|
return parsed_treatment(multiple, treatment_data)
|
68
69
|
end
|
69
70
|
|
70
71
|
if split_name.nil?
|
71
|
-
|
72
|
+
SplitIoClient.configuration.logger.warn('split_name was null for key: ' + key)
|
72
73
|
return parsed_treatment(multiple, treatment_data)
|
73
74
|
end
|
74
75
|
|
@@ -78,7 +79,7 @@ module SplitIoClient
|
|
78
79
|
split = multiple ? split_data : @splits_repository.get_split(split_name)
|
79
80
|
|
80
81
|
if split.nil?
|
81
|
-
|
82
|
+
SplitIoClient.configuration.logger.debug("split_name: #{split_name} does not exist. Returning CONTROL")
|
82
83
|
return parsed_treatment(multiple, treatment_data)
|
83
84
|
else
|
84
85
|
treatment_data =
|
@@ -87,7 +88,7 @@ module SplitIoClient
|
|
87
88
|
)
|
88
89
|
end
|
89
90
|
rescue StandardError => error
|
90
|
-
|
91
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
91
92
|
|
92
93
|
store_impression(
|
93
94
|
split_name, matching_key, bucketing_key,
|
@@ -106,9 +107,9 @@ module SplitIoClient
|
|
106
107
|
split && store_impression(split_name, matching_key, bucketing_key, treatment_data, store_impressions, attributes)
|
107
108
|
|
108
109
|
# Measure
|
109
|
-
@adapter.metrics.time('sdk.get_treatment', latency)
|
110
|
+
@adapter.metrics.time('sdk.get_treatment', latency) unless multiple
|
110
111
|
rescue StandardError => error
|
111
|
-
|
112
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
112
113
|
|
113
114
|
store_impression(
|
114
115
|
split_name, matching_key, bucketing_key,
|
@@ -126,10 +127,10 @@ module SplitIoClient
|
|
126
127
|
end
|
127
128
|
|
128
129
|
def destroy
|
129
|
-
|
130
|
+
SplitIoClient.configuration.logger.info('Split client shutdown started...') if SplitIoClient.configuration.debug_enabled
|
130
131
|
|
131
|
-
|
132
|
-
|
132
|
+
SplitIoClient.configuration.threads[:impressions_sender].raise(SplitIoClient::ImpressionShutdownException)
|
133
|
+
SplitIoClient.configuration.threads.reject { |k, _| k == :impressions_sender }.each do |name, thread|
|
133
134
|
Thread.kill(thread)
|
134
135
|
end
|
135
136
|
|
@@ -138,19 +139,19 @@ module SplitIoClient
|
|
138
139
|
@segments_repository.clear
|
139
140
|
@events_repository.clear
|
140
141
|
|
141
|
-
|
142
|
+
SplitIoClient.configuration.logger.info('Split client shutdown complete') if SplitIoClient.configuration.debug_enabled
|
142
143
|
end
|
143
144
|
|
144
145
|
def store_impression(split_name, matching_key, bucketing_key, treatment, store_impressions, attributes)
|
145
146
|
time = (Time.now.to_f * 1000.0).to_i
|
146
147
|
|
147
|
-
return if
|
148
|
+
return if SplitIoClient.configuration.disable_impressions || !store_impressions
|
148
149
|
|
149
150
|
@impressions_repository.add(split_name,
|
150
151
|
'keyName' => matching_key,
|
151
152
|
'bucketingKey' => bucketing_key,
|
152
153
|
'treatment' => treatment[:treatment],
|
153
|
-
'label' =>
|
154
|
+
'label' => SplitIoClient.configuration.labels_enabled ? treatment[:label] : nil,
|
154
155
|
'time' => time,
|
155
156
|
'changeNumber' => treatment[:change_number]
|
156
157
|
)
|
@@ -158,7 +159,7 @@ module SplitIoClient
|
|
158
159
|
route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
|
159
160
|
|
160
161
|
rescue StandardError => error
|
161
|
-
|
162
|
+
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
162
163
|
end
|
163
164
|
|
164
165
|
def route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
|
@@ -184,7 +185,7 @@ module SplitIoClient
|
|
184
185
|
end
|
185
186
|
|
186
187
|
def impression_router
|
187
|
-
@impression_router ||= SplitIoClient::ImpressionRouter.new
|
188
|
+
@impression_router ||= SplitIoClient::ImpressionRouter.new
|
188
189
|
end
|
189
190
|
|
190
191
|
def track(key, traffic_type, event_type, value = nil)
|