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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +9 -5
  4. data/CHANGES.txt +12 -1
  5. data/Detailed-README.md +1 -1
  6. data/NEWS +10 -2
  7. data/exe/splitio +6 -6
  8. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +3 -4
  9. data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +1 -2
  10. data/lib/splitclient-rb/cache/repositories/events_repository.rb +6 -7
  11. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +6 -7
  12. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +9 -10
  13. data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +3 -4
  14. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +1 -3
  15. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +1 -3
  16. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +3 -4
  17. data/lib/splitclient-rb/cache/repositories/repository.rb +2 -2
  18. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +2 -4
  19. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +12 -16
  20. data/lib/splitclient-rb/cache/routers/impression_router.rb +4 -5
  21. data/lib/splitclient-rb/cache/senders/events_sender.rb +6 -7
  22. data/lib/splitclient-rb/cache/senders/impressions_sender.rb +8 -9
  23. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +6 -7
  24. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +3 -4
  25. data/lib/splitclient-rb/cache/stores/segment_store.rb +11 -12
  26. data/lib/splitclient-rb/cache/stores/split_store.rb +12 -13
  27. data/lib/splitclient-rb/clients/localhost_split_client.rb +2 -2
  28. data/lib/splitclient-rb/clients/split_client.rb +20 -19
  29. data/lib/splitclient-rb/engine/api/client.rb +22 -22
  30. data/lib/splitclient-rb/engine/api/events.rb +6 -8
  31. data/lib/splitclient-rb/engine/api/impressions.rb +5 -6
  32. data/lib/splitclient-rb/engine/api/metrics.rb +8 -9
  33. data/lib/splitclient-rb/engine/api/segments.rb +2 -3
  34. data/lib/splitclient-rb/engine/api/splits.rb +2 -3
  35. data/lib/splitclient-rb/engine/metrics/metrics.rb +1 -4
  36. data/lib/splitclient-rb/engine/parser/split_adapter.rb +8 -10
  37. data/lib/splitclient-rb/managers/split_manager.rb +1 -2
  38. data/lib/splitclient-rb/split_config.rb +47 -38
  39. data/lib/splitclient-rb/split_factory.rb +13 -14
  40. data/lib/splitclient-rb/split_logger.rb +3 -8
  41. data/lib/splitclient-rb/version.rb +1 -1
  42. data/splitclient-rb.gemspec +1 -1
  43. 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, config, api_key)
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
- @config.threads[:events_sender] = Thread.new do
29
- @config.logger.info('Starting events service')
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(@config.events_push_rate))
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, @config, @events_repository.clear).post
39
+ SplitIoClient::Api::Events.new(@api_key, @events_repository.clear).post
41
40
  rescue StandardError => error
42
- @config.log_found_exception(__method__.to_s, error)
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, config, api_key)
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 @config.disable_impressions
13
- @config.logger.info('Disabling impressions service by config')
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
- @config.threads[:impressions_sender] = Thread.new do
32
+ SplitIoClient.configuration.threads[:impressions_sender] = Thread.new do
34
33
  begin
35
- @config.logger.info('Starting impressions service')
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(@config.impressions_refresh_rate))
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
- @config.log_found_exception(__method__.to_s, error)
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, @config, formatted_impressions)
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, config, api_key)
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
- @config.threads[:metrics_sender] = Thread.new do
27
- @config.logger.info('Starting metrics service')
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(@config.metrics_refresh_rate))
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
- @config.log_found_exception(__method__.to_s, error)
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, @config, @metrics_repository)
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(config, splits_repository, segments_repository)
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(@config.block_until_ready) do
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
- @config.logger.info('SplitIO SDK is ready')
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, config, api_key, metrics, sdk_blocker = nil)
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
- @config.threads[:segment_store] = @sdk_blocker.segments_thread = Thread.new do
33
- @config.logger.info('Starting segments fetcher service')
34
- @config.block_until_ready > 0 ? blocked_store : unblocked_store
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
- @config.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if @config.debug_enabled
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
- @config.logger.info('segments are ready')
46
+ SplitIoClient.configuration.logger.info('segments are ready')
48
47
  end
49
48
 
50
- sleep_for = random_interval(@config.segments_refresh_rate)
51
- @config.logger.debug("Segments store is sleeping for: #{sleep_for} seconds") if @config.debug_enabled
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(@config.segments_refresh_rate))
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
- @config.log_found_exception(__method__.to_s, error)
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, @config, @metrics, @segments_repository)
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, config, api_key, metrics, sdk_blocker = nil)
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
- @config.threads[:split_store] = @sdk_blocker.splits_thread = Thread.new do
33
- @config.logger.info('Starting splits fetcher service')
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(@config.features_refresh_rate))
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
- @config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled
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 @config.block_until_ready > 0 && !@sdk_blocker.ready?
53
+ if SplitIoClient.configuration.block_until_ready > 0 && !@sdk_blocker.ready?
55
54
  @sdk_blocker.splits_ready!
56
- @config.logger.info('splits are ready')
55
+ SplitIoClient.configuration.logger.info('splits are ready')
57
56
  end
58
57
 
59
58
  rescue StandardError => error
60
- @config.log_found_exception(__method__.to_s, error)
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, @config, @metrics).since(since)
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
- @config.logger.debug("Seeing archived split #{split[:name]}") if @config.debug_enabled
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
- @config.logger.debug("removing split from store(#{split})") if @config.debug_enabled
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
- @config.logger.debug("storing split (#{split[:name]})") if @config.debug_enabled
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
- @config.logger.warn('id was null for feature: ' + feature)
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
- @config.logger.warn('feature was null for id: ' + id)
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, config = {}, adapter = nil, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository)
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 @config.disable_impressions
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
- @config.logger.warn('matching_key was null for split_name: ' + split_name.to_s)
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
- @config.logger.warn('split_name was null for key: ' + key)
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
- @config.logger.debug("split_name: #{split_name} does not exist. Returning CONTROL")
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
- @config.log_found_exception(__method__.to_s, error)
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
- @config.log_found_exception(__method__.to_s, error)
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
- @config.logger.info('Split client shutdown started...') if @config.debug_enabled
130
+ SplitIoClient.configuration.logger.info('Split client shutdown started...') if SplitIoClient.configuration.debug_enabled
130
131
 
131
- @config.threads[:impressions_sender].raise(SplitIoClient::ImpressionShutdownException)
132
- @config.threads.reject { |k, _| k == :impressions_sender }.each do |name, thread|
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
- @config.logger.info('Split client shutdown complete') if @config.debug_enabled
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 @config.disable_impressions || !store_impressions
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' => @config.labels_enabled ? treatment[:label] : nil,
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
- @config.log_found_exception(__method__.to_s, error)
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(@config)
188
+ @impression_router ||= SplitIoClient::ImpressionRouter.new
188
189
  end
189
190
 
190
191
  def track(key, traffic_type, event_type, value = nil)