splitclient-rb 4.5.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 +7 -0
- data/.gitignore +45 -0
- data/CHANGES.txt +147 -0
- data/Detailed-README.md +571 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/NEWS +75 -0
- data/README.md +43 -0
- data/Rakefile +24 -0
- data/exe/splitio +96 -0
- data/ext/murmurhash/MurmurHash3.java +162 -0
- data/lib/murmurhash/base.rb +58 -0
- data/lib/murmurhash/murmurhash.jar +0 -0
- data/lib/murmurhash/murmurhash_mri.rb +3 -0
- data/lib/splitclient-rb.rb +90 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapter.rb +12 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +133 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +44 -0
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +165 -0
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +30 -0
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +29 -0
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +41 -0
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +49 -0
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +78 -0
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +21 -0
- data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +129 -0
- data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +98 -0
- data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +22 -0
- data/lib/splitclient-rb/cache/repositories/repository.rb +23 -0
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +82 -0
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +106 -0
- data/lib/splitclient-rb/cache/routers/impression_router.rb +52 -0
- data/lib/splitclient-rb/cache/senders/events_sender.rb +47 -0
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +73 -0
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +67 -0
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +49 -0
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +48 -0
- data/lib/splitclient-rb/cache/stores/segment_store.rb +82 -0
- data/lib/splitclient-rb/cache/stores/split_store.rb +97 -0
- data/lib/splitclient-rb/clients/localhost_split_client.rb +92 -0
- data/lib/splitclient-rb/clients/split_client.rb +214 -0
- data/lib/splitclient-rb/engine/api/client.rb +74 -0
- data/lib/splitclient-rb/engine/api/events.rb +48 -0
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +55 -0
- data/lib/splitclient-rb/engine/api/impressions.rb +42 -0
- data/lib/splitclient-rb/engine/api/metrics.rb +61 -0
- data/lib/splitclient-rb/engine/api/segments.rb +62 -0
- data/lib/splitclient-rb/engine/api/splits.rb +60 -0
- data/lib/splitclient-rb/engine/evaluator/splitter.rb +123 -0
- data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +46 -0
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +56 -0
- data/lib/splitclient-rb/engine/matchers/combiners.rb +9 -0
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +86 -0
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +21 -0
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +19 -0
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +30 -0
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +27 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +54 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +19 -0
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +53 -0
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +53 -0
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +24 -0
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +60 -0
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +23 -0
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +45 -0
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +66 -0
- data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +128 -0
- data/lib/splitclient-rb/engine/metrics/metrics.rb +83 -0
- data/lib/splitclient-rb/engine/models/label.rb +8 -0
- data/lib/splitclient-rb/engine/models/split.rb +17 -0
- data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
- data/lib/splitclient-rb/engine/parser/condition.rb +210 -0
- data/lib/splitclient-rb/engine/parser/evaluator.rb +118 -0
- data/lib/splitclient-rb/engine/parser/partition.rb +35 -0
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +88 -0
- data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +4 -0
- data/lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb +4 -0
- data/lib/splitclient-rb/localhost_split_factory.rb +13 -0
- data/lib/splitclient-rb/localhost_utils.rb +36 -0
- data/lib/splitclient-rb/managers/localhost_split_manager.rb +45 -0
- data/lib/splitclient-rb/managers/split_manager.rb +77 -0
- data/lib/splitclient-rb/split_config.rb +391 -0
- data/lib/splitclient-rb/split_factory.rb +35 -0
- data/lib/splitclient-rb/split_factory_builder.rb +16 -0
- data/lib/splitclient-rb/utilitites.rb +41 -0
- data/lib/splitclient-rb/version.rb +3 -0
- data/splitclient-rb.gemspec +50 -0
- data/splitio.yml.example +7 -0
- data/tasks/benchmark_get_treatment.rake +43 -0
- data/tasks/irb.rake +4 -0
- data/tasks/rspec.rake +3 -0
- metadata +321 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
module Events
|
|
5
|
+
class MemoryRepository < EventsRepository
|
|
6
|
+
EVENTS_SLICE = 100
|
|
7
|
+
|
|
8
|
+
def initialize(adapter, config)
|
|
9
|
+
@adapter = adapter
|
|
10
|
+
@config = config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add(key, traffic_type, event_type, time, value)
|
|
14
|
+
@adapter.add_to_queue(m: metadata, e: event(key, traffic_type, event_type, time, value))
|
|
15
|
+
rescue ThreadError # queue is full
|
|
16
|
+
if @config.debug_enabled
|
|
17
|
+
@config.logger.warn("Dropping events. Current size is #{@config.events_queue_size}. " \
|
|
18
|
+
"Consider increasing events_queue_size")
|
|
19
|
+
end
|
|
20
|
+
@adapter.clear
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def clear
|
|
24
|
+
@adapter.clear
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
module Events
|
|
5
|
+
class RedisRepository < EventsRepository
|
|
6
|
+
EVENTS_SLICE = 100
|
|
7
|
+
|
|
8
|
+
def initialize(adapter, config)
|
|
9
|
+
@adapter = adapter
|
|
10
|
+
@config = config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add(key, traffic_type, event_type, time, value)
|
|
14
|
+
@adapter.add_to_queue(
|
|
15
|
+
namespace_key('.events'),
|
|
16
|
+
{ m: metadata, e: event(key, traffic_type, event_type, time, value) }.to_json,
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def clear
|
|
21
|
+
@adapter.get_from_queue(namespace_key('.events'), EVENTS_SLICE).map do |e|
|
|
22
|
+
JSON.parse(e, symbolize_names: true)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
# Repository which forwards events interface to the selected adapter
|
|
5
|
+
class EventsRepository < Repository
|
|
6
|
+
extend Forwardable
|
|
7
|
+
def_delegators :@adapter, :add, :clear
|
|
8
|
+
|
|
9
|
+
def initialize(adapter, config)
|
|
10
|
+
@config = config
|
|
11
|
+
@adapter = case adapter.class.to_s
|
|
12
|
+
when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
|
|
13
|
+
Repositories::Events::MemoryRepository.new(adapter, config)
|
|
14
|
+
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
|
15
|
+
Repositories::Events::RedisRepository.new(adapter, config)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
|
|
21
|
+
def metadata
|
|
22
|
+
{
|
|
23
|
+
s: "#{@config.language}-#{@config.version}",
|
|
24
|
+
i: @config.machine_ip,
|
|
25
|
+
n: @config.machine_name
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def event(key, traffic_type, event_type, time, value)
|
|
30
|
+
{
|
|
31
|
+
key: key,
|
|
32
|
+
trafficTypeName: traffic_type,
|
|
33
|
+
eventTypeId: event_type,
|
|
34
|
+
value: value,
|
|
35
|
+
timestamp: time
|
|
36
|
+
}.reject { |_, v| v.nil? }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
module Impressions
|
|
5
|
+
class MemoryRepository
|
|
6
|
+
def initialize(adapter, config)
|
|
7
|
+
@adapter = adapter
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Store impression data in the selected adapter
|
|
12
|
+
def add(split_name, data)
|
|
13
|
+
@adapter.add_to_queue(feature: split_name, impressions: data)
|
|
14
|
+
rescue ThreadError # queue is full
|
|
15
|
+
if random_sampler.rand(1..1000) <= 2 # log only 0.2 % of the time
|
|
16
|
+
@config.logger.warn("Dropping impressions. Current size is #{@config.impressions_queue_size}. " \
|
|
17
|
+
"Consider increasing impressions_queue_size")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_bulk(key, bucketing_key, treatments_labels_change_numbers, time)
|
|
22
|
+
treatments_labels_change_numbers.each do |split_name, treatment_label_number|
|
|
23
|
+
add(
|
|
24
|
+
split_name,
|
|
25
|
+
'keyName' => key,
|
|
26
|
+
'bucketingKey' => bucketing_key,
|
|
27
|
+
'treatment' => treatment_label_number[:treatment],
|
|
28
|
+
'label' => @config.labels_enabled ? treatment_label_number[:label] : nil,
|
|
29
|
+
'changeNumber' => treatment_label_number[:change_number],
|
|
30
|
+
'time' => time
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Get everything from the queue and leave it empty
|
|
36
|
+
def clear
|
|
37
|
+
@adapter.clear.map { |impression| impression.update(ip: @config.machine_ip) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def random_sampler
|
|
43
|
+
@random_sampler ||= Random.new
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
module Impressions
|
|
5
|
+
class RedisRepository < Repository
|
|
6
|
+
IMPRESSIONS_SLICE = 1000
|
|
7
|
+
|
|
8
|
+
def initialize(adapter, config)
|
|
9
|
+
@adapter = adapter
|
|
10
|
+
@config = config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Store impression data in Redis
|
|
14
|
+
def add(split_name, data)
|
|
15
|
+
@adapter.add_to_set(
|
|
16
|
+
impressions_metrics_key("impressions.#{split_name}"),
|
|
17
|
+
data.to_json
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_bulk(key, bucketing_key, treatments_labels_change_numbers, time)
|
|
22
|
+
@adapter.redis.pipelined do
|
|
23
|
+
treatments_labels_change_numbers.each_slice(IMPRESSIONS_SLICE) do |treatments_labels_change_numbers_slice|
|
|
24
|
+
treatments_labels_change_numbers_slice.each do |split_name, treatment_label_change_number|
|
|
25
|
+
add(split_name,
|
|
26
|
+
'keyName' => key,
|
|
27
|
+
'bucketingKey' => bucketing_key,
|
|
28
|
+
'treatment' => treatment_label_change_number[:treatment],
|
|
29
|
+
'label' => @config.labels_enabled ? treatment_label_change_number[:label] : nil,
|
|
30
|
+
'changeNumber' => treatment_label_change_number[:change_number],
|
|
31
|
+
'time' => time)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get random impressions from redis in batches of size @config.impressions_queue_size,
|
|
38
|
+
# delete fetched impressions afterwards
|
|
39
|
+
def clear
|
|
40
|
+
impressions = impression_keys.each_with_object([]) do |key, memo|
|
|
41
|
+
ip = key.split('/')[-2] # 'prefix/sdk_lang/ip/impressions.name' -> ip
|
|
42
|
+
if ip.nil?
|
|
43
|
+
@config.logger.warn("Impressions IP parse error for key: #{key}")
|
|
44
|
+
next
|
|
45
|
+
end
|
|
46
|
+
split_name = key.split('.').last
|
|
47
|
+
members = @adapter.random_set_elements(key, @config.impressions_queue_size)
|
|
48
|
+
members.each do |impression|
|
|
49
|
+
parsed_impression = JSON.parse(impression)
|
|
50
|
+
|
|
51
|
+
memo << {
|
|
52
|
+
feature: split_name.to_sym,
|
|
53
|
+
impressions: parsed_impression,
|
|
54
|
+
ip: ip
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
@adapter.delete_from_set(key, members)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
impressions
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
@config.logger.error("Exception while clearing impressions cache: #{e}")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
# Get all sets by prefix
|
|
69
|
+
def impression_keys
|
|
70
|
+
@adapter.find_sets_by_prefix("#{@config.redis_namespace}/*/impressions.*")
|
|
71
|
+
rescue StandardError => e
|
|
72
|
+
@config.logger.error("Exception while fetching impression_keys: #{e}")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
# Repository which forwards impressions interface to the selected adapter
|
|
5
|
+
class ImpressionsRepository < Repository
|
|
6
|
+
extend Forwardable
|
|
7
|
+
def_delegators :@adapter, :add, :add_bulk, :clear, :empty?
|
|
8
|
+
|
|
9
|
+
def initialize(adapter, config)
|
|
10
|
+
@config = config
|
|
11
|
+
@adapter = case adapter.class.to_s
|
|
12
|
+
when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
|
|
13
|
+
Repositories::Impressions::MemoryRepository.new(adapter, config)
|
|
14
|
+
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
|
15
|
+
Repositories::Impressions::RedisRepository.new(adapter, config)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
module Metrics
|
|
5
|
+
class MemoryRepository
|
|
6
|
+
def initialize(_ = nil, adapter, config)
|
|
7
|
+
@counts = []
|
|
8
|
+
@latencies = []
|
|
9
|
+
@gauges = []
|
|
10
|
+
|
|
11
|
+
@config = config
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def add_count(counter, delta)
|
|
15
|
+
counter_hash = @counts.find { |c| c[:name] == counter }
|
|
16
|
+
if counter_hash.nil?
|
|
17
|
+
counter_delta = SumAndCount.new
|
|
18
|
+
counter_delta.add_delta(delta)
|
|
19
|
+
@counts << { name: counter, delta: counter_delta }
|
|
20
|
+
else
|
|
21
|
+
counter_hash[:delta].add_delta(delta)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_latency(operation, time_in_ms, binary_search)
|
|
26
|
+
operation_hash = @latencies.find { |l| l[:operation] == operation }
|
|
27
|
+
if operation_hash.nil?
|
|
28
|
+
latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : [time_in_ms]
|
|
29
|
+
@latencies << { operation: operation, latencies: latencies_for_op }
|
|
30
|
+
else
|
|
31
|
+
latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : operation_hash[:latencies].push(time_in_ms)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def add_gauge(gauge, value)
|
|
36
|
+
gauge_hash = @gauges.find { |g| g[:name] == gauge }
|
|
37
|
+
if gauge_hash.nil?
|
|
38
|
+
gauge_value = ValueAndCount.new
|
|
39
|
+
gauge_value.set_value(value)
|
|
40
|
+
@gauges << { name: gauge, value: gauge_value }
|
|
41
|
+
else
|
|
42
|
+
gauge_hash[:value].set_value(value)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def counts
|
|
47
|
+
@counts.each_with_object({}) do |count, memo|
|
|
48
|
+
memo[count[:name]] = count[:delta].sum
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def latencies
|
|
53
|
+
@latencies.each_with_object({}) do |latency, memo|
|
|
54
|
+
memo[latency[:operation]] = latency[:latencies]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def gauges
|
|
59
|
+
# TODO
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def clear_counts
|
|
63
|
+
@counts = []
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def clear_latencies
|
|
67
|
+
@latencies = []
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def clear_gauges
|
|
71
|
+
@gauges = []
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def clear
|
|
75
|
+
clear_counts
|
|
76
|
+
clear_latencies
|
|
77
|
+
clear_gauges
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# small class to act as DTO for counts
|
|
82
|
+
#
|
|
83
|
+
class SumAndCount
|
|
84
|
+
attr_reader :count
|
|
85
|
+
attr_reader :sum
|
|
86
|
+
|
|
87
|
+
def initialize
|
|
88
|
+
@count = 0
|
|
89
|
+
@sum = 0
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def add_delta(delta)
|
|
93
|
+
@count += 1
|
|
94
|
+
@sum += delta
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def clear
|
|
98
|
+
@count = 0
|
|
99
|
+
@sum = 0
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#
|
|
104
|
+
# small class to act as DTO for gauges
|
|
105
|
+
#
|
|
106
|
+
class ValueAndCount
|
|
107
|
+
attr_reader :count
|
|
108
|
+
attr_reader :value
|
|
109
|
+
|
|
110
|
+
def initialize
|
|
111
|
+
@count = 0
|
|
112
|
+
@value = 0
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def set_value(value)
|
|
116
|
+
@count += 1
|
|
117
|
+
@value = value
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def clear
|
|
121
|
+
@count = 0
|
|
122
|
+
@value = 0
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
module Cache
|
|
3
|
+
module Repositories
|
|
4
|
+
module Metrics
|
|
5
|
+
class RedisRepository < Repository
|
|
6
|
+
def initialize(adapter = nil, config)
|
|
7
|
+
@config = config
|
|
8
|
+
@adapter = 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
|
+
latencies = @adapter.find_strings_by_prefix(prefixed_name)
|
|
21
|
+
|
|
22
|
+
if operation == 'sdk.get_treatment'
|
|
23
|
+
@adapter.inc("#{prefixed_name}.#{binary_search.add_latency_millis(time_in_ms, true)}")
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
@adapter.append_to_string(prefixed_name, "#{time_in_ms},")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add_gauge(gauge, value)
|
|
31
|
+
# TODO
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def counts
|
|
35
|
+
keys = @adapter.find_strings_by_prefix(impressions_metrics_key("count"))
|
|
36
|
+
|
|
37
|
+
return [] if keys.empty?
|
|
38
|
+
|
|
39
|
+
@adapter.multiple_strings(keys).map do |name, data|
|
|
40
|
+
[name.gsub(impressions_metrics_key('count.'), ''), data]
|
|
41
|
+
end.to_h
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def latencies
|
|
45
|
+
collected_latencies = {}
|
|
46
|
+
latencies_array = Array.new(BinarySearchLatencyTracker::BUCKETS.length, 0)
|
|
47
|
+
keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
|
|
48
|
+
|
|
49
|
+
return [] if keys.empty?
|
|
50
|
+
|
|
51
|
+
found_latencies = @adapter.multiple_strings(keys).map do |name, data|
|
|
52
|
+
[name.gsub(impressions_metrics_key('latency.'), ''), data]
|
|
53
|
+
end.to_h
|
|
54
|
+
|
|
55
|
+
found_latencies.each do |key, value|
|
|
56
|
+
if key.start_with?('sdk.get_treatment')
|
|
57
|
+
index = key.gsub('sdk.get_treatment.', '').to_i
|
|
58
|
+
latencies_array[index] = value.to_i
|
|
59
|
+
|
|
60
|
+
next
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
collected_latencies[key] = value.split(',').map(&:to_f)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
collected_latencies['sdk.get_treatment'] = latencies_array unless latencies_array.reduce(:+) == 0
|
|
67
|
+
|
|
68
|
+
collected_latencies
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def gauges
|
|
72
|
+
# TODO
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def clear_counts
|
|
76
|
+
keys = @adapter.find_strings_by_prefix(impressions_metrics_key('count'))
|
|
77
|
+
@adapter.delete(keys)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def clear_latencies
|
|
81
|
+
keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
|
|
82
|
+
@adapter.delete(keys)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def clear_gauges
|
|
86
|
+
# TODO
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def clear
|
|
90
|
+
clear_counts
|
|
91
|
+
clear_latencies
|
|
92
|
+
clear_gauges
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|