splitclient-rb 7.2.3.pre.rc2-java → 7.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -0
  3. data/CHANGES.txt +10 -0
  4. data/LICENSE +1 -1
  5. data/README.md +1 -1
  6. data/lib/splitclient-rb.rb +24 -9
  7. data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +4 -0
  8. data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +13 -9
  9. data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +8 -7
  10. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +6 -3
  11. data/lib/splitclient-rb/cache/repositories/events_repository.rb +4 -3
  12. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +8 -0
  13. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +2 -0
  14. data/lib/splitclient-rb/cache/repositories/repository.rb +0 -4
  15. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +20 -0
  16. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +4 -0
  17. data/lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb +1 -3
  18. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +9 -0
  19. data/lib/splitclient-rb/clients/split_client.rb +59 -25
  20. data/lib/splitclient-rb/engine/api/client.rb +3 -2
  21. data/lib/splitclient-rb/engine/api/events.rb +10 -1
  22. data/lib/splitclient-rb/engine/api/impressions.rb +19 -2
  23. data/lib/splitclient-rb/engine/api/segments.rb +20 -18
  24. data/lib/splitclient-rb/engine/api/splits.rb +10 -10
  25. data/lib/splitclient-rb/engine/api/telemetry_api.rb +39 -0
  26. data/lib/splitclient-rb/engine/auth_api_client.rb +21 -8
  27. data/lib/splitclient-rb/engine/common/impressions_manager.rb +27 -3
  28. data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +3 -65
  29. data/lib/splitclient-rb/engine/push_manager.rb +10 -2
  30. data/lib/splitclient-rb/engine/sync_manager.rb +42 -20
  31. data/lib/splitclient-rb/engine/synchronizer.rb +13 -12
  32. data/lib/splitclient-rb/split_config.rb +46 -21
  33. data/lib/splitclient-rb/split_factory.rb +31 -13
  34. data/lib/splitclient-rb/split_factory_registry.rb +12 -0
  35. data/lib/splitclient-rb/sse/event_source/client.rb +10 -1
  36. data/lib/splitclient-rb/sse/notification_manager_keeper.rb +17 -3
  37. data/lib/splitclient-rb/sse/sse_handler.rb +10 -6
  38. data/lib/splitclient-rb/telemetry/domain/constants.rb +42 -0
  39. data/lib/splitclient-rb/telemetry/domain/structs.rb +31 -0
  40. data/lib/splitclient-rb/telemetry/evaluation_consumer.rb +14 -0
  41. data/lib/splitclient-rb/telemetry/evaluation_producer.rb +21 -0
  42. data/lib/splitclient-rb/telemetry/init_consumer.rb +14 -0
  43. data/lib/splitclient-rb/telemetry/init_producer.rb +19 -0
  44. data/lib/splitclient-rb/telemetry/memory/memory_evaluation_consumer.rb +32 -0
  45. data/lib/splitclient-rb/telemetry/memory/memory_evaluation_producer.rb +24 -0
  46. data/lib/splitclient-rb/telemetry/memory/memory_init_consumer.rb +28 -0
  47. data/lib/splitclient-rb/telemetry/memory/memory_init_producer.rb +34 -0
  48. data/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb +112 -0
  49. data/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb +81 -0
  50. data/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +192 -0
  51. data/lib/splitclient-rb/telemetry/redis/redis_evaluation_producer.rb +38 -0
  52. data/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +37 -0
  53. data/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb +28 -0
  54. data/lib/splitclient-rb/telemetry/runtime_consumer.rb +24 -0
  55. data/lib/splitclient-rb/telemetry/runtime_producer.rb +24 -0
  56. data/lib/splitclient-rb/telemetry/storages/memory.rb +139 -0
  57. data/lib/splitclient-rb/telemetry/sync_task.rb +38 -0
  58. data/lib/splitclient-rb/telemetry/synchronizer.rb +29 -0
  59. data/lib/splitclient-rb/version.rb +1 -1
  60. metadata +26 -11
  61. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +0 -163
  62. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +0 -131
  63. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +0 -23
  64. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +0 -55
  65. data/lib/splitclient-rb/engine/api/metrics.rb +0 -61
  66. data/lib/splitclient-rb/engine/metrics/metrics.rb +0 -80
  67. data/lib/splitclient-rb/redis_metrics_fixer.rb +0 -36
