splitclient-rb 7.2.3 → 7.3.0.pre.rc1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -0
  3. data/lib/splitclient-rb.rb +24 -9
  4. data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +4 -0
  5. data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +8 -7
  6. data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +7 -7
  7. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +6 -3
  8. data/lib/splitclient-rb/cache/repositories/events_repository.rb +4 -3
  9. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +8 -0
  10. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +2 -0
  11. data/lib/splitclient-rb/cache/repositories/repository.rb +0 -4
  12. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +20 -0
  13. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +4 -0
  14. data/lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb +1 -3
  15. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +9 -0
  16. data/lib/splitclient-rb/clients/split_client.rb +59 -25
  17. data/lib/splitclient-rb/engine/api/client.rb +3 -2
  18. data/lib/splitclient-rb/engine/api/events.rb +10 -1
  19. data/lib/splitclient-rb/engine/api/impressions.rb +19 -2
  20. data/lib/splitclient-rb/engine/api/segments.rb +20 -18
  21. data/lib/splitclient-rb/engine/api/splits.rb +10 -10
  22. data/lib/splitclient-rb/engine/api/telemetry_api.rb +39 -0
  23. data/lib/splitclient-rb/engine/auth_api_client.rb +21 -8
  24. data/lib/splitclient-rb/engine/common/impressions_manager.rb +27 -3
  25. data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +3 -65
  26. data/lib/splitclient-rb/engine/push_manager.rb +10 -2
  27. data/lib/splitclient-rb/engine/sync_manager.rb +42 -20
  28. data/lib/splitclient-rb/engine/synchronizer.rb +13 -12
  29. data/lib/splitclient-rb/split_config.rb +46 -21
  30. data/lib/splitclient-rb/split_factory.rb +31 -13
  31. data/lib/splitclient-rb/split_factory_registry.rb +12 -0
  32. data/lib/splitclient-rb/sse/event_source/client.rb +10 -1
  33. data/lib/splitclient-rb/sse/notification_manager_keeper.rb +17 -3
  34. data/lib/splitclient-rb/sse/sse_handler.rb +10 -6
  35. data/lib/splitclient-rb/telemetry/domain/constants.rb +42 -0
  36. data/lib/splitclient-rb/telemetry/domain/structs.rb +31 -0
  37. data/lib/splitclient-rb/telemetry/evaluation_consumer.rb +14 -0
  38. data/lib/splitclient-rb/telemetry/evaluation_producer.rb +21 -0
  39. data/lib/splitclient-rb/telemetry/init_consumer.rb +14 -0
  40. data/lib/splitclient-rb/telemetry/init_producer.rb +19 -0
  41. data/lib/splitclient-rb/telemetry/memory/memory_evaluation_consumer.rb +32 -0
  42. data/lib/splitclient-rb/telemetry/memory/memory_evaluation_producer.rb +24 -0
  43. data/lib/splitclient-rb/telemetry/memory/memory_init_consumer.rb +28 -0
  44. data/lib/splitclient-rb/telemetry/memory/memory_init_producer.rb +34 -0
  45. data/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb +112 -0
  46. data/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb +81 -0
  47. data/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +192 -0
  48. data/lib/splitclient-rb/telemetry/redis/redis_evaluation_producer.rb +38 -0
  49. data/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +37 -0
  50. data/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb +28 -0
  51. data/lib/splitclient-rb/telemetry/runtime_consumer.rb +24 -0
  52. data/lib/splitclient-rb/telemetry/runtime_producer.rb +24 -0
  53. data/lib/splitclient-rb/telemetry/storages/memory.rb +139 -0
  54. data/lib/splitclient-rb/telemetry/sync_task.rb +38 -0
  55. data/lib/splitclient-rb/telemetry/synchronizer.rb +29 -0
  56. data/lib/splitclient-rb/version.rb +1 -1
  57. metadata +26 -11
  58. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +0 -163
  59. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +0 -131
  60. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +0 -23
  61. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +0 -55
  62. data/lib/splitclient-rb/engine/api/metrics.rb +0 -61
  63. data/lib/splitclient-rb/engine/metrics/metrics.rb +0 -80
  64. data/lib/splitclient-rb/redis_metrics_fixer.rb +0 -36
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ module Telemetry
5
+ class SyncTask
6
+ def initialize(config, telemetry_synchronizer)
7
+ @config = config
8
+ @telemetry_synchronizer = telemetry_synchronizer
9
+ end
10
+
11
+ def call
12
+ stats_thread
13
+
14
+ PhusionPassenger.on_event(:starting_worker_process) { |forked| stats_thread if forked } if defined?(PhusionPassenger)
15
+ end
16
+
17
+ private
18
+
19
+ def stats_thread
20
+ @config.threads[:telemetry_stats_sender] = Thread.new do
21
+ begin
22
+ @config.logger.info('Starting Telemetry Sync Task')
23
+
24
+ loop do
25
+ sleep(@config.telemetry_refresh_rate)
26
+
27
+ @telemetry_synchronizer.synchronize_stats
28
+ end
29
+ rescue SplitIoClient::SDKShutdownException
30
+ @telemetry_synchronizer.synchronize_stats
31
+
32
+ @config.logger.info('Posting Telemetry due to shutdown')
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SplitIoClient
4
+ module Telemetry
5
+ class Synchronizer
6
+ extend Forwardable
7
+ def_delegators :@synchronizer,
8
+ :synchronize_config,
9
+ :synchronize_stats
10
+
11
+ def initialize(config,
12
+ telemtry_consumers,
13
+ telemetry_init_producer,
14
+ repositories,
15
+ telemetry_api)
16
+ @synchronizer = case config.telemetry_adapter.class.to_s
17
+ when 'SplitIoClient::Cache::Adapters::RedisAdapter'
18
+ SplitIoClient::Telemetry::RedisSynchronizer.new(config,
19
+ telemetry_init_producer)
20
+ else
21
+ SplitIoClient::Telemetry::MemorySynchronizer.new(config,
22
+ telemtry_consumers,
23
+ repositories,
24
+ telemetry_api)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '7.2.3'
2
+ VERSION = '7.3.0.pre.rc1'
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: 7.2.3
4
+ version: 7.3.0.pre.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Split Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-24 00:00:00.000000000 Z
11
+ date: 2021-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allocation_stats
@@ -350,9 +350,6 @@ files:
350
350
  - lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb
351
351
  - lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb
352
352
  - lib/splitclient-rb/cache/repositories/impressions_repository.rb
353
- - lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb
354
- - lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb
355
- - lib/splitclient-rb/cache/repositories/metrics_repository.rb
356
353
  - lib/splitclient-rb/cache/repositories/repository.rb
357
354
  - lib/splitclient-rb/cache/repositories/segments_repository.rb
358
355
  - lib/splitclient-rb/cache/repositories/splits_repository.rb
@@ -362,7 +359,6 @@ files:
362
359
  - lib/splitclient-rb/cache/senders/impressions_formatter.rb
363
360
  - lib/splitclient-rb/cache/senders/impressions_sender.rb
364
361
  - lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb
365
- - lib/splitclient-rb/cache/senders/metrics_sender.rb
366
362
  - lib/splitclient-rb/cache/stores/localhost_split_builder.rb
367
363
  - lib/splitclient-rb/cache/stores/localhost_split_store.rb
368
364
  - lib/splitclient-rb/cache/stores/sdk_blocker.rb
@@ -374,9 +370,9 @@ files:
374
370
  - lib/splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent.rb
375
371
  - lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb
376
372
  - lib/splitclient-rb/engine/api/impressions.rb
377
- - lib/splitclient-rb/engine/api/metrics.rb
378
373
  - lib/splitclient-rb/engine/api/segments.rb
379
374
  - lib/splitclient-rb/engine/api/splits.rb
375
+ - lib/splitclient-rb/engine/api/telemetry_api.rb
380
376
  - lib/splitclient-rb/engine/auth_api_client.rb
381
377
  - lib/splitclient-rb/engine/common/impressions_counter.rb
382
378
  - lib/splitclient-rb/engine/common/impressions_manager.rb
