splitclient-rb 5.0.3.pre.rc1-java → 5.1.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -0
- data/CHANGES.txt +8 -1
- data/Detailed-README.md +246 -313
- data/Gemfile +2 -0
- data/NEWS +12 -2
- data/Rakefile +6 -2
- data/exe/splitio +20 -20
- data/lib/splitclient-rb.rb +1 -0
- data/lib/splitclient-rb/engine/api/client.rb +1 -2
- data/lib/splitclient-rb/engine/api/segments.rb +33 -27
- data/lib/splitclient-rb/engine/api/splits.rb +22 -17
- data/lib/splitclient-rb/split_config.rb +1 -1
- data/lib/splitclient-rb/split_logger.rb +29 -0
- data/lib/splitclient-rb/version.rb +1 -1
- data/splitclient-rb.gemspec +38 -34
- data/tasks/benchmark_get_treatment.rake +31 -17
- data/tasks/irb.rake +5 -3
- data/tasks/rspec.rake +3 -1
- metadata +69 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 237ced7a078d2f81c4fdec42ef6ac9bb3be2ab47
|
4
|
+
data.tar.gz: 4c2ba4675ee194ba0cb1ced8725ecf1ee6dbbaf2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5318af0f98865412ca9640dad68793ad250a7c3dd79cfeae763a89a6d8bac6e0deb8f3e1c2a7a1ca11b4297a8bc6482a1e97d7c953799530050411583b055319
|
7
|
+
data.tar.gz: 06d3f0ffce460d6e0460f6a3bc244e027cf8c30ccccd6f2ab2c495328592f75ccb1e34829b5c0d00830337d3b0ff6498a25975fdc172971ae691a47b323bf0f4
|
data/.rubocop.yml
ADDED
data/CHANGES.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
5.1.0 (September 10th, 2018)
|
2
|
+
- Change `get_api` to return only a Faraday response.
|
3
|
+
- Add `SplitLogger` to clean up logging code and reduce the complexity in several methods.
|
4
|
+
|
5
|
+
5.0.3 (August 13th, 2018)
|
6
|
+
- Add `impressions_bulk_size` option to set the max number of impressions to be sent to the Split backend on each post.
|
7
|
+
|
1
8
|
5.0.2 (July 31st, 2018)
|
2
9
|
- Prevents the impression thread from being started if a listener is not in place
|
3
10
|
|
@@ -5,7 +12,7 @@
|
|
5
12
|
- Adds stop! method to the factory for gracefully stopping the SDK.
|
6
13
|
|
7
14
|
5.0.0 (May 18th, 2018)
|
8
|
-
- Fix bug where the sdk picked the wrong hashing algo. This is a breaking change.
|
15
|
+
- Fix bug where the sdk picked the wrong hashing algo. This is a breaking change.
|
9
16
|
|
10
17
|
4.5.2 (May 16th, 2018)
|
11
18
|
- do not return control when a split has custom attr and I don't pass attributes to get_treatment
|
data/Detailed-README.md
CHANGED
@@ -1,216 +1,324 @@
|
|
1
1
|
# Split Ruby SDK
|
2
2
|
|
3
|
-
Ruby
|
3
|
+
Ruby [Split](https://www.split.io/) SDK client.
|
4
4
|
|
5
5
|
## Installation
|
6
|
-
---
|
7
|
-
|
8
|
-
- Once the gem is published you can install it with the following steps:
|
9
6
|
|
10
|
-
|
7
|
+
Install by running:
|
11
8
|
|
12
|
-
|
13
|
-
gem 'splitclient-rb'
|
14
|
-
```
|
9
|
+
$ gem install splitclient-rb
|
15
10
|
|
16
|
-
|
11
|
+
If using [Bundler](https://bundler.io/), add this line to your `Gemfile`:
|
17
12
|
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
```ruby
|
14
|
+
gem 'splitclient-rb'
|
15
|
+
```
|
21
16
|
|
22
|
-
|
17
|
+
And then run:
|
23
18
|
|
24
|
-
|
19
|
+
$ bundle install
|
25
20
|
|
26
|
-
|
27
|
-
```ruby
|
28
|
-
gem 'splitclient-rb', git: 'https://github.com/splitio/ruby-client.git',
|
29
|
-
```
|
30
|
-
You can also use any specific branch if necessary:
|
31
|
-
```ruby
|
32
|
-
gem 'splitclient-rb', git: 'https://github.com/splitio/ruby-client.git', branch: 'development'
|
33
|
-
```
|
34
|
-
And then execute:
|
21
|
+
Or use any specific branch by adding the following to your `Gemfile` instead:
|
35
22
|
|
36
|
-
|
23
|
+
```ruby
|
24
|
+
gem 'splitclient-rb', git: 'https://github.com/splitio/ruby-client.git', branch: 'branch_name'
|
25
|
+
```
|
37
26
|
|
38
27
|
## Usage
|
39
28
|
|
40
29
|
### Quick Setup
|
41
30
|
---
|
42
31
|
|
43
|
-
Within your application
|
44
|
-
|
45
|
-
Require the Split client:
|
32
|
+
Within your application, include the Split client using Ruby's `require`:
|
46
33
|
```ruby
|
47
34
|
require 'splitclient-rb'
|
48
35
|
```
|
49
36
|
|
50
|
-
|
37
|
+
Then, create a new split client instance with your API key, which can be found in your Organization Settings page, in the APIs tab.
|
38
|
+
|
51
39
|
```ruby
|
52
|
-
factory = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY')
|
40
|
+
factory = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY')
|
53
41
|
split_client = factory.client
|
54
42
|
```
|
55
43
|
|
56
|
-
|
44
|
+
### Ruby on Rails
|
45
|
+
---
|
46
|
+
|
47
|
+
Create an initializer (typically `config/initializers/split_client.rb`) with the following code:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
Rails.configuration.split_client = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY').client
|
51
|
+
```
|
52
|
+
And use the snippet below to access the client in your controllers:
|
53
|
+
|
57
54
|
```ruby
|
58
|
-
|
55
|
+
Rails.application.config.split_client
|
59
56
|
```
|
60
57
|
|
61
|
-
|
58
|
+
### Using the SDK
|
59
|
+
---
|
62
60
|
|
63
|
-
|
61
|
+
In its simplest form, using the SDK is reduced to calling the `get_treatment` method of the SDK client to decide what version of your features your customers should be served for a specific feature and user. You can then use an if-else-if block for the different treatments that you defined in the Split UI:
|
64
62
|
|
63
|
+
```ruby
|
64
|
+
treatment = split_client.get_treatment('user_id', 'feature_name');
|
65
|
+
|
66
|
+
if treatment == 'on'
|
67
|
+
# insert code here to show on treatment
|
68
|
+
elsif treatment == 'off'
|
69
|
+
# insert code here to show off treatment
|
70
|
+
else
|
71
|
+
# handle the client returning the control treatment
|
72
|
+
end
|
65
73
|
```
|
66
|
-
# this is a comment
|
67
74
|
|
68
|
-
|
69
|
-
|
70
|
-
reporting_v2 on
|
71
|
-
double_writes_to_cassandra off
|
72
|
-
new-navigation v3
|
75
|
+
For features that use targeting rules based on user attributes, you can call the `get_treatment` method the following way:
|
73
76
|
|
77
|
+
```ruby
|
78
|
+
split_client.get_treatment('user_id','feature_name', attr: 'val')
|
74
79
|
```
|
75
80
|
|
76
|
-
|
81
|
+
e.g.
|
82
|
+
```ruby
|
83
|
+
if split_client.get_treatment('employee_user_01','view_main_list', age: 35)
|
84
|
+
my_app.display_main_list
|
85
|
+
end
|
86
|
+
```
|
77
87
|
|
88
|
+
Also, you can you can provide two different keys - one for matching and the other for bucketing:
|
78
89
|
```ruby
|
79
|
-
|
80
|
-
|
90
|
+
split_client.get_treatment(
|
91
|
+
{ matching_key: 'subscriber_id', bucketing_key: 'user_id' },
|
92
|
+
'feature_name',
|
93
|
+
attr: 'val'
|
94
|
+
)
|
81
95
|
```
|
96
|
+
An scenario that requires the usage of both keys is a visitor user that browses the site and at some point gets logged into the system: as an anonymous visitor, the user browses the home page and is given the `new_homepage` treatment based on her visitor id. If the visitor signs up and turns into a subscriber, then upon being given her `subscriber_id`, Split may decide to give her the old_homepage treatment. This is of course, the opposite of the desired outcome, as the visitor's entire homepage experience would change as soon as she signs up.
|
82
97
|
|
83
|
-
|
84
|
-
file name (full path) to look for the file (note: you must provide absolute path):
|
98
|
+
Split solves this situation by introducing the concept of a matching_key and a bucketing key. By providing the `subscriber_id` as the `matching_key` and the `visitor_id` as the `bucketing_key`, Split will give the same treatment back to the user that it used to give to the visitor.
|
85
99
|
|
86
|
-
|
100
|
+
**Note**: read more about this topic [here](https://docs.split.io/docs/anonymous-to-logged-in).
|
87
101
|
|
102
|
+
The `bucketing_key` may be `nil`. In that case the `matching_key` would be used instead, so calling:
|
88
103
|
```ruby
|
89
|
-
|
104
|
+
split_client.get_treatment(
|
105
|
+
{ matching_key: 'subscriber_id' },
|
106
|
+
'feature_name',
|
107
|
+
attr: 'val'
|
108
|
+
)
|
90
109
|
```
|
110
|
+
It's exactly the same as calling:
|
111
|
+
```ruby
|
112
|
+
split_client.get_treatment('subscriber_id' ,'feature_name', attr: 'val')
|
113
|
+
```
|
114
|
+
**Important:** `matching_key` cannot be nil.
|
91
115
|
|
92
|
-
|
93
|
-
---
|
116
|
+
#### Split Manager
|
94
117
|
|
95
|
-
|
118
|
+
For some advanced use cases you can use the Split Manager. To get a `manager` instance, do:
|
96
119
|
|
97
120
|
```ruby
|
98
|
-
|
121
|
+
split_manager = SplitIoClient::SplitFactoryBuilder.build('your_api_key', options).manager
|
99
122
|
```
|
100
|
-
|
123
|
+
_Or simply call `#manager` in your factory instance if you built it previously._
|
124
|
+
|
125
|
+
As an example, using the manager you could get a list of your splits by doing:
|
101
126
|
|
102
127
|
```ruby
|
103
|
-
|
128
|
+
split_manager.splits
|
104
129
|
```
|
105
130
|
|
106
|
-
|
107
|
-
---
|
131
|
+
Which would produce an output similar to:
|
108
132
|
|
109
|
-
|
133
|
+
```ruby
|
134
|
+
[
|
135
|
+
{
|
136
|
+
name: 'some_feature',
|
137
|
+
traffic_type_name: nil,
|
138
|
+
killed: false,
|
139
|
+
treatments: nil,
|
140
|
+
change_number: 1469134003507
|
141
|
+
},
|
142
|
+
{
|
143
|
+
name: 'another_feature',
|
144
|
+
traffic_type_name: nil,
|
145
|
+
killed: false,
|
146
|
+
treatments: nil,
|
147
|
+
change_number: 1469134003414
|
148
|
+
},
|
149
|
+
{
|
150
|
+
name: 'even_more_features',
|
151
|
+
traffic_type_name: nil,
|
152
|
+
killed: false,
|
153
|
+
treatments: nil,
|
154
|
+
change_number: 1469133991063
|
155
|
+
},
|
156
|
+
{
|
157
|
+
name: 'yet_another_feature',
|
158
|
+
traffic_type_name: nil,
|
159
|
+
killed: false,
|
160
|
+
treatments: nil,
|
161
|
+
change_number: 1469133757521
|
162
|
+
}
|
163
|
+
]
|
164
|
+
```
|
165
|
+
|
166
|
+
#### Localhost Mode
|
167
|
+
|
168
|
+
You can run the SDK in _localhost_ mode. In this mode, the SDK won't actually communicate with the Split API, but it'll rather return treatments based on a `.split` file on your local environment. This file must be a list of `split_name treatment_name_to_be_returned` entries. e.g.:
|
169
|
+
|
170
|
+
```
|
171
|
+
reporting_v2 on
|
172
|
+
double_writes_to_cassandra off
|
173
|
+
new-navigation v3
|
174
|
+
```
|
175
|
+
|
176
|
+
Using the file above, when calling:
|
177
|
+
```ruby
|
178
|
+
split_client.get_treatment('foo', 'reporting_v2')
|
179
|
+
```
|
180
|
+
|
181
|
+
The split client will return `on`. Note that this will be true for any bucketing or matching key.
|
182
|
+
|
183
|
+
To configure the SDK to work in localhost mode, use `localhost` as the API key:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
factory = SplitIoClient::SplitFactoryBuilder.build('localhost', path: '/where/to-look-for/<file_name>')
|
187
|
+
split_client = factory.client
|
188
|
+
```
|
189
|
+
|
190
|
+
By default, the SDK will look in your home directory (i.e. `~`) for the `.split` file. You can change this location by specifying an absolute path instead.
|
191
|
+
|
192
|
+
When in localhost mode, you can make use of the SDK ability to automatically refresh the splits from the `.split` file. To do that, just specify a reload rate in seconds when building the split factory instance, like this:
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
factory = SplitIoClient::SplitFactoryBuilder.build('localhost', path: '/where/to-look-for/<file_name>', reload_rate: 3)
|
196
|
+
```
|
197
|
+
|
198
|
+
## Advanced Configuration
|
199
|
+
|
200
|
+
Split client's default configuration should cover most scenarios. However, you can also provide custom configuration settings when initializing the factory using a hash of options. e.g.:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
options = {
|
204
|
+
impressions_refresh_rate: 10,
|
205
|
+
debug_enabled: true,
|
206
|
+
transport_debug_enabled: false
|
207
|
+
}
|
208
|
+
|
209
|
+
factory = SplitIoClient::SplitFactoryBuilder.build('your_api_key'], options)
|
210
|
+
```
|
110
211
|
|
111
212
|
The following values can be customized:
|
112
213
|
|
113
|
-
**base_uri** : URI for the api endpoints
|
214
|
+
**base_uri** : URI for the api endpoints.
|
114
215
|
|
115
|
-
*
|
216
|
+
*default value* = `https://sdk.split.io/api/`
|
116
217
|
|
117
|
-
**connection_timeout** :
|
218
|
+
**connection_timeout** : Http client connection timeout (in seconds).
|
118
219
|
|
119
220
|
*default value* = `5`
|
120
221
|
|
121
|
-
**read_timeout** :
|
222
|
+
**read_timeout** : Http socket read timeout (in seconds).
|
122
223
|
|
123
224
|
*default value* = `5`
|
124
225
|
|
125
|
-
**features_refresh_rate** : The SDK polls Split servers for changes to feature
|
126
|
-
|
226
|
+
**features_refresh_rate** : The SDK polls Split servers for changes to feature Splits every X seconds, where X is this property's value.
|
227
|
+
|
127
228
|
*default value* = `30`
|
128
229
|
|
129
|
-
**segments_refresh_rate** : The SDK polls Split servers for changes to
|
230
|
+
**segments_refresh_rate** : The SDK polls Split servers for changes to segments every X seconds, where X is this property's value.
|
130
231
|
|
131
232
|
*default value* = `60`
|
132
233
|
|
133
|
-
**metrics_refresh_rate** : The SDK sends diagnostic metrics to Split servers
|
234
|
+
**metrics_refresh_rate** : The SDK sends and flushes diagnostic metrics to Split servers every X seconds where X is this property's value.
|
134
235
|
|
135
236
|
*default value* = `60`
|
136
237
|
|
137
|
-
**impressions_refresh_rate** : The
|
238
|
+
**impressions_refresh_rate** : The treatment log captures which customer saw what treatment ("on", "off", etc) at what time. This parameter controls how often this log is flushed back to Split servers to power analytics (in seconds).
|
239
|
+
|
240
|
+
*default value* = `60`
|
138
241
|
|
139
242
|
**impressions_queue_size** : The size of the impressions queue in case of `cache_adapter == :memory`.
|
140
243
|
|
141
|
-
|
244
|
+
*default value* = 5000
|
142
245
|
|
143
|
-
|
246
|
+
**impressions_bulk_size** : Maximum number of impressions to be sent to Split servers on each post.
|
247
|
+
|
248
|
+
*default value* = defaults to `impressions_queue_size`
|
144
249
|
|
145
|
-
**debug_enabled** : Enables extra logging
|
250
|
+
**debug_enabled** : Enables extra logging (verbose mode).
|
146
251
|
|
147
252
|
*default value* = `false`
|
148
253
|
|
149
|
-
**transport_debug_enabled** :
|
254
|
+
**transport_debug_enabled** : Super verbose mode that prints network payloads among others.
|
150
255
|
|
151
256
|
*default value* = `false`
|
152
257
|
|
153
|
-
**logger** :
|
258
|
+
**logger** : Default logger for messages and errors.
|
154
259
|
|
155
260
|
*default value* = `Logger.new($stdout)`
|
156
261
|
|
157
|
-
**
|
262
|
+
**impression_listener** : Route impressions' information to a location of your choice (in addition to the SDK servers). _See [Impression Listener](#impression-listener) section for specifics._
|
263
|
+
|
264
|
+
*default value* = (no impression listener)
|
265
|
+
|
266
|
+
**block_until_ready** : The SDK will block your app for the provided amount of seconds until it's ready. A `SplitIoClient::SDKBlockerTimeoutExpiredException` will be thrown If the provided time expires. When `0` is provided, the SDK runs in non-blocking mode.
|
158
267
|
|
159
268
|
*default value* = `0`
|
160
269
|
|
161
|
-
**labels_enabled** :
|
270
|
+
**labels_enabled** : Allows preventing labels from being sent to the Split servers, as they may contain sensitive information.
|
162
271
|
|
163
272
|
*default value* = `true`
|
164
273
|
|
165
|
-
**mode** : See [SDK
|
274
|
+
**mode** : See [SDK Modes](#sdk-modes).
|
166
275
|
|
167
276
|
*default value* = `:standalone`
|
168
277
|
|
169
|
-
|
278
|
+
**cache_adapter** : Where to store data (splits, segments, and impressions) in between calls to the the Split servers. Supported options are `:memory` (default) and `:redis`.
|
170
279
|
|
171
|
-
|
280
|
+
_To use Redis, include `redis-rb` in your app's Gemfile._
|
172
281
|
|
173
|
-
|
282
|
+
*default value* = `:memory`
|
174
283
|
|
175
|
-
**
|
284
|
+
**redis_namespace** : Prefix to add to elements in Redis cache when having to share redis with other applications.
|
176
285
|
|
177
|
-
*default value* = `
|
286
|
+
*default value* = `SPLITIO`
|
178
287
|
|
179
|
-
**language** : SDK
|
288
|
+
**language** : SDK language (used in the Redis namespace for metrics and impressions, also included in requests' headers).
|
180
289
|
|
181
290
|
*default value* = `'ruby'`
|
182
291
|
|
183
|
-
**version** : SDK
|
292
|
+
**version** : SDK version (used in the Redis namespace for metrics and impressions, also included in requests' headers).
|
184
293
|
|
185
|
-
*default value* =
|
294
|
+
*default value* = (current version of the SDK)
|
186
295
|
|
187
|
-
**machine_ip** : SDK
|
296
|
+
**machine_ip** : SDK machine ip (used in the Redis namespace for metrics and impressions, also included in requests' headers).
|
188
297
|
|
189
|
-
*default value* =
|
298
|
+
*default value* = (your current host's ip)
|
190
299
|
|
191
|
-
**machine_name** : SDK
|
300
|
+
**machine_name** : SDK machine name (used in the Redis namespace for metrics and impressions, also included in requests' headers).
|
192
301
|
|
193
|
-
*default value* =
|
302
|
+
*default value* = (your current hostname)
|
194
303
|
|
195
|
-
**redis_url** : Redis URL or hash with configuration for SDK to connect to.
|
304
|
+
**redis_url** : Redis URL or hash with configuration for the SDK to connect to. See [Redis#initialize](https://www.rubydoc.info/github/redis/redis-rb/Redis%3Ainitialize) for detailed information.
|
196
305
|
|
197
306
|
*default value* = `'redis://127.0.0.1:6379/0'`
|
198
307
|
|
199
|
-
|
308
|
+
_You can also use [Redis Sentinel](https://redis.io/topics/sentinel) by providing an array of sentinels in the Redis configuration:_
|
200
309
|
|
201
310
|
```ruby
|
202
311
|
SENTINELS = [{host: '127.0.0.1', port: 26380},
|
203
312
|
{host: '127.0.0.1', port: 26381}]
|
204
313
|
|
205
|
-
redis_connection = { url: 'redis://mymaster', sentinels: SENTINELS, role: :master }
|
206
|
-
|
207
314
|
options = {
|
208
315
|
# Other options here
|
209
|
-
redis_url:
|
316
|
+
redis_url: { url: 'redis://mymaster', sentinels: SENTINELS, role: :master }
|
210
317
|
}
|
211
318
|
```
|
319
|
+
### Sample Configuration Using Redis
|
320
|
+
---
|
212
321
|
|
213
|
-
Example using Redis
|
214
322
|
```ruby
|
215
323
|
options = {
|
216
324
|
connection_timeout: 10,
|
@@ -227,150 +335,28 @@ options = {
|
|
227
335
|
begin
|
228
336
|
split_client = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY', options).client
|
229
337
|
rescue SplitIoClient::SDKBlockerTimeoutExpiredException
|
230
|
-
#
|
231
|
-
end
|
232
|
-
```
|
233
|
-
|
234
|
-
#### Unicorn
|
235
|
-
|
236
|
-
When using Unicorn without Redis (i.e. in memory mode) it's highly recommended to include the startup code above inside Unicorn's `after_fork` hook:
|
237
|
-
|
238
|
-
*unicorn.rb*
|
239
|
-
```ruby
|
240
|
-
# Unicorn configuration
|
241
|
-
after_fork do
|
242
|
-
options = {
|
243
|
-
connection_timeout: 10,
|
244
|
-
read_timeout: 5,
|
245
|
-
features_refresh_rate: 120,
|
246
|
-
segments_refresh_rate: 120,
|
247
|
-
metrics_refresh_rate: 360,
|
248
|
-
impressions_refresh_rate: 360,
|
249
|
-
logger: Logger.new('logfile.log'),
|
250
|
-
cache_adapter: :redis,
|
251
|
-
mode: :standalone,
|
252
|
-
redis_url: 'redis://127.0.0.1:6379/0'
|
253
|
-
}
|
254
|
-
begin
|
255
|
-
split_client = SplitIoClient::SplitFactoryBuilder.build('YOUR_API_KEY', options).client
|
256
|
-
rescue SplitIoClient::SDKBlockerTimeoutExpiredException
|
257
|
-
# Some arbitrary actions
|
258
|
-
end
|
338
|
+
# Code to treat raised exception
|
259
339
|
end
|
260
340
|
```
|
261
341
|
|
262
|
-
|
263
|
-
|
264
|
-
#### IMPORTANT
|
265
|
-
|
266
|
-
For now, SDK does not support both `producer` mode and `ready`. You must either run SDK in `standalone` mode, or do not use `ready` option.
|
267
|
-
|
268
|
-
This begin-rescue-end block is optional, you might want to use it to catch timeout expired exception and apply some logic.
|
269
|
-
|
270
|
-
### Execution
|
342
|
+
### Logging
|
271
343
|
---
|
272
344
|
|
273
|
-
|
274
|
-
```ruby
|
275
|
-
split_client.get_treatment('user_id','feature_name', attr: 'val')
|
276
|
-
```
|
277
|
-
|
278
|
-
For example
|
279
|
-
```ruby
|
280
|
-
if split_client.get_treatment('employee_user_01','view_main_list', age: 35)
|
281
|
-
my_app.display_main_list
|
282
|
-
end
|
283
|
-
```
|
345
|
+
By default, the SDK makes use of Ruby stdlib's `Logger` class to log errors and events. You can change the following options when configuring the SDK in your application:
|
284
346
|
|
285
|
-
Also, you can use different keys for actually getting treatment and sending impressions to the server:
|
286
347
|
```ruby
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
attr: 'val'
|
291
|
-
)
|
348
|
+
logger: Logger.new('logfile.log'), # Logger class instance.
|
349
|
+
debug_enabled: true, # Verbose logging.
|
350
|
+
transport_debug_enabled: true # Super verbose logging, including http request data.
|
292
351
|
```
|
293
|
-
When it might be useful? Say, you have a user browsing your website and not signed up yet. You assign some internal id to that user (i.e. bucketing_key) and after user signs up you assign him a matching_key.
|
294
|
-
By doing this you can provide both anonymous and signed up user with the same treatment.
|
295
352
|
|
296
|
-
|
297
|
-
```ruby
|
298
|
-
split_client.get_treatment(
|
299
|
-
{ matching_key: 'user_id' },
|
300
|
-
'feature_name',
|
301
|
-
attr: 'val'
|
302
|
-
)
|
303
|
-
```
|
304
|
-
Is exactly the same as calling
|
305
|
-
```ruby
|
306
|
-
split_client.get_treatment('user_id' ,'feature_name', attr: 'val')
|
307
|
-
```
|
308
|
-
`bucketing_key` must not be nil
|
353
|
+
_Refer to [Advanced Configuration](#advanced-configuration) for more information._
|
309
354
|
|
310
|
-
|
311
|
-
|
312
|
-
```ruby
|
313
|
-
split_manager = SplitIoClient::SplitFactoryBuilder.build('your_api_key', options).manager
|
314
|
-
```
|
315
|
-
|
316
|
-
With the manager you can get a list of your splits by doing:
|
317
|
-
|
318
|
-
```ruby
|
319
|
-
manager.splits
|
320
|
-
```
|
321
|
-
|
322
|
-
And you should get something like this:
|
323
|
-
|
324
|
-
```ruby
|
325
|
-
[
|
326
|
-
{
|
327
|
-
name: 'some_feature',
|
328
|
-
traffic_type_name: nil,
|
329
|
-
killed: false,
|
330
|
-
treatments: nil,
|
331
|
-
change_number: 1469134003507
|
332
|
-
},
|
333
|
-
{
|
334
|
-
name: 'another_feature',
|
335
|
-
traffic_type_name: nil,
|
336
|
-
killed: false,
|
337
|
-
treatments: nil,
|
338
|
-
change_number: 1469134003414
|
339
|
-
},
|
340
|
-
{
|
341
|
-
name: 'even_more_features',
|
342
|
-
traffic_type_name: nil,
|
343
|
-
killed: false,
|
344
|
-
treatments: nil,
|
345
|
-
change_number: 1469133991063
|
346
|
-
},
|
347
|
-
{
|
348
|
-
name: 'yet_another_feature',
|
349
|
-
traffic_type_name: nil,
|
350
|
-
killed: false,
|
351
|
-
treatments: nil,
|
352
|
-
change_number: 1469133757521
|
353
|
-
}
|
354
|
-
]
|
355
|
-
```
|
356
|
-
|
357
|
-
### Logging
|
358
|
-
|
359
|
-
Ruby SDK makes use of Ruby stdlib's `Logger` class to log errors/events, default option is: `Logger.new($stdout)`.
|
360
|
-
|
361
|
-
You can configure the following options in the config file:
|
362
|
-
|
363
|
-
```
|
364
|
-
logger: Logger.new('logfile.log'), # you can specify your own Logger class instance here
|
365
|
-
debug_enabled: true, # used for more verbose logging, including more debug information (false is the default)
|
366
|
-
transport_debug_enabled: true # used for log transport data (mostly http requests, false is the default)
|
367
|
-
```
|
368
|
-
|
369
|
-
### Impression Listener
|
355
|
+
#### Impression Listener
|
370
356
|
|
371
357
|
The SDK provides an optional featured called Impression Listener, that captures every single impression in your app.
|
372
358
|
|
373
|
-
To set up an Impression Listener, define a class that implements a `log` instance method, which must receive the `impression` argument.
|
359
|
+
To set up an Impression Listener, define a class that implements a `log` instance method, which must receive the `impression` argument. e.g.:
|
374
360
|
|
375
361
|
```ruby
|
376
362
|
class MyImpressionListener
|
@@ -380,76 +366,39 @@ class MyImpressionListener
|
|
380
366
|
end
|
381
367
|
```
|
382
368
|
|
383
|
-
|
369
|
+
In the example above, the listener simply takes an impression and logs it to the stdout. By providing a specific listener, you could send this information to a location of your choice. To use this feature, you need to specify the class name in the corresponding option of your configuration (i.e. initializer) like this:
|
384
370
|
|
385
371
|
```ruby
|
386
372
|
{
|
387
373
|
# other options
|
388
|
-
impression_listener: MyImpressionListener.new #
|
374
|
+
impression_listener: MyImpressionListener.new # remember to initialize your class here
|
389
375
|
}
|
390
376
|
```
|
391
377
|
|
392
378
|
### SDK Modes
|
393
|
-
|
394
|
-
By default SDK would run alongside with your application and will be run in `standalone` mode, which includes two modes:
|
395
|
-
- `producer` - storing information from the Splits API in the chosen cache
|
396
|
-
- `consumer` - retrieving data from the cache and providing `get_treatment` interface
|
397
|
-
|
398
|
-
As you might think, you can choose between these 3 modes by providing `mode` option in the config.
|
399
|
-
|
400
|
-
#### Producer mode
|
401
|
-
|
402
|
-
If you have, say, one Redis cache which is used by several Split SDKs at once, e.g.: Python and Ruby, you want to have only one of them to write data to Redis, so it would remain consistent. That's why we have producer mode.
|
403
|
-
|
404
|
-
SDK can be ran in `producer` mode both in the scope of the application (e.g. as a part of the Rails app), and as a separate process. Let's see what steps are needed to run it as a separate process:
|
405
|
-
|
406
|
-
- You need to create a config file with .yml extension. All options specified in the above example section are valid, but you should write them in the YAML format, like this:
|
407
|
-
|
408
|
-
```yaml
|
409
379
|
---
|
410
|
-
:api_key: 'SECRET_API_KEY'
|
411
|
-
:connection_timeout: 10
|
412
|
-
:read_timeout: 5
|
413
|
-
:features_refresh_rate: 120
|
414
|
-
:segments_refresh_rate: 120
|
415
|
-
:metrics_refresh_rate: 360
|
416
|
-
:impressions_refresh_rate: 360
|
417
|
-
:cache_adapter: :redis
|
418
|
-
:mode: :producer
|
419
|
-
:redis_url: 'redis://127.0.0.1:6379/0'
|
420
|
-
```
|
421
380
|
|
381
|
+
The SDK is capable of running in two different modes to fit in different infrastructure configurations:
|
422
382
|
|
423
|
-
-
|
424
|
-
|
425
|
-
bundle binstubs splitclient-rb
|
426
|
-
```
|
383
|
+
- `:standalone` - (default) : The SDK will retrieve information (e.g. split definitions) periodically from the Split servers, and store it in the chosen cache (memory / Redis). It'll also store the application execution information (e.g. impressions) in the cache and send it periodically to the Split servers. As it name implies, in this mode, the SDK neither relies nor synchronizes with any other component.
|
384
|
+
- `:consumer` - If using a load balancer or more than one SDK in your application, guaranteeing that all changes in split definitions are picked up by all SDK instances at the same time is highly recommended in order to ensure consistent results across your infrastructure (i.e. getting the same treatment for a specific split and user pair). To achieve this, use the [Split Synchronizer](https://docs.split.io/docs/split-synchronizer)) and setup your SDKs to work in the `consumer` mode. Setting the components this way, all communication with the Split server is orchestrated by the Synchronizer, while the SDKs pick up definitions and store the execution information from / into a shared Redis data store.
|
427
385
|
|
428
|
-
|
429
|
-
```ruby
|
430
|
-
bundle exec bin/splitio -c ~/path/to/config/file.yml
|
431
|
-
```
|
386
|
+
_You can choose between these 2 modes setting the `mode` option in the config._
|
432
387
|
|
433
|
-
|
434
|
-
```
|
435
|
-
bundle exec bin/splitio -c ~/path/to/config/file.yml --debug
|
436
|
-
```
|
388
|
+
## SDK Server Compatibility
|
437
389
|
|
438
|
-
|
439
|
-
```
|
440
|
-
bundle exec bin/splitio -h
|
441
|
-
```
|
442
|
-
## Server support
|
443
|
-
|
444
|
-
Currently SDK supports:
|
390
|
+
The Split Ruby SDK has been tested as a standalone app as well as using the following web servers:
|
445
391
|
- Thin
|
446
392
|
- Puma
|
447
393
|
- Passenger
|
448
394
|
- Unicorn
|
449
395
|
|
450
|
-
|
396
|
+
For other setups, please reach out to [support@split.io](mailto:support@split.io).
|
397
|
+
|
398
|
+
### Server Compatibility Notes
|
399
|
+
---
|
451
400
|
|
452
|
-
|
401
|
+
#### Unicorn and Puma in cluster mode (only for "memory mode")
|
453
402
|
|
454
403
|
During the start of your application, the SDK spawns multiple threads. Each thread has an infinite loop inside,
|
455
404
|
which is used to fetch splits/segments or send impressions/metrics to the Split service continuously.
|
@@ -497,92 +446,76 @@ end
|
|
497
446
|
|
498
447
|
By doing the above, the SDK will recreate the threads for each new worker and prevent the master process (that doesn't handle requests) from needlessly querying the Split service.
|
499
448
|
|
500
|
-
## Proxy
|
449
|
+
## Proxy Support
|
501
450
|
|
502
|
-
SDK
|
451
|
+
SDK uses the `http_proxy` environment variable. Assign your proxy address to the variable value in the following format, and the SDK will make use of it:
|
503
452
|
|
504
453
|
```
|
505
454
|
http_proxy=http://username:password@hostname:port
|
506
455
|
```
|
507
456
|
|
508
|
-
##
|
509
|
-
|
510
|
-
Currently SDK supports:
|
511
|
-
- Rails
|
457
|
+
## Development Notes
|
512
458
|
|
513
|
-
|
459
|
+
Check out the repository and run `bin/setup` to install dependencies. You can also run `bin/console` to get an interactive prompt.
|
514
460
|
|
515
|
-
|
461
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
516
462
|
|
517
|
-
|
518
|
-
|
519
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
520
|
-
|
521
|
-
## Coverage
|
463
|
+
### Tests & Coverage
|
464
|
+
---
|
522
465
|
|
523
|
-
The gem uses rspec for unit testing.
|
466
|
+
The gem uses `rspec` for unit testing. You can find the files for the unit tests and the specs helper file (`spec_helper.rb`) under the default `/spec` folder.
|
524
467
|
|
525
|
-
To run the
|
468
|
+
To run all the specs in the `spec` folder, use the provided rake task (_make sure Redis is running in localhost_):
|
526
469
|
|
527
|
-
Make sure redis is running in localhost at redis://127.0.0.1:6379/0 and then just run:
|
528
470
|
```bash
|
529
471
|
SPLITCLIENT_ENV=test bundle exec rspec spec
|
530
472
|
```
|
531
473
|
|
532
|
-
|
533
|
-
Right now, the code coverage of the gem is at about 95%.
|
474
|
+
`Simplecov` is used for coverage reporting. Upon executing the rake task it will store the reports in the `/coverage` folder.
|
534
475
|
|
535
|
-
|
536
|
-
|
537
|
-
```bash
|
538
|
-
gem build splitclient-rb.gemspec
|
539
|
-
```
|
540
|
-
|
541
|
-
This will generate a file gemspec with the right version, then:
|
542
|
-
|
543
|
-
```bash
|
544
|
-
gem push splitclient-rb-<VERSION>.gem
|
545
|
-
```
|
546
|
-
|
547
|
-
## Benchmarking
|
476
|
+
### Benchmarks
|
477
|
+
---
|
548
478
|
|
549
|
-
To benchmark hashing algorithms (
|
479
|
+
To benchmark the hashing algorithms (MurmurHash) run:
|
550
480
|
|
551
481
|
```bash
|
552
482
|
bundle exec rake benchmark_hashing_algorithm
|
553
483
|
```
|
554
484
|
|
555
|
-
|
485
|
+
### Contribute
|
486
|
+
---
|
556
487
|
|
557
488
|
Bug reports and pull requests are welcome on GitHub at https://github.com/splitio/ruby-client.
|
558
489
|
|
559
|
-
|
490
|
+
### Release
|
491
|
+
---
|
492
|
+
|
493
|
+
To build and release a new version of the gem, document any changes into the `CHANGES.txt` and the `NEWS` files. Then, increase the version number in `version.rb`.
|
494
|
+
**Note**: This step assumes that all new features and fixes have been merged into the `development` branch, tested, validated, and finally merged into the `master` branch of the `ruby-client` repository.
|
560
495
|
|
561
|
-
To build a new version of the gem
|
496
|
+
To build a new version of the gem after making the changes specified above, run:
|
562
497
|
|
563
498
|
```bash
|
564
499
|
gem build splitclient-rb.gemspec
|
565
500
|
```
|
566
501
|
|
567
|
-
That will generate a splitclient-rb-x.x.x.gem file, with the corresponding version information on it.
|
568
|
-
To
|
502
|
+
That will generate a `splitclient-rb-x.x.x.gem` file, with the corresponding version information on it.
|
503
|
+
To release the new version of the gem at [rubygems.org](rubygems.org) run the following command:
|
569
504
|
|
570
505
|
```bash
|
571
506
|
gem push splitclient-rb-x.x.x.gem
|
572
507
|
```
|
573
508
|
|
574
|
-
|
509
|
+
_A valid rubygems username and password is required._
|
575
510
|
|
576
|
-
|
511
|
+
Once released, `splitclient-rb-x.x.x` version will be available for use in any ruby application.
|
577
512
|
|
578
|
-
|
513
|
+
To get a specific gem version in a Rails application that uses Bundler, add this line to your gemfile:
|
579
514
|
|
580
515
|
```ruby
|
581
516
|
gem 'splitclient-rb', '~> x.x.x'
|
582
517
|
```
|
583
518
|
|
584
|
-
line to have the latest version of the gem ready to be used.
|
585
|
-
|
586
519
|
## License
|
587
520
|
|
588
521
|
The gem is available as open source under the terms of the [Apache License](http://www.apache.org/licenses/).
|