@@ -11,6 +11,7 @@ module SplitIoClient
11
11
  @splits_repository = splits_repository
12
12
  @segments_repository = segments_repository
13
13
  @config = config
14
+ @internal_ready = Concurrent::CountDownLatch.new(1)
14
15
 
15
16
  if @config.standalone?
16
17
  @splits_repository.not_ready!
@@ -49,6 +50,14 @@ module SplitIoClient
49
50
  return true if @config.consumer?
50
51
  @splits_repository.ready? && @segments_repository.ready?
51
52
  end
53
+
54
+ def sdk_internal_ready
55
+ @internal_ready.count_down
56
+ end
57
+
58
+ def wait_unitil_internal_ready
59
+ @internal_ready.wait
60
+ end
52
61
  end
53
62
  end
54
63
  end
@@ -1,6 +1,11 @@
1
1
  module SplitIoClient
2
2
  EVENTS_SIZE_THRESHOLD = 32768
3
3
  EVENT_AVERAGE_SIZE = 1024
4
+ GET_TREATMENT = 'get_treatment'
5
+ GET_TREATMENTS = 'get_treatments'
6
+ GET_TREATMENT_WITH_CONFIG = 'get_treatment_with_config'
7
+ GET_TREATMENTS_WITH_CONFIG = 'get_treatments_with_config'
8
+ TRACK = 'track'
4
9
 
5
10
  class SplitClient
6
11
  #
@@ -9,18 +14,17 @@ module SplitIoClient
9
14
  # @param api_key [String] the API key for your split account
10
15
  #
11
16
  # @return [SplitIoClient] split.io client instance
12
- def initialize(api_key, metrics, splits_repository, segments_repository, impressions_repository, metrics_repository, events_repository, sdk_blocker, config, impressions_manager)
17
+ def initialize(api_key, repositories, sdk_blocker, config, impressions_manager, telemetry_evaluation_producer)
13
18
  @api_key = api_key
14
- @metrics = metrics
15
- @splits_repository = splits_repository
16
- @segments_repository = segments_repository
17
- @impressions_repository = impressions_repository
18
- @metrics_repository = metrics_repository
19
- @events_repository = events_repository
19
+ @splits_repository = repositories[:splits]
20
+ @segments_repository = repositories[:segments]
21
+ @impressions_repository = repositories[:impressions]
22
+ @events_repository = repositories[:events]
20
23
  @sdk_blocker = sdk_blocker
21
24
  @destroyed = false
22
25
  @config = config
23
26
  @impressions_manager = impressions_manager
27
+ @telemetry_evaluation_producer = telemetry_evaluation_producer
24
28
  end
25
29
 
26
30
  def get_treatment(
@@ -28,7 +32,7 @@ module SplitIoClient
28
32
  multiple = false, evaluator = nil
29
33
  )
30
34
  impressions = []
31
- result = treatment(key, split_name, attributes, split_data, store_impressions, multiple, evaluator, 'get_treatment', impressions)
35
+ result = treatment(key, split_name, attributes, split_data, store_impressions, multiple, evaluator, GET_TREATMENT, impressions)
32
36
  @impressions_manager.track(impressions)
33
37
 
34
38
  if multiple
@@ -43,7 +47,7 @@ module SplitIoClient
43
47
  multiple = false, evaluator = nil
44
48
  )
45
49
  impressions = []
46
- result = treatment(key, split_name, attributes, split_data, store_impressions, multiple, evaluator, 'get_treatment_with_config', impressions)
50
+ result = treatment(key, split_name, attributes, split_data, store_impressions, multiple, evaluator, GET_TREATMENT_WITH_CONFIG, impressions)
47
51
  @impressions_manager.track(impressions)
48
52
 
49
53
  result
@@ -58,7 +62,7 @@ module SplitIoClient
58
62
  end
59
63
 
60
64
  def get_treatments_with_config(key, split_names, attributes = {})