@@ -404,7 +400,6 @@ files:
404
400
  - lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb
405
401
  - lib/splitclient-rb/engine/matchers/whitelist_matcher.rb
406
402
  - lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb
407
- - lib/splitclient-rb/engine/metrics/metrics.rb
408
403
  - lib/splitclient-rb/engine/models/label.rb
409
404
  - lib/splitclient-rb/engine/models/split.rb
410
405
  - lib/splitclient-rb/engine/models/treatment.rb
@@ -417,7 +412,6 @@ files:
417
412
  - lib/splitclient-rb/exceptions.rb
418
413
  - lib/splitclient-rb/helpers/thread_helper.rb
419
414
  - lib/splitclient-rb/managers/split_manager.rb
420
- - lib/splitclient-rb/redis_metrics_fixer.rb
421
415
  - lib/splitclient-rb/split_config.rb
422
416
  - lib/splitclient-rb/split_factory.rb
423
417
  - lib/splitclient-rb/split_factory_builder.rb
@@ -433,6 +427,27 @@ files:
433
427
  - lib/splitclient-rb/sse/sse_handler.rb
434
428
  - lib/splitclient-rb/sse/workers/segments_worker.rb
435
429
  - lib/splitclient-rb/sse/workers/splits_worker.rb
430
+ - lib/splitclient-rb/telemetry/domain/constants.rb
431
+ - lib/splitclient-rb/telemetry/domain/structs.rb
432
+ - lib/splitclient-rb/telemetry/evaluation_consumer.rb
433
+ - lib/splitclient-rb/telemetry/evaluation_producer.rb
434
+ - lib/splitclient-rb/telemetry/init_consumer.rb
435
+ - lib/splitclient-rb/telemetry/init_producer.rb
436
+ - lib/splitclient-rb/telemetry/memory/memory_evaluation_consumer.rb
437
+ - lib/splitclient-rb/telemetry/memory/memory_evaluation_producer.rb
438
+ - lib/splitclient-rb/telemetry/memory/memory_init_consumer.rb
439
+ - lib/splitclient-rb/telemetry/memory/memory_init_producer.rb
440
+ - lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb
441
+ - lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb
442
+ - lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb
443
+ - lib/splitclient-rb/telemetry/redis/redis_evaluation_producer.rb
444
+ - lib/splitclient-rb/telemetry/redis/redis_init_producer.rb
445
+ - lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb
446
+ - lib/splitclient-rb/telemetry/runtime_consumer.rb
447
+ - lib/splitclient-rb/telemetry/runtime_producer.rb
448
+ - lib/splitclient-rb/telemetry/storages/memory.rb
449
+ - lib/splitclient-rb/telemetry/sync_task.rb
450
+ - lib/splitclient-rb/telemetry/synchronizer.rb
436
451
  - lib/splitclient-rb/utilitites.rb
437
452
  - lib/splitclient-rb/validators.rb
438
453
  - lib/splitclient-rb/version.rb
@@ -455,9 +470,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
455
470
  version: '0'
456
471
  required_rubygems_version: !ruby/object:Gem::Requirement
457
472
  requirements:
458
- - - ">="
473
+ - - ">"
459
474
  - !ruby/object:Gem::Version
460
- version: '0'
475
+ version: 1.3.1
461
476
  requirements: []
462
477
  rubygems_version: 3.0.6
463
478
  signing_key:
