splitclient-rb 4.5.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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,53 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class LessThanOrEqualToMatcher
|
3
|
+
MATCHER_TYPE = 'LESS_THAN_OR_EQUAL_TO'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
|
+
|
7
|
+
def initialize(attribute_hash)
|
8
|
+
@attribute = attribute_hash[:attribute]
|
9
|
+
@data_type = attribute_hash[:data_type]
|
10
|
+
@value = formatted_value(attribute_hash[:value], true)
|
11
|
+
end
|
12
|
+
|
13
|
+
def match?(args)
|
14
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
15
|
+
return false if args.key?(:value) && args[:value].nil?
|
16
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
17
|
+
|
18
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
19
|
+
|
20
|
+
value.is_a?(Integer) ? (value <= @value) : false
|
21
|
+
end
|
22
|
+
|
23
|
+
def equals?(obj)
|
24
|
+
if obj.nil?
|
25
|
+
false
|
26
|
+
elsif !obj.instance_of?(LessThanOrEqualToMatcher)
|
27
|
+
false
|
28
|
+
elsif self.equal?(obj)
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def string_type?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def formatted_value(value, sdk_data = false)
|
42
|
+
case @data_type
|
43
|
+
when 'NUMBER'
|
44
|
+
return value
|
45
|
+
when 'DATETIME'
|
46
|
+
value = value / 1000 if sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_our
|
47
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
|
48
|
+
else
|
49
|
+
@logger.error('Invalid data type')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class MatchesStringMatcher
|
3
|
+
MATCHER_TYPE = 'MATCHES_STRING'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
|
+
|
7
|
+
def initialize(attribute, regexp_string)
|
8
|
+
@attribute = attribute
|
9
|
+
@regexp_string = @regexp_string.is_a?(Regexp) ? regexp_string : Regexp.new(regexp_string)
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(args)
|
13
|
+
value = args[:value] || args[:attributes].fetch(@attribute) do |a|
|
14
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
+
end
|
16
|
+
|
17
|
+
(value =~ @regexp_string) != nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def string_type?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
#
|
3
|
+
# class to implement the negation of a matcher
|
4
|
+
#
|
5
|
+
class NegationMatcher
|
6
|
+
MATCHER_TYPE = 'NEGATION_MATCHER'.freeze
|
7
|
+
|
8
|
+
def initialize(matcher = nil)
|
9
|
+
@matcher = matcher
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# evaluates if the key matches the negation of the matcher
|
14
|
+
#
|
15
|
+
# @param key [string] key value to be matched
|
16
|
+
#
|
17
|
+
# @return [boolean] evaluation of the negation matcher
|
18
|
+
def match?(args)
|
19
|
+
!@matcher.match?(args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to?(method)
|
23
|
+
@matcher.respond_to? method
|
24
|
+
end
|
25
|
+
|
26
|
+
def attribute
|
27
|
+
@matcher.attribute
|
28
|
+
end
|
29
|
+
|
30
|
+
def string_type?
|
31
|
+
@matcher.string_type?
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# evaluates if the given object equals the matcher
|
36
|
+
#
|
37
|
+
# @param obj [object] object to be evaluated
|
38
|
+
#
|
39
|
+
# @returns [boolean] true if obj equals the matcher
|
40
|
+
def equals?(obj)
|
41
|
+
if obj.nil?
|
42
|
+
false
|
43
|
+
elsif !obj.instance_of?(NegationMatcher)
|
44
|
+
false
|
45
|
+
elsif self.equal?(obj)
|
46
|
+
true
|
47
|
+
else
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# function to print string value for this matcher
|
54
|
+
#
|
55
|
+
# @reutrn [string] string value of this matcher
|
56
|
+
def to_s
|
57
|
+
"not #{@matcher}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class PartOfSetMatcher < SetMatcher
|
3
|
+
MATCHER_TYPE = 'PART_OF_SET'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
|
+
|
7
|
+
def initialize(attribute, remote_array)
|
8
|
+
super(attribute, remote_array)
|
9
|
+
end
|
10
|
+
|
11
|
+
def match?(args)
|
12
|
+
@local_set = local_set(args[:attributes], @attribute)
|
13
|
+
|
14
|
+
return false if @local_set.empty?
|
15
|
+
|
16
|
+
@local_set.subset? @remote_set
|
17
|
+
end
|
18
|
+
|
19
|
+
def string_type?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
class SetMatcher
|
5
|
+
protected
|
6
|
+
|
7
|
+
def initialize(attribute, remote_array)
|
8
|
+
@attribute = attribute
|
9
|
+
@remote_set = remote_array.to_set
|
10
|
+
end
|
11
|
+
|
12
|
+
def local_set(data, attribute)
|
13
|
+
data = data.fetch(attribute) { |a| data[a.to_s] || data[a.to_sym] }
|
14
|
+
# Allow user to pass individual elements as well
|
15
|
+
local_array = data.kind_of?(Array) ? data : [data]
|
16
|
+
|
17
|
+
local_array.to_set
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class StartsWithMatcher
|
3
|
+
MATCHER_TYPE = 'STARTS_WITH'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
|
+
|
7
|
+
def initialize(attribute, prefix_list)
|
8
|
+
@attribute = attribute
|
9
|
+
@prefix_list = prefix_list
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(args)
|
13
|
+
value = args[:value] || args[:attributes].fetch(@attribute) do |a|
|
14
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
+
end
|
16
|
+
|
17
|
+
return false if @prefix_list.empty?
|
18
|
+
|
19
|
+
@prefix_list.any? { |prefix| value.to_s.start_with? prefix }
|
20
|
+
end
|
21
|
+
|
22
|
+
def string_type?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
#
|
3
|
+
# class to implement the user defined matcher
|
4
|
+
#
|
5
|
+
class UserDefinedSegmentMatcher
|
6
|
+
MATCHER_TYPE = 'IN_SEGMENT'.freeze
|
7
|
+
|
8
|
+
def initialize(segments_repository, segment_name)
|
9
|
+
@segments_repository = segments_repository
|
10
|
+
@segment_name = segment_name
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# evaluates if the key matches the matcher
|
15
|
+
#
|
16
|
+
# @param key [string] key value to be matched
|
17
|
+
#
|
18
|
+
# @return [boolean] evaluation of the key against the segment
|
19
|
+
def match?(args)
|
20
|
+
@segments_repository.in_segment?(@segment_name, args[:value] || args[:matching_key])
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# evaluates if the given object equals the matcher
|
25
|
+
#
|
26
|
+
# @param obj [object] object to be evaluated
|
27
|
+
#
|
28
|
+
# @returns [boolean] true if obj equals the matcher
|
29
|
+
def equals?(obj)
|
30
|
+
if obj.nil?
|
31
|
+
false
|
32
|
+
elsif !obj.instance_of?(UserDefinedSegmentMatcher)
|
33
|
+
false
|
34
|
+
elsif self.equal?(obj)
|
35
|
+
true
|
36
|
+
else
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def string_type?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
#
|
3
|
+
# class to implement the user defined matcher
|
4
|
+
#
|
5
|
+
class WhitelistMatcher < NoMethodError
|
6
|
+
MATCHER_TYPE = 'WHITELIST_MATCHER'
|
7
|
+
|
8
|
+
attr_reader :attribute
|
9
|
+
|
10
|
+
def initialize(whitelist_data)
|
11
|
+
@whitelist = case whitelist_data
|
12
|
+
when Array
|
13
|
+
whitelist_data
|
14
|
+
when Hash
|
15
|
+
@matcher_type = 'ATTR_WHITELIST'
|
16
|
+
@attribute = whitelist_data[:attribute]
|
17
|
+
|
18
|
+
whitelist_data[:value]
|
19
|
+
else
|
20
|
+
[]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def match?(args)
|
25
|
+
return @whitelist.include?(args[:value] || args[:matching_key]) unless @matcher_type == 'ATTR_WHITELIST'
|
26
|
+
|
27
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
28
|
+
return false if args.key?(:value) && args[:value].nil?
|
29
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
30
|
+
|
31
|
+
return @whitelist.include?(args[:value] || args[:attributes][@attribute.to_sym])
|
32
|
+
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# evaluates if the given object equals the matcher
|
38
|
+
#
|
39
|
+
# @param obj [object] object to be evaluated
|
40
|
+
#
|
41
|
+
# @returns [boolean] true if obj equals the matcher
|
42
|
+
def equals?(obj)
|
43
|
+
if obj.nil?
|
44
|
+
false
|
45
|
+
elsif !obj.instance_of?(WhitelistMatcher)
|
46
|
+
false
|
47
|
+
elsif self.equal?(obj)
|
48
|
+
true
|
49
|
+
else
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def string_type?
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# function to print string value for this matcher
|
60
|
+
#
|
61
|
+
# @reutrn [string] string value of this matcher
|
62
|
+
def to_s
|
63
|
+
"in segment #{@whitelist}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
|
3
|
+
#
|
4
|
+
# Tracks latencies pero bucket of time.
|
5
|
+
# Each bucket represent a latency greater than the one before
|
6
|
+
# and each number within each bucket is a number of calls in the range.
|
7
|
+
#
|
8
|
+
# (1) 1.00
|
9
|
+
# (2) 1.50
|
10
|
+
# (3) 2.25
|
11
|
+
# (4) 3.38
|
12
|
+
# (5) 5.06
|
13
|
+
# (6) 7.59
|
14
|
+
# (7) 11.39
|
15
|
+
# (8) 17.09
|
16
|
+
# (9) 25.63
|
17
|
+
# (10) 38.44
|
18
|
+
# (11) 57.67
|
19
|
+
# (12) 86.50
|
20
|
+
# (13) 129.75
|
21
|
+
# (14) 194.62
|
22
|
+
# (15) 291.93
|
23
|
+
# (16) 437.89
|
24
|
+
# (17) 656.84
|
25
|
+
# (18) 985.26
|
26
|
+
# (19) 1,477.89
|
27
|
+
# (20) 2,216.84
|
28
|
+
# (21) 3,325.26
|
29
|
+
# (22) 4,987.89
|
30
|
+
# (23) 7,481.83
|
31
|
+
#
|
32
|
+
# Created by fvitale on 2/17/16 based on java implementation by patricioe.
|
33
|
+
#
|
34
|
+
|
35
|
+
class BinarySearchLatencyTracker < NoMethodError
|
36
|
+
|
37
|
+
BUCKETS = [ 1000, 1500, 2250, 3375, 5063,
|
38
|
+
7594, 11391, 17086, 25629, 38443,
|
39
|
+
57665, 86498, 129746, 194620, 291929,
|
40
|
+
437894, 656841, 985261, 1477892, 2216838,
|
41
|
+
3325257, 4987885, 7481828 ].freeze
|
42
|
+
|
43
|
+
MAX_LATENCY = 7481828
|
44
|
+
|
45
|
+
attr_accessor :latencies
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@latencies = Array.new(BUCKETS.length, 0)
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Increment the internal counter for the bucket this latency falls into.
|
53
|
+
# @param millis
|
54
|
+
#
|
55
|
+
def add_latency_millis(millis, return_index = false)
|
56
|
+
index = find_bucket_index(millis * 1000)
|
57
|
+
|
58
|
+
return index if return_index
|
59
|
+
|
60
|
+
@latencies[index] += 1
|
61
|
+
@latencies
|
62
|
+
end
|
63
|
+
|
64
|
+
# Increment the internal counter for the bucket this latency falls into.
|
65
|
+
# @param micros
|
66
|
+
def add_latency_micros(micros, return_index = false)
|
67
|
+
index = find_bucket_index(micros)
|
68
|
+
|
69
|
+
return index if return_index
|
70
|
+
|
71
|
+
@latencies[index] += 1
|
72
|
+
@latencies
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the list of latencies buckets as an array.
|
76
|
+
#
|
77
|
+
#
|
78
|
+
# @return the list of latencies buckets as an array.
|
79
|
+
def get_latencies
|
80
|
+
@latencies
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_latency(index)
|
84
|
+
return @latencies[index]
|
85
|
+
end
|
86
|
+
|
87
|
+
def clear
|
88
|
+
@latencies = Array.new(BUCKETS.length, 0)
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Returns the counts in the bucket this latency falls into.
|
93
|
+
# The latencies will not be updated.
|
94
|
+
# @param latency
|
95
|
+
# @return the bucket content for the latency.
|
96
|
+
#
|
97
|
+
def get_bucket_for_latency_millis(latency)
|
98
|
+
return @latencies[find_bucket_index(latency * 1000)]
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Returns the counts in the bucket this latency falls into.
|
103
|
+
# The latencies will not be updated.
|
104
|
+
# @param latency
|
105
|
+
# @return the bucket content for the latency.
|
106
|
+
#
|
107
|
+
def get_bucket_for_latency_micros(latency)
|
108
|
+
return @latencies[find_bucket_index(latency)]
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def find_bucket_index(micros)
|
114
|
+
if (micros > MAX_LATENCY) then
|
115
|
+
return BUCKETS.length - 1
|
116
|
+
end
|
117
|
+
|
118
|
+
if (micros < 1500) then
|
119
|
+
return 0
|
120
|
+
end
|
121
|
+
|
122
|
+
index = BUCKETS.find_index(BUCKETS.bsearch {|x| x >= micros })
|
123
|
+
|
124
|
+
return index
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|