61
- treatments(key, split_names, attributes,'get_treatments_with_config')
65
+ treatments(key, split_names, attributes, GET_TREATMENTS_WITH_CONFIG)
62
66
  end
63
67
 
64
68
  def destroy
@@ -85,6 +89,7 @@ module SplitIoClient
85
89
  def track(key, traffic_type_name, event_type, value = nil, properties = nil)
86
90
  return false unless valid_client && @config.split_validator.valid_track_parameters(key, traffic_type_name, event_type, value, properties)
87
91
 
92
+ start = Time.now
88
93
  properties_size = EVENT_AVERAGE_SIZE
89
94
 
90
95
  if !properties.nil?
@@ -102,13 +107,14 @@ module SplitIoClient
102
107
  'your events to a valid traffic type defined in the Split console')
103
108
  end
104
109
 
105
- begin
106
- @events_repository.add(key.to_s, traffic_type_name.downcase, event_type.to_s, (Time.now.to_f * 1000).to_i, value, properties, properties_size)
107
- true
108
- rescue StandardError => error
109
- @config.log_found_exception(__method__.to_s, error)
110
- false
111
- end
110
+ @events_repository.add(key.to_s, traffic_type_name.downcase, event_type.to_s, (Time.now.to_f * 1000).to_i, value, properties, properties_size)
111
+ record_latency(TRACK, start)
112
+ true
113
+ rescue StandardError => error
114
+ @config.log_found_exception(__method__.to_s, error)
115
+ record_exception(TRACK)
116
+
117
+ false
112
118
  end
113
119
 
114
120
  def keys_from_key(key)
@@ -209,10 +215,8 @@ module SplitIoClient
209
215
  @splits_repository.get_splits(sanitized_split_names).each_with_object({}) do |(name, data), memo|
210
216
  memo.merge!(name => treatment(key, name, attributes, data, false, true, evaluator, calling_method, impressions))
211
217
  end
212
- latency = (Time.now - start) * 1000.0
213
- # Measure
214
- @metrics.time('sdk.' + calling_method, latency)
215
218
 
219
+ record_latency(calling_method, start)
216
220
  @impressions_manager.track(impressions)
217
221
 
218
222
  split_names_keys = treatments_labels_change_numbers.keys
@@ -283,17 +287,15 @@ module SplitIoClient
283
287
  control_treatment.merge({ label: Engine::Models::Label::NOT_READY })
284
288
  end
285
289
 
286
- latency = (Time.now - start) * 1000.0
290
+ record_latency(calling_method, start) unless multiple
287
291
 
288
292
  impression = @impressions_manager.build_impression(matching_key, bucketing_key, split_name, treatment_data, { attributes: attributes, time: nil })
289
293
  impressions << impression unless impression.nil?
290
-
291
- # Measure
292
- @metrics.time('sdk.' + calling_method, latency) unless multiple
293
294
  rescue StandardError => error
294
- p error
295
295
  @config.log_found_exception(__method__.to_s, error)
296
296
 
297
+ record_exception(calling_method)
298
+
297
299
  impression = @impressions_manager.build_impression(matching_key, bucketing_key, split_name, control_treatment, { attributes: attributes, time: nil })
298
300
  impressions << impression unless impression.nil?
299
301
 
@@ -315,5 +317,37 @@ module SplitIoClient
315
317
  def parsed_attributes(attributes)
316
318
  return attributes || attributes.to_h
317
319
  end
