splitclient-rb 7.2.3 → 7.3.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
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