splitclient-rb 0.1.3
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 +38 -0
- data/Gemfile +4 -0
- data/LICENSE +202 -0
- data/README.md +152 -0
- data/Rakefile +4 -0
- data/lib/splitclient-cache/local_store.rb +45 -0
- data/lib/splitclient-engine/evaluator/splitter.rb +110 -0
- data/lib/splitclient-engine/impressions/impressions.rb +79 -0
- data/lib/splitclient-engine/matchers/all_keys_matcher.rb +46 -0
- data/lib/splitclient-engine/matchers/combiners.rb +13 -0
- data/lib/splitclient-engine/matchers/combining_matcher.rb +94 -0
- data/lib/splitclient-engine/matchers/negation_matcher.rb +54 -0
- data/lib/splitclient-engine/matchers/user_defined_segment_matcher.rb +58 -0
- data/lib/splitclient-engine/matchers/whitelist_matcher.rb +55 -0
- data/lib/splitclient-engine/metrics/binary_search_latency_tracker.rb +122 -0
- data/lib/splitclient-engine/metrics/metrics.rb +158 -0
- data/lib/splitclient-engine/parser/condition.rb +90 -0
- data/lib/splitclient-engine/parser/partition.rb +37 -0
- data/lib/splitclient-engine/parser/segment.rb +84 -0
- data/lib/splitclient-engine/parser/segment_parser.rb +46 -0
- data/lib/splitclient-engine/parser/split.rb +68 -0
- data/lib/splitclient-engine/parser/split_adapter.rb +433 -0
- data/lib/splitclient-engine/parser/split_parser.rb +129 -0
- data/lib/splitclient-engine/partitions/treatments.rb +40 -0
- data/lib/splitclient-rb.rb +22 -0
- data/lib/splitclient-rb/split_client.rb +170 -0
- data/lib/splitclient-rb/split_config.rb +193 -0
- data/lib/splitclient-rb/version.rb +3 -0
- data/splitclient-rb.gemspec +44 -0
- data/tasks/benchmark_is_treatment.rake +37 -0
- data/tasks/concurrent_benchmark_is_treatment.rake +43 -0
- data/tasks/console.rake +4 -0
- data/tasks/rspec.rake +3 -0
- metadata +260 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
#
|
|
3
|
+
# helper class to parse fetched splits
|
|
4
|
+
#
|
|
5
|
+
class SplitParser < NoMethodError
|
|
6
|
+
#
|
|
7
|
+
# since value for splitChanges last fetch
|
|
8
|
+
attr_accessor :since
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# till value for splitChanges last fetch
|
|
12
|
+
attr_accessor :till
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# splits data
|
|
16
|
+
attr_accessor :splits
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# splits segments data
|
|
20
|
+
attr_accessor :segments
|
|
21
|
+
|
|
22
|
+
def initialize(logger)
|
|
23
|
+
@splits = []
|
|
24
|
+
@since = -1
|
|
25
|
+
@till = -1
|
|
26
|
+
@logger = logger
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# gets all the split names retrived from the endpoint
|
|
31
|
+
#
|
|
32
|
+
# @return [object] array of split names
|
|
33
|
+
def get_split_names
|
|
34
|
+
@splits.map { |s| s.name }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# @return [boolean] true if the splits content is empty false otherwise
|
|
39
|
+
def is_empty?
|
|
40
|
+
@splits.empty? ? true : false
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# gets all the segment names that are used within the retrieved splits
|
|
45
|
+
#
|
|
46
|
+
# @return [object] array of segment names
|
|
47
|
+
def get_used_segments
|
|
48
|
+
segment_names = []
|
|
49
|
+
|
|
50
|
+
@splits.each { |s|
|
|
51
|
+
s.conditions.each { |c|
|
|
52
|
+
c.matchers.each { |m|
|
|
53
|
+
m[:userDefinedSegmentMatcherData].each { |seg, name|
|
|
54
|
+
segment_names << name
|
|
55
|
+
} unless m[:userDefinedSegmentMatcherData].nil?
|
|
56
|
+
} unless c.matchers.nil?
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
segment_names.uniq
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# gets a split parsed object by name
|
|
64
|
+
#
|
|
65
|
+
# @param name [string] name of the split
|
|
66
|
+
#
|
|
67
|
+
# @return split [object] split object
|
|
68
|
+
def get_split(name)
|
|
69
|
+
@splits.find { |s| s.name == name }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# gets the treatment for the given combination of user key and split name
|
|
74
|
+
# using all parsed data for the splits
|
|
75
|
+
#
|
|
76
|
+
# @param id [string] user key
|
|
77
|
+
# @param name [string] split name
|
|
78
|
+
# @param default_treatment [string] default treatment value to be returned
|
|
79
|
+
#
|
|
80
|
+
# @return treatment [object] treatment for this user key, split pair
|
|
81
|
+
def get_split_treatment(id, name, default_treatment)
|
|
82
|
+
split = get_split(name)
|
|
83
|
+
|
|
84
|
+
if !split.is_empty? && split.status == 'ACTIVE' && !split.killed?
|
|
85
|
+
split.conditions.each do |c|
|
|
86
|
+
unless c.is_empty?
|
|
87
|
+
matcher = get_matcher_type(c)
|
|
88
|
+
if matcher.match?(id)
|
|
89
|
+
result = Splitter.get_treatment(id, split.seed, c.partitions) #'true match - running split'
|
|
90
|
+
if result.nil?
|
|
91
|
+
return default_treatment
|
|
92
|
+
else
|
|
93
|
+
return result
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
default_treatment
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#
|
|
104
|
+
# gets the matcher type from a condition object
|
|
105
|
+
#
|
|
106
|
+
# @param contidion [object] a condition object
|
|
107
|
+
#
|
|
108
|
+
# @return matcher [object] the matcher object for the given condition
|
|
109
|
+
def get_matcher_type(condition)
|
|
110
|
+
final_matcher = nil
|
|
111
|
+
|
|
112
|
+
case condition.matcher
|
|
113
|
+
when 'ALL_KEYS'
|
|
114
|
+
final_matcher = AllKeysMatcher.new
|
|
115
|
+
when 'IN_SEGMENT'
|
|
116
|
+
segment = @segments.get_segment(condition.matcher_segment)
|
|
117
|
+
final_matcher = segment.is_empty? ? UserDefinedSegmentMatcher.new(nil) : UserDefinedSegmentMatcher.new(segment)
|
|
118
|
+
when 'WHITELIST'
|
|
119
|
+
final_matcher = WhitelistMatcher.new(condition.matcher_whitelist)
|
|
120
|
+
else
|
|
121
|
+
@logger.error('Invalid matcher type')
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
final_matcher
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module SplitIoClient
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# represents the possible return values for a treatment
|
|
5
|
+
#
|
|
6
|
+
class Treatments < NoMethodError
|
|
7
|
+
|
|
8
|
+
# Constants to represent treatment values
|
|
9
|
+
CONTROL = 'control'
|
|
10
|
+
OFF = 'off'
|
|
11
|
+
ON = 'on'
|
|
12
|
+
|
|
13
|
+
# get the actual value for the given treatment type
|
|
14
|
+
#
|
|
15
|
+
# @param type [string] treatment type
|
|
16
|
+
#
|
|
17
|
+
# @return [Treatment] treatment type value
|
|
18
|
+
def self.get_type(type)
|
|
19
|
+
case type
|
|
20
|
+
when 'on'
|
|
21
|
+
return ON
|
|
22
|
+
when 'off', 'control'
|
|
23
|
+
return CONTROL
|
|
24
|
+
else # default return off
|
|
25
|
+
return CONTROL
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# checks if the give treatment matches control type
|
|
30
|
+
#
|
|
31
|
+
# @param type [string] treatment type
|
|
32
|
+
#
|
|
33
|
+
# @return [boolean] true if matches, false otherwise
|
|
34
|
+
def self.is_control?(treatment)
|
|
35
|
+
get_type(treatment).equal?(CONTROL) ? true : false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'splitclient-rb/version'
|
|
2
|
+
require 'splitclient-rb/split_client'
|
|
3
|
+
require 'splitclient-rb/split_config'
|
|
4
|
+
require 'splitclient-cache/local_store'
|
|
5
|
+
require 'splitclient-engine/parser/split'
|
|
6
|
+
require 'splitclient-engine/parser/condition'
|
|
7
|
+
require 'splitclient-engine/parser/partition'
|
|
8
|
+
require 'splitclient-engine/parser/segment'
|
|
9
|
+
require 'splitclient-engine/parser/split_adapter'
|
|
10
|
+
require 'splitclient-engine/parser/split_parser'
|
|
11
|
+
require 'splitclient-engine/parser/segment_parser'
|
|
12
|
+
require 'splitclient-engine/partitions/treatments'
|
|
13
|
+
require 'splitclient-engine/matchers/combiners'
|
|
14
|
+
require 'splitclient-engine/matchers/combining_matcher'
|
|
15
|
+
require 'splitclient-engine/matchers/all_keys_matcher'
|
|
16
|
+
require 'splitclient-engine/matchers/negation_matcher'
|
|
17
|
+
require 'splitclient-engine/matchers/user_defined_segment_matcher'
|
|
18
|
+
require 'splitclient-engine/matchers/whitelist_matcher'
|
|
19
|
+
require 'splitclient-engine/evaluator/splitter'
|
|
20
|
+
require 'splitclient-engine/impressions/impressions'
|
|
21
|
+
require 'splitclient-engine/metrics/metrics'
|
|
22
|
+
require 'splitclient-engine/metrics/binary_search_latency_tracker'
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# main class for split client sdk
|
|
7
|
+
#
|
|
8
|
+
class SplitClient < NoMethodError
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# constant that defines the localhost mode
|
|
12
|
+
LOCALHOST_MODE = 'localhost'
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# object that acts as an api adapter connector. used to get and post to api endpoints
|
|
16
|
+
attr_reader :adapter
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# variables to if the sdk is being used in localhost mode and store the list of features
|
|
20
|
+
attr_reader :localhost_mode
|
|
21
|
+
attr_reader :localhost_mode_features
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# Creates a new split client instance that connects to split.io API.
|
|
25
|
+
#
|
|
26
|
+
# @param api_key [String] the API key for your split account
|
|
27
|
+
#
|
|
28
|
+
# @return [SplitIoClient] split.io client instance
|
|
29
|
+
def initialize(api_key, config = {})
|
|
30
|
+
@localhost_mode = false
|
|
31
|
+
@localhost_mode_features = []
|
|
32
|
+
|
|
33
|
+
@config = SplitConfig.new(config)
|
|
34
|
+
|
|
35
|
+
if api_key == LOCALHOST_MODE
|
|
36
|
+
@localhost_mode = true
|
|
37
|
+
load_localhost_mode_features
|
|
38
|
+
else
|
|
39
|
+
@adapter = SplitAdapter.new(api_key, @config)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# validates the treatment for the provided user key and feature
|
|
45
|
+
#
|
|
46
|
+
# @param id [string] user id
|
|
47
|
+
# @param feature [string] name of the feature that is being validated
|
|
48
|
+
# @param treatment [string] value of the treatment for this user key and feature
|
|
49
|
+
#
|
|
50
|
+
# @return [boolean] true if the user key has valida treatment, false otherwise
|
|
51
|
+
def is_treatment?(id, feature, treatment)
|
|
52
|
+
is_treatment = false
|
|
53
|
+
|
|
54
|
+
if is_localhost_mode?
|
|
55
|
+
is_treatment = get_localhost_treatment(feature)
|
|
56
|
+
else
|
|
57
|
+
begin
|
|
58
|
+
is_treatment = (get_treatment(id, feature) == treatment)
|
|
59
|
+
rescue
|
|
60
|
+
@config.logger.error("MUST NOT throw this error")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
is_treatment
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#
|
|
67
|
+
# obtains the treatment for a given feature
|
|
68
|
+
#
|
|
69
|
+
# @param id [string] user id
|
|
70
|
+
# @param feature [string] name of the feature that is being validated
|
|
71
|
+
#
|
|
72
|
+
# @return [Treatment] treatment constant value
|
|
73
|
+
def get_treatment(id, feature)
|
|
74
|
+
unless id
|
|
75
|
+
@config.logger.warn('id was null for feature: ' + feature)
|
|
76
|
+
return Treatments::CONTROL
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
unless feature
|
|
80
|
+
@config.logger.warn('feature was null for id: ' + id)
|
|
81
|
+
return Treatments::CONTROL
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
start = Time.now
|
|
85
|
+
result = nil
|
|
86
|
+
|
|
87
|
+
begin
|
|
88
|
+
result = get_treatment_without_exception_handling(id, feature)
|
|
89
|
+
rescue StandardError => error
|
|
90
|
+
@config.log_found_exception(__method__.to_s, error)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
result = result.nil? ? Treatments::CONTROL : result
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
@adapter.impressions.log(id, feature, result, (Time.now.to_f * 1000.0))
|
|
97
|
+
latency = (Time.now - start) * 1000.0
|
|
98
|
+
if (@adapter.impressions.queue.length >= @adapter.impressions.max_number_of_keys)
|
|
99
|
+
@adapter.impressions_producer.wakeup
|
|
100
|
+
end
|
|
101
|
+
rescue StandardError => error
|
|
102
|
+
@config.log_found_exception(__method__.to_s, error)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
result
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# auxiliary method to get the treatments avoding exceptions
|
|
110
|
+
#
|
|
111
|
+
# @param id [string] user id
|
|
112
|
+
# @param feature [string] name of the feature that is being validated
|
|
113
|
+
#
|
|
114
|
+
# @return [Treatment] tretment constant value
|
|
115
|
+
def get_treatment_without_exception_handling(id, feature)
|
|
116
|
+
@adapter.parsed_splits.segments = @adapter.parsed_segments
|
|
117
|
+
split = @adapter.parsed_splits.get_split(feature)
|
|
118
|
+
|
|
119
|
+
if split.nil?
|
|
120
|
+
return Treatments::CONTROL
|
|
121
|
+
else
|
|
122
|
+
default_treatment = split.data[:defaultTreatment]
|
|
123
|
+
return @adapter.parsed_splits.get_split_treatment(id, feature, default_treatment)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# method that returns the sdk gem version
|
|
129
|
+
#
|
|
130
|
+
# @return [string] version value for this sdk
|
|
131
|
+
def self.sdk_version
|
|
132
|
+
'RubyClientSDK-'+SplitIoClient::VERSION
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
#
|
|
136
|
+
# method to check if the sdk is running in localhost mode based on api key
|
|
137
|
+
#
|
|
138
|
+
# @return [boolean] True if is in localhost mode, false otherwise
|
|
139
|
+
def is_localhost_mode?
|
|
140
|
+
@localhost_mode
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# method to set localhost mode features by reading .splits file located at home directory
|
|
145
|
+
#
|
|
146
|
+
# @returns [void]
|
|
147
|
+
def load_localhost_mode_features
|
|
148
|
+
splits_file = File.join(Dir.home, ".splits")
|
|
149
|
+
if File.exists?(splits_file)
|
|
150
|
+
line_num=0
|
|
151
|
+
File.open(splits_file).each do |line|
|
|
152
|
+
@localhost_mode_features << line.strip unless line.start_with?('#') || line.strip.empty?
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
#
|
|
158
|
+
# method to check the treatment for the given feature in localhost mode
|
|
159
|
+
#
|
|
160
|
+
# @return [boolean] true if the feature is available in localhost mode, false otherwise
|
|
161
|
+
def get_localhost_treatment(feature)
|
|
162
|
+
@localhost_mode_features.include?(feature)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private :get_treatment_without_exception_handling, :is_localhost_mode?,
|
|
166
|
+
:load_localhost_mode_features, :get_localhost_treatment
|
|
167
|
+
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
require 'socket'
|
|
3
|
+
|
|
4
|
+
module SplitIoClient
|
|
5
|
+
#
|
|
6
|
+
# This class manages configuration options for the split client library.
|
|
7
|
+
# If not custom configuration is required the default configuration values will be used
|
|
8
|
+
#
|
|
9
|
+
class SplitConfig
|
|
10
|
+
#
|
|
11
|
+
# Constructor for creating custom split client config
|
|
12
|
+
#
|
|
13
|
+
# @param opts [Hash] optional hash with configuration options
|
|
14
|
+
# @option opts [String] :base_uri ("https://sdk.split.io/api/") The base URL for split API end points
|
|
15
|
+
# @option opts [Int] :read_timeout (10) The read timeout for network connections in seconds.
|
|
16
|
+
# @option opts [Int] :connection_timeout (2) The connect timeout for network connections in seconds.
|
|
17
|
+
# @option opts [Object] :local_store A cache store for the Faraday HTTP caching library. Defaults to the Rails cache in a Rails environment, or a thread-safe in-memory store otherwise.
|
|
18
|
+
# @option opts [Int] :features_refresh_rate The SDK polls Split servers for changes to feature roll-out plans. This parameter controls this polling period in seconds.
|
|
19
|
+
# @option opts [Int] :segments_refresh_rate
|
|
20
|
+
# @option opts [Int] :metrics_refresh_rate
|
|
21
|
+
# @option opts [Int] :impressions_refresh_rate
|
|
22
|
+
# @option opts [Object] :logger a logger to user for messages from the client. Defaults to stdout
|
|
23
|
+
# @option opts [Boolean] :debug_enabled (false) The value for the debug flag
|
|
24
|
+
#
|
|
25
|
+
# @return [type] SplitConfig with configuration options
|
|
26
|
+
def initialize(opts = {})
|
|
27
|
+
@base_uri = (opts[:base_uri] || SplitConfig.default_base_uri).chomp('/')
|
|
28
|
+
@local_store = opts[:local_store] || SplitConfig.default_local_store
|
|
29
|
+
@connection_timeout = opts[:connection_timeout] || SplitConfig.default_connection_timeout
|
|
30
|
+
@read_timeout = opts[:read_timeout] || SplitConfig.default_read_timeout
|
|
31
|
+
@features_refresh_rate = opts[:features_refresh_rate] || SplitConfig.default_features_refresh_rate
|
|
32
|
+
@segments_refresh_rate = opts[:segments_refresh_rate] || SplitConfig.default_segments_refresh_rate
|
|
33
|
+
@metrics_refresh_rate = opts[:metrics_refresh_rate] || SplitConfig.default_metrics_refresh_rate
|
|
34
|
+
@impressions_refresh_rate = opts[:impressions_refresh_rate] || SplitConfig.default_impressions_refresh_rate
|
|
35
|
+
@logger = opts[:logger] || SplitConfig.default_logger
|
|
36
|
+
@debug_enabled = opts[:debug_enabled] || SplitConfig.default_debug
|
|
37
|
+
@machine_name = SplitConfig.get_hostname
|
|
38
|
+
@machine_ip = SplitConfig.get_ip
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# The base URL for split API end points
|
|
43
|
+
#
|
|
44
|
+
# @return [String] The configured base URL for the split API end points
|
|
45
|
+
attr_reader :base_uri
|
|
46
|
+
|
|
47
|
+
#
|
|
48
|
+
# The store for the Faraday HTTP caching library. Stores should respond to
|
|
49
|
+
# 'read', 'write' and 'delete' requests.
|
|
50
|
+
#
|
|
51
|
+
# @return [Object] The configured store for the Faraday HTTP caching library.
|
|
52
|
+
attr_reader :local_store
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# The read timeout for network connections in seconds.
|
|
56
|
+
#
|
|
57
|
+
# @return [Int] The timeout in seconds.
|
|
58
|
+
attr_reader :read_timeout
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# The connection timeout for network connections in seconds.
|
|
62
|
+
#
|
|
63
|
+
# @return [Int] The connect timeout in seconds.
|
|
64
|
+
attr_reader :connection_timeout
|
|
65
|
+
|
|
66
|
+
#
|
|
67
|
+
# The configured logger. The client library uses the log to
|
|
68
|
+
# print warning and error messages.
|
|
69
|
+
#
|
|
70
|
+
# @return [Logger] The configured logger
|
|
71
|
+
attr_reader :logger
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# The boolean that represents the state of the debug log level
|
|
75
|
+
#
|
|
76
|
+
# @return [Boolean] The value for the debug flag
|
|
77
|
+
attr_reader :debug_enabled
|
|
78
|
+
|
|
79
|
+
attr_reader :machine_ip
|
|
80
|
+
attr_reader :machine_name
|
|
81
|
+
|
|
82
|
+
attr_reader :features_refresh_rate
|
|
83
|
+
attr_reader :segments_refresh_rate
|
|
84
|
+
attr_reader :metrics_refresh_rate
|
|
85
|
+
attr_reader :impressions_refresh_rate
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# The default split client configuration
|
|
89
|
+
#
|
|
90
|
+
# @return [Config] The default split client configuration.
|
|
91
|
+
def self.default
|
|
92
|
+
SplitConfig.new
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#
|
|
96
|
+
# The default base uri for api calls
|
|
97
|
+
#
|
|
98
|
+
# @return [string] The default base uri
|
|
99
|
+
def self.default_base_uri
|
|
100
|
+
'https://sdk.split.io/api/'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @return [LocalStore] configuration value for local cache store
|
|
104
|
+
def self.default_local_store
|
|
105
|
+
defined?(Rails) && Rails.respond_to?(:cache) ? Rails.cache : LocalStore.new
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# The default read timeout value
|
|
110
|
+
#
|
|
111
|
+
# @return [int]
|
|
112
|
+
def self.default_read_timeout
|
|
113
|
+
5
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
#
|
|
117
|
+
# The default connection timeout value
|
|
118
|
+
#
|
|
119
|
+
# @return [int]
|
|
120
|
+
def self.default_connection_timeout
|
|
121
|
+
5
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def self.default_features_refresh_rate
|
|
125
|
+
30
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.default_segments_refresh_rate
|
|
129
|
+
60
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.default_metrics_refresh_rate
|
|
133
|
+
60
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def self.default_impressions_refresh_rate
|
|
137
|
+
60
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
#
|
|
141
|
+
# The default logger object
|
|
142
|
+
#
|
|
143
|
+
# @return [object]
|
|
144
|
+
def self.default_logger
|
|
145
|
+
Logger.new($stdout)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
#
|
|
149
|
+
# The default debug value
|
|
150
|
+
#
|
|
151
|
+
# @return [boolean]
|
|
152
|
+
def self.default_debug
|
|
153
|
+
false
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
#
|
|
157
|
+
# custom logger of exceptions
|
|
158
|
+
#
|
|
159
|
+
# @return [void]
|
|
160
|
+
def log_found_exception(caller, exn)
|
|
161
|
+
error_traceback = "#{exn.inspect} #{exn}\n\t#{exn.backtrace.join("\n\t")}"
|
|
162
|
+
error = "[splitclient-rb] Unexpected exception in #{caller}: #{error_traceback}"
|
|
163
|
+
@logger.error(error)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
#
|
|
167
|
+
# gets the hostname where the sdk gem is running
|
|
168
|
+
#
|
|
169
|
+
# @return [string]
|
|
170
|
+
def self.get_hostname
|
|
171
|
+
begin
|
|
172
|
+
Socket.gethostname
|
|
173
|
+
rescue
|
|
174
|
+
#unable to get hostname
|
|
175
|
+
'localhost'
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
#
|
|
180
|
+
# gets the ip where the sdk gem is running
|
|
181
|
+
#
|
|
182
|
+
# @return [string]
|
|
183
|
+
def self.get_ip
|
|
184
|
+
begin
|
|
185
|
+
Socket::getaddrinfo(Socket.gethostname, 'echo', Socket::AF_INET)[0][3]
|
|
186
|
+
rescue
|
|
187
|
+
#unable to get local ip
|
|
188
|
+
'127.0.0.0'
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
end
|