320
+
321
+ def record_latency(method, start)
322
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
323
+
324
+ case method
325
+ when GET_TREATMENT
326
+ @telemetry_evaluation_producer.record_latency(Telemetry::Domain::Constants::TREATMENT, bucket)
327
+ when GET_TREATMENTS
328
+ @telemetry_evaluation_producer.record_latency(Telemetry::Domain::Constants::TREATMENTS, bucket)
329
+ when GET_TREATMENT_WITH_CONFIG
330
+ @telemetry_evaluation_producer.record_latency(Telemetry::Domain::Constants::TREATMENT_WITH_CONFIG, bucket)
331
+ when GET_TREATMENTS_WITH_CONFIG
332
+ @telemetry_evaluation_producer.record_latency(Telemetry::Domain::Constants::TREATMENTS_WITH_CONFIG, bucket)
333
+ when TRACK
334
+ @telemetry_evaluation_producer.record_latency(Telemetry::Domain::Constants::TRACK, bucket)
335
+ end
336
+ end
337
+
338
+ def record_exception(method)
339
+ case method
340
+ when GET_TREATMENT
341
+ @telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TREATMENT)
342
+ when GET_TREATMENTS
343
+ @telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TREATMENTS)
344
+ when GET_TREATMENT_WITH_CONFIG
345
+ @telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TREATMENT_WITH_CONFIG)
346
+ when GET_TREATMENTS_WITH_CONFIG
347
+ @telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TREATMENTS_WITH_CONFIG)
348
+ when TRACK
349
+ @telemetry_evaluation_producer.record_exception(Telemetry::Domain::Constants::TRACK)
350
+ end
351
+ end
318
352
  end
319
353
  end
@@ -8,12 +8,13 @@ module SplitIoClient
8
8
  RUBY_ENCODING = '1.9'.respond_to?(:force_encoding)
9
9
 
10
10
  def initialize(config)
11
- @config = config
11
+ @config = config
12
12
  end
13
13
 
14
- def get_api(url, api_key, params = {})
14
+ def get_api(url, api_key, params = {}, cache_control_headers = false)
15
15
  api_client.get(url, params) do |req|
16
16
  req.headers = common_headers(api_key).merge('Accept-Encoding' => 'gzip')
17
+ req.headers = req.headers.merge('Cache-Control' => 'no-cache') if cache_control_headers
17
18
 
18
19
  req.options[:timeout] = @config.read_timeout
19
20
  req.options[:open_timeout] = @config.connection_timeout
@@ -3,9 +3,10 @@
3
3
  module SplitIoClient
4
4
  module Api
5
5
  class Events < Client
6
- def initialize(api_key, config)
6
+ def initialize(api_key, config, telemetry_runtime_producer)
7
7
  super(config)
8
8
  @api_key = api_key
9
+ @telemetry_runtime_producer = telemetry_runtime_producer
9
10
  end
10
11
 
11
12
  def post(events)
@@ -14,6 +15,8 @@ module SplitIoClient
14
15
  return
15
16
  end
16
17
 
18
+ start = Time.now
19
+
17
20
  events.each_slice(@config.events_queue_size) do |events_slice|
18
21
  response = post_api(
19
22
  "#{@config.events_uri}/events/bulk",
@@ -23,7 +26,13 @@ module SplitIoClient
23
26
 
24
27
  if response.success?
25
28
  @config.split_logger.log_if_debug("Events reported: #{events_slice.size}")
29
+
30
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
31
+ @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::EVENT_SYNC, bucket)
32
+ @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::EVENT_SYNC, (Time.now.to_f * 1000.0).to_i)
26
33
  else
34
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::EVENT_SYNC, response.status)
35
+
27
36
  @config.logger.error("Unexpected status code while posting events: #{response.status}." \
28
37
  ' - Check your API key and base URI')
29
38
  raise 'Split SDK failed to connect to backend to post events'
@@ -3,9 +3,10 @@
3
3
  module SplitIoClient
4
4
  module Api
5
5
  class Impressions < Client
6
- def initialize(api_key, config)
6
+ def initialize(api_key, config, telemetry_runtime_producer)
7
+ super(config)
7
8
  @api_key = api_key
8
- @config = config
9
+ @telemetry_runtime_producer = telemetry_runtime_producer
9
10
  end
10
11
 
11
12
  def post(impressions)
@@ -14,11 +15,19 @@ module SplitIoClient
14
15
  return
15
16
  end
16
17
 
18
+ start = Time.now
19
+
17
20
  response = post_api("#{@config.events_uri}/testImpressions/bulk", @api_key, impressions, impressions_headers)
18
21
 
19
22
  if response.success?
20
23
  @config.split_logger.log_if_debug("Impressions reported: #{total_impressions(impressions)}")
24
+
25
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
26
+ @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::IMPRESSIONS_SYNC, bucket)
27
+ @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::IMPRESSIONS_SYNC, (Time.now.to_f * 1000.0).to_i)
21
28
  else