@@ -1,163 +0,0 @@
1
- require 'concurrent'
2
-
3
- module SplitIoClient
4
- module Cache
5
- module Repositories
6
- module Metrics
7
- class MemoryRepository
8
- OPERATIONS = %w(sdk.get_treatment sdk.get_treatments sdk.get_treatment_with_config sdk.get_treatments_with_config)
9
-
10
- def initialize(_ = nil, config)
11
- @counts = Concurrent::Array.new
12
- @latencies = Concurrent::Array.new
13
- @gauges = Concurrent::Array.new
14
- @config = config
15
- end
16
-
17
- def add_count(counter, delta)
18
- counter_hash = @counts.find { |c| c[:name] == counter }
19
- if counter_hash.nil?
20
- counter_delta = SumAndCount.new
21
- counter_delta.add_delta(delta)
22
- @counts << { name: counter, delta: counter_delta }
23
- else
24
- counter_hash[:delta].add_delta(delta)
25
- end
26
- end
27
-
28
- def add_latency(operation, time_in_ms, binary_search)
29
- if (OPERATIONS.include?(operation))
30
- index = binary_search.add_latency_millis(time_in_ms, true)
31
- increase_latency_bucket(operation, index)
32
- else
33
- concatenate_latency(operation, time_in_ms)
34
- end
35
- end
36
-
37
- def add_gauge(gauge, value)
38
- gauge_hash = @gauges.find { |g| g[:name] == gauge }
39
- if gauge_hash.nil?
40
- gauge_value = ValueAndCount.new
41
- gauge_value.set_value(value)
42
- @gauges << { name: gauge, value: gauge_value }
43
- else
44
- gauge_hash[:value].set_value(value)
45
- end
46
- end
47
-
48
- def counts
49
- @counts.each_with_object({}) do |count, memo|
50
- memo[count[:name]] = count[:delta].sum
51
- end
52
- end
53
-
54
- def latencies
55
- @latencies.each_with_object({}) do |latency, memo|
56
- memo[latency[:operation]] = latency[:latencies]
57
- end
58
- end
59
-
60
- def gauges
61
- # TODO
62
- end
63
-
64
- def fix_latencies
65
- # NOOP
66
- end
67
-
68
- def clear_counts
69
- @counts = Concurrent::Array.new
70
- end
71
-
72
- def clear_latencies
73
- @latencies = Concurrent::Array.new
74
- end
75
-
76
- def clear_gauges
77
- @gauges = Concurrent::Array.new
78
- end
79
-
80
- def clear
81
- clear_counts
82
- clear_latencies
83
- clear_gauges
84
- end
85
-
86
- #
87
- # small class to act as DTO for counts
88
- #
89
- class SumAndCount
90
- attr_reader :count
91
- attr_reader :sum
92
-
93
- def initialize
94
- @count = 0
95
- @sum = 0
96
- end
97
-
98
- def add_delta(delta)
99
- @count += 1
100
- @sum += delta
101
- end
102
-
103
- def clear
104
- @count = 0
105
- @sum = 0
106
- end
107
- end
108
-
109
- #
110
- # small class to act as DTO for gauges
111
- #
112
- class ValueAndCount
113
- attr_reader :count
114
- attr_reader :value
115
-
116
- def initialize
117
- @count = 0
118
- @value = 0
119
- end
120
-
121
- def set_value(value)
122
- @count += 1
123
- @value = value
124
- end
125
-
126
- def clear
127
- @count = 0
128
- @value = 0
129
- end
130
- end
131
-
132
- private
133
-
134
- def increase_latency_bucket(operation, index)
135
- operation_latencies = find_operation_latencies(operation)
136
-
137
- if (operation_latencies.nil?)
138
- latencies_array = Array.new(BinarySearchLatencyTracker::BUCKETS.length, 0)
139
- latencies_array[index] = 1
140
- @latencies << { operation: operation, latencies: latencies_array }
141
- else
142
- operation_latencies[:latencies][index] += 1
143
- end
144
- end
145
-
146
- def concatenate_latency(operation, time_in_ms)
147
- operation_latencies = find_operation_latencies(operation)
148
-
149
- if (operation_latencies.nil?)
150
- @latencies << { operation: operation, latencies: [time_in_ms] }
151
- else
152
- operation_latencies[:latencies].push(time_in_ms)
153
- end
154
- end
155
-
156
- def find_operation_latencies(operation)
157
- @latencies.find { |l| l[:operation] == operation }
158
- end
159
- end
160
- end
161
- end
162
- end
163
- end
@@ -1,131 +0,0 @@
1
- module SplitIoClient
2
- module Cache
3
- module Repositories
4
- module Metrics
5
- class RedisRepository < Repository
6
- def initialize(config)
7
- @config = config
8
- @adapter = config.metrics_adapter
9
- end
10
-
11
- def add_count(counter, delta)
12
- prefixed_name = impressions_metrics_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 = impressions_metrics_key("latency.#{operation}")
20
-
21
- @adapter.inc("#{prefixed_name}.bucket.#{binary_search.add_latency_millis(time_in_ms, true)}")
22
- end
23
-
24
- def add_gauge(gauge, value)
25
- # TODO
26
- end
27
-
28
- def counts
29
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key("count"))
30
-
31
- return [] if keys.empty?
32
-
33
- @adapter.multiple_strings(keys).map do |name, data|
34
- [name.gsub(impressions_metrics_key('count.'), ''), data]
35
- end.to_h
36
- end
37
-
38
- def latencies
39
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
40
- return [] if keys.empty?
41
-
42
- collected_latencies = collect_latencies(keys)
43
-
44
- collected_latencies.keys.each_with_object({}) do |operation, latencies|
45
- operation_latencies = Array.new(BinarySearchLatencyTracker::BUCKETS.length, 0)
46
- collected_latencies[operation].each do |bucket, value|
47
- operation_latencies[bucket.to_i] = value.to_i
48
- end
49
-
50
- latencies[operation] = operation_latencies
51
- end
52
- end
53
-
54
- def gauges
55
- # TODO
56
- end
57
-
58
- def clear_counts
59
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key('count'))
60
- @adapter.delete(keys)
61
- end
62
-
63
- def clear_latencies
64
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
65
- @adapter.delete(keys)
66
- end
67
-
68
- # introduced to fix incorrect latencies
69
- def fix_latencies
70
- latencies_cleaned_key = namespace_key('/latencies.cleaned')
71
- return if @adapter.exists?(latencies_cleaned_key)
72
-
73
- keys =[]
74
-
75
- 23.times do |index|
76
- keys.concat @adapter.find_strings_by_pattern(latencies_to_be_deleted_key_pattern_prefix("sdk.get_treatment.#{index}"))
77
- end
78
-
79
- keys.concat @adapter.find_strings_by_pattern(latencies_to_be_deleted_key_pattern_prefix('sdk.get_treatments'))
80
- keys.concat @adapter.find_strings_by_pattern(latencies_to_be_deleted_key_pattern_prefix('sdk.get_treatment_with_config'))
81
- keys.concat @adapter.find_strings_by_pattern(latencies_to_be_deleted_key_pattern_prefix('sdk.get_treatments_with_config'))
82
-
83
- keys.concat @adapter.find_strings_by_pattern(latencies_to_be_deleted_key_pattern_prefix('*.time'))
84
-
85
- @config.logger.info("Found incorrect latency keys, deleting. Keys: #{keys}") unless keys.size == 0
86
-
87
- keys.each_slice(500) do |chunk|
88
- @adapter.pipelined do
89
- chunk.each do |key|
90
- @adapter.delete key
91
- end
92
- end
93
- end
94
-
95
- @adapter.set_string(latencies_cleaned_key, '1')
96
- end
97
-
98
- def latencies_to_be_deleted_key_pattern_prefix(key)
99
- "#{@config.redis_namespace}/#{@config.language}-*/latency.#{key}"
100
- end
101
-
102
- def clear_gauges
103
- # TODO
104
- end
105
-
106
- def clear
107
- clear_counts
108
- clear_latencies
109
- clear_gauges
110
- end
111
-
112
- private
113
-
114
- def find_latencies(keys)
115
- @adapter.multiple_strings(keys).map do |name, data|
116
- [name.gsub(impressions_metrics_key('latency.'), ''), data]
117
- end.to_h
118
- end
119
-
120
- def collect_latencies(keys)
121
- find_latencies(keys).each_with_object({}) do |(key, value), collected_latencies|
122
- operation, bucket = key.split('.bucket.')
123
- collected_latencies[operation] = {} unless collected_latencies[operation]
124
- collected_latencies[operation].merge!({bucket => value})
125
- end
126
- end
127
- end
128
- end
129
- end
130
- end
131
- end