29
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::IMPRESSIONS_SYNC, response.status)
30
+
22
31
  @config.logger.error("Unexpected status code while posting impressions: #{response.status}." \
23
32
  ' - Check your API key and base URI')
24
33
  raise 'Split SDK failed to connect to backend to post impressions'
@@ -31,11 +40,19 @@ module SplitIoClient
31
40
  return
32
41
  end
33
42
 
43
+ start = Time.now
44
+
34
45
  response = post_api("#{@config.events_uri}/testImpressions/count", @api_key, impressions_count)
35
46
 
36
47
  if response.success?
37
48
  @config.split_logger.log_if_debug("Impressions count sent: #{impressions_count[:pf].length}")
49
+
50
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
51
+ @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::IMPRESSION_COUNT_SYNC, bucket)
52
+ @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::IMPRESSION_COUNT_SYNC, (Time.now.to_f * 1000.0).to_i)
38
53
  else
54
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::IMPRESSION_COUNT_SYNC, response.status)
55
+
39
56
  @config.logger.error("Unexpected status code while posting impressions count: #{response.status}." \
40
57
  ' - Check your API key and base URI')
41
58
  raise 'Split SDK failed to connect to backend to post impressions'
@@ -4,24 +4,20 @@ module SplitIoClient
4
4
  module Api
5
5
  # Retrieves segment changes from the Split Backend
6
6
  class Segments < Client
7
- METRICS_PREFIX = 'segmentChangeFetcher'
8
-
9
- def initialize(api_key, metrics, segments_repository, config)
7
+ def initialize(api_key, segments_repository, config, telemetry_runtime_producer)
10
8
  super(config)
11
- @metrics = metrics
12
9
  @api_key = api_key
13
10
  @segments_repository = segments_repository
11
+ @telemetry_runtime_producer = telemetry_runtime_producer
14
12
  end
15
13
 
16
- def fetch_segments_by_names(names)
17
- start = Time.now
18
-
14
+ def fetch_segments_by_names(names, cache_control_headers = false)
19
15
  return if names.nil? || names.empty?
20
16
 
21
17
  names.each do |name|
22
18
  since = @segments_repository.get_change_number(name)
23
19
  loop do
24
- segment = fetch_segment_changes(name, since)
20
+ segment = fetch_segment_changes(name, since, cache_control_headers)
25
21
  @segments_repository.add_to_segment(segment)
26
22
 
27
23
  @config.split_logger.log_if_debug("Segment #{name} fetched before: #{since}, \
@@ -32,19 +28,17 @@ module SplitIoClient
32
28
  since = @segments_repository.get_change_number(name)
33
29
  end
34
30
  end
35
-
36
- latency = (Time.now - start) * 1000.0
37
- @metrics.time(METRICS_PREFIX + '.time', latency)
38
31
  end
39
32
 
40
33
  private
41
34
 
42
- def fetch_segment_changes(name, since)
43
- response = get_api("#{@config.base_uri}/segmentChanges/#{name}", @api_key, since: since)
35
+ def fetch_segment_changes(name, since, cache_control_headers = false)
36
+ start = Time.now
37
+ response = get_api("#{@config.base_uri}/segmentChanges/#{name}", @api_key, { since: since }, cache_control_headers)
38
+
44
39
  if response.success?
45
40
  segment = JSON.parse(response.body, symbolize_names: true)
46
41
  @segments_repository.set_change_number(name, segment[:till])
47
- @metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
48
42
 
49
43
  @config.split_logger.log_if_debug("\'#{segment[:name]}\' segment retrieved.")
50
44
  unless segment[:added].empty?
@@ -55,15 +49,23 @@ module SplitIoClient
55
49
  end
56
50
  @config.split_logger.log_if_transport("Segment changes response: #{segment.to_s}")
57
51
 
52
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
53
+ @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::SEGMENT_SYNC, bucket)
54
+ @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::SEGMENT_SYNC, (Time.now.to_f * 1000.0).to_i)
55
+
58
56
  segment
59
57
  elsif response.status == 403
60
- @config.logger.error('Factory Instantiation: You passed a browser type api_key, ' \
61
- 'please grab an api key from the Split console that is of type sdk')
62
- @config.valid_mode = false
58
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::SEGMENT_SYNC, response.status)
59
+
60
+ @config.logger.error('Factory Instantiation: You passed a browser type api_key, ' \
61
+ 'please grab an api key from the Split console that is of type sdk')
62
+ @config.valid_mode = false
63
63
  else
64
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::SEGMENT_SYNC, response.status)
65
+
64
66
  @config.logger.error("Unexpected status code while fetching segments: #{response.status}." \
65
67
  "Since #{since} - Check your API key and base URI")
66
- @metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
68
+
67
69
  raise 'Split SDK failed to connect to backend to fetch segments'
68
70
  end
69
71
  end
@@ -4,35 +4,35 @@ module SplitIoClient
4
4
  module Api
5
5
  # Retrieves split definitions from the Split Backend
6
6
  class Splits < Client
7
- METRICS_PREFIX = 'splitChangeFetcher'
8
-
9
- def initialize(api_key, metrics, config)
7
+ def initialize(api_key, config, telemetry_runtime_producer)
10
8
  super(config)
11
9
  @api_key = api_key
12
- @metrics = metrics
10
+ @telemetry_runtime_producer = telemetry_runtime_producer
13
11
  end
14
12
 
15
- def since(since)
13
+ def since(since, cache_control_headers = false)
16
14
  start = Time.now
17
15
 
18
- response = get_api("#{@config.base_uri}/splitChanges", @api_key, since: since)
16
+ response = get_api("#{@config.base_uri}/splitChanges", @api_key, { since: since }, cache_control_headers)
19
17
  if response.success?
20
18
  result = splits_with_segment_names(response.body)
21
19
 
22
- @metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
23
20
  unless result[:splits].empty?
24
21
  @config.split_logger.log_if_debug("#{result[:splits].length} splits retrieved. since=#{since}")
25
22
  end
26
23
  @config.split_logger.log_if_transport("Split changes response: #{result.to_s}")
27
24
 
28
- latency = (Time.now - start) * 1000.0
29
- @metrics.time(METRICS_PREFIX + '.time', latency)
25
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
26
+ @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::SPLIT_SYNC, bucket)
27
+ @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::SPLIT_SYNC, (Time.now.to_f * 1000.0).to_i)
30
28
 
31
29
  result
32
30
  else
33
- @metrics.count(METRICS_PREFIX + '.status.' + response.status.to_s, 1)
31
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::SPLIT_SYNC, response.status)
32
+
34
33
  @config.logger.error("Unexpected status code while fetching splits: #{response.status}. " \
35
34
  'Check your API key and base URI')
35
+
36
36
  raise 'Split SDK failed to connect to backend to fetch split definitions'
37
37
  end
38
38
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ module Api
5
+ class TelemetryApi < Client
6
+ def initialize(config, api_key, telemetry_runtime_producer)
7
+ super(config)
8
+ @api_key = api_key
9
+ @telemetry_runtime_producer = telemetry_runtime_producer
10
+ end
11
+
12
+ def record_init(config_init)
13
+ post_telemetry("#{@config.telemetry_service_url}/metrics/config", config_init, 'init')
14
+ end
15
+
16
+ def record_stats(stats)
17
+ post_telemetry("#{@config.telemetry_service_url}/metrics/usage", stats, 'stats')
18
+ end
19
+
20
+ private
21
+
22
+ def post_telemetry(url, obj, method)
23
+ start = Time.now
24
+ response = post_api(url, @api_key, obj)
25
+
26
+ if response.success?
27
+ @config.split_logger.log_if_debug("Telemetry post succeeded: record #{method}.")
28
+
29
+ bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0)
30
+ @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::TELEMETRY_SYNC, bucket)
31
+ @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::TELEMETRY_SYNC, (Time.now.to_f * 1000.0).to_i)
32
+ else
33
+ @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::TELEMETRY_SYNC, response.status)
34
+ @config.logger.error("Unexpected status code while posting telemetry #{method}: #{response.status}.")
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end