splitclient-rb 6.3.0 → 8.11.0
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 +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/pull_request_template.md +9 -0
- data/.github/workflows/ci.yml +90 -0
- data/.github/workflows/update-license-year.yml +45 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +46 -3
- data/CHANGES.txt +158 -11
- data/CONTRIBUTORS-GUIDE.md +49 -0
- data/LICENSE +169 -13
- data/NOTICE.txt +5 -0
- data/README.md +67 -27
- data/Rakefile +1 -8
- data/ext/murmurhash/3_x64_128.c +117 -0
- data/ext/murmurhash/murmurhash.c +5 -1
- data/lib/murmurhash/murmurhash.jar +0 -0
- data/lib/splitclient-rb/cache/adapters/cache_adapter.rb +3 -3
- data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +4 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +7 -0
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +12 -4
- data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +83 -0
- data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +70 -0
- data/lib/splitclient-rb/cache/filter/bloom_filter.rb +67 -0
- data/lib/splitclient-rb/cache/filter/filter_adapter.rb +32 -0
- data/lib/splitclient-rb/cache/filter/flag_set_filter.rb +40 -0
- data/lib/splitclient-rb/cache/hashers/impression_hasher.rb +34 -0
- data/lib/splitclient-rb/cache/observers/impression_observer.rb +22 -0
- data/lib/splitclient-rb/cache/observers/noop_impression_observer.rb +10 -0
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +26 -14
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +9 -14
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +31 -10
- data/lib/splitclient-rb/cache/repositories/flag_sets/memory_repository.rb +40 -0
- data/lib/splitclient-rb/cache/repositories/flag_sets/redis_repository.rb +49 -0
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +22 -23
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +15 -22
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +6 -31
- data/lib/splitclient-rb/cache/repositories/repository.rb +6 -5
- data/lib/splitclient-rb/cache/repositories/rule_based_segments_repository.rb +136 -0
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +46 -6
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +232 -43
- data/lib/splitclient-rb/cache/routers/impression_router.rb +24 -22
- data/lib/splitclient-rb/cache/senders/events_sender.rb +12 -29
- data/lib/splitclient-rb/cache/senders/impressions_adapter/memory_sender.rb +71 -0
- data/lib/splitclient-rb/cache/senders/impressions_adapter/redis_sender.rb +69 -0
- data/lib/splitclient-rb/cache/senders/impressions_count_sender.rb +43 -0
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +27 -13
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +11 -25
- data/lib/splitclient-rb/cache/senders/impressions_sender_adapter.rb +21 -0
- data/lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb +47 -0
- data/lib/splitclient-rb/cache/stores/localhost_split_builder.rb +95 -0
- data/lib/splitclient-rb/cache/stores/localhost_split_store.rb +110 -0
- data/lib/splitclient-rb/cache/stores/store_utils.rb +13 -0
- data/lib/splitclient-rb/clients/split_client.rb +385 -138
- data/lib/splitclient-rb/constants.rb +16 -0
- data/lib/splitclient-rb/engine/api/client.rb +38 -43
- data/lib/splitclient-rb/engine/api/events.rb +19 -11
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +1 -0
- data/lib/splitclient-rb/engine/api/impressions.rb +49 -14
- data/lib/splitclient-rb/engine/api/segments.rb +31 -24
- data/lib/splitclient-rb/engine/api/splits.rb +108 -33
- data/lib/splitclient-rb/engine/api/telemetry_api.rb +47 -0
- data/lib/splitclient-rb/engine/auth_api_client.rb +96 -0
- data/lib/splitclient-rb/engine/back_off.rb +26 -0
- data/lib/splitclient-rb/engine/common/impressions_counter.rb +45 -0
- data/lib/splitclient-rb/engine/common/impressions_manager.rb +165 -0
- data/lib/splitclient-rb/engine/common/noop_impressions_counter.rb +27 -0
- data/lib/splitclient-rb/engine/events/events_delivery.rb +20 -0
- data/lib/splitclient-rb/engine/events/events_manager.rb +194 -0
- data/lib/splitclient-rb/engine/events/events_manager_config.rb +96 -0
- data/lib/splitclient-rb/engine/events/events_task.rb +50 -0
- data/lib/splitclient-rb/engine/events/noop_events_queue.rb +13 -0
- data/lib/splitclient-rb/engine/fallback_treatment_calculator.rb +48 -0
- data/lib/splitclient-rb/engine/impressions/noop_unique_keys_tracker.rb +17 -0
- data/lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb +144 -0
- data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +1 -1
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +7 -5
- data/lib/splitclient-rb/engine/matchers/between_semver_matcher.rb +33 -0
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +10 -8
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +2 -6
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +1 -5
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +7 -5
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +6 -5
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +5 -4
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +3 -2
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +6 -4
- data/lib/splitclient-rb/engine/matchers/equal_to_semver_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +1 -5
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +6 -4
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/in_list_semver_matcher.rb +36 -0
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +6 -4
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/matcher.rb +22 -0
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +3 -2
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +3 -2
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +2 -6
- data/lib/splitclient-rb/engine/matchers/prerequisites_matcher.rb +31 -0
- data/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +78 -0
- data/lib/splitclient-rb/engine/matchers/semver.rb +201 -0
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +2 -1
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +4 -3
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +3 -2
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +7 -5
- data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +3 -65
- data/lib/splitclient-rb/engine/models/evaluation_options.rb +9 -0
- data/lib/splitclient-rb/engine/models/event_active_subscriptions.rb +14 -0
- data/lib/splitclient-rb/engine/models/events_metadata.rb +10 -0
- data/lib/splitclient-rb/engine/models/fallback_treatment.rb +11 -0
- data/lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb +36 -0
- data/lib/splitclient-rb/engine/models/label.rb +3 -0
- data/lib/splitclient-rb/engine/models/sdk_event.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_event_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event.rb +8 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb +14 -0
- data/lib/splitclient-rb/engine/models/segment_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/split_http_response.rb +19 -0
- data/lib/splitclient-rb/engine/models/valid_sdk_event.rb +14 -0
- data/lib/splitclient-rb/engine/parser/condition.rb +81 -20
- data/lib/splitclient-rb/engine/parser/evaluator.rb +40 -51
- data/lib/splitclient-rb/engine/push_manager.rb +66 -0
- data/lib/splitclient-rb/engine/status_manager.rb +39 -0
- data/lib/splitclient-rb/engine/sync_manager.rb +180 -0
- data/lib/splitclient-rb/engine/synchronizer.rb +231 -0
- data/lib/splitclient-rb/exceptions.rb +20 -1
- data/lib/splitclient-rb/helpers/decryption_helper.rb +25 -0
- data/lib/splitclient-rb/helpers/evaluator_helper.rb +37 -0
- data/lib/splitclient-rb/helpers/repository_helper.rb +61 -0
- data/lib/splitclient-rb/helpers/thread_helper.rb +24 -0
- data/lib/splitclient-rb/helpers/util.rb +26 -0
- data/lib/splitclient-rb/managers/split_manager.rb +58 -20
- data/lib/splitclient-rb/spec.rb +9 -0
- data/lib/splitclient-rb/split_config.rb +336 -54
- data/lib/splitclient-rb/split_factory.rb +219 -33
- data/lib/splitclient-rb/split_factory_builder.rb +1 -22
- data/lib/splitclient-rb/split_factory_registry.rb +63 -0
- data/lib/splitclient-rb/split_logger.rb +9 -10
- data/lib/splitclient-rb/sse/event_source/client.rb +263 -0
- data/lib/splitclient-rb/sse/event_source/event_parser.rb +65 -0
- data/lib/splitclient-rb/sse/event_source/event_types.rb +15 -0
- data/lib/splitclient-rb/sse/event_source/stream_data.rb +22 -0
- data/lib/splitclient-rb/sse/notification_manager_keeper.rb +84 -0
- data/lib/splitclient-rb/sse/notification_processor.rb +48 -0
- data/lib/splitclient-rb/sse/sse_handler.rb +44 -0
- data/lib/splitclient-rb/sse/workers/segments_worker.rb +62 -0
- data/lib/splitclient-rb/sse/workers/splits_worker.rb +149 -0
- data/lib/splitclient-rb/telemetry/domain/constants.rb +48 -0
- data/lib/splitclient-rb/telemetry/domain/structs.rb +35 -0
- data/lib/splitclient-rb/telemetry/evaluation_consumer.rb +14 -0
- data/lib/splitclient-rb/telemetry/evaluation_producer.rb +21 -0
- data/lib/splitclient-rb/telemetry/init_consumer.rb +14 -0
- data/lib/splitclient-rb/telemetry/init_producer.rb +19 -0
- data/lib/splitclient-rb/telemetry/memory/memory_evaluation_consumer.rb +32 -0
- data/lib/splitclient-rb/telemetry/memory/memory_evaluation_producer.rb +24 -0
- data/lib/splitclient-rb/telemetry/memory/memory_init_consumer.rb +28 -0
- data/lib/splitclient-rb/telemetry/memory/memory_init_producer.rb +34 -0
- data/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb +119 -0
- data/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb +87 -0
- data/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +213 -0
- data/lib/splitclient-rb/telemetry/redis/redis_evaluation_producer.rb +38 -0
- data/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +37 -0
- data/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb +27 -0
- data/lib/splitclient-rb/telemetry/runtime_consumer.rb +25 -0
- data/lib/splitclient-rb/telemetry/runtime_producer.rb +25 -0
- data/lib/splitclient-rb/telemetry/storages/memory.rb +159 -0
- data/lib/splitclient-rb/telemetry/sync_task.rb +36 -0
- data/lib/splitclient-rb/telemetry/synchronizer.rb +33 -0
- data/lib/splitclient-rb/utilitites.rb +8 -0
- data/lib/splitclient-rb/validators.rb +142 -38
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +101 -16
- data/sonar-project.properties +6 -0
- data/splitclient-rb.gemspec +28 -23
- metadata +262 -82
- data/.travis.yml +0 -11
- data/Appraisals +0 -10
- data/Detailed-README.md +0 -588
- data/NEWS +0 -141
- data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +0 -127
- data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +0 -96
- data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +0 -21
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +0 -56
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +0 -46
- data/lib/splitclient-rb/cache/stores/segment_store.rb +0 -81
- data/lib/splitclient-rb/cache/stores/split_store.rb +0 -102
- data/lib/splitclient-rb/clients/localhost_split_client.rb +0 -183
- data/lib/splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent.rb +0 -46
- data/lib/splitclient-rb/engine/api/metrics.rb +0 -60
- data/lib/splitclient-rb/engine/metrics/metrics.rb +0 -80
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +0 -81
- data/lib/splitclient-rb/localhost_split_factory.rb +0 -13
- data/lib/splitclient-rb/localhost_utils.rb +0 -59
- data/lib/splitclient-rb/managers/localhost_split_manager.rb +0 -60
data/NEWS
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
6.3.0 (Apr 30, 2019)
|
|
2
|
-
|
|
3
|
-
- Added Dynamic Configurations support through two new methods that mimick the regular ones, changing the type of what is returned.
|
|
4
|
-
- get_treatment_with_config: Same as get_treatment but returning the treatment with it's config.
|
|
5
|
-
- get_treatments_with_config: Same as get_treatments, but instead of a map of string it returns a map of treatments with config.
|
|
6
|
-
- Added configs to SplitViews returned by the manager module.
|
|
7
|
-
- Updated localhost mode. Now besides supporting the old text files with `.split` extension (to be deprecated soon), we support YAML (.yaml/.yml) files where you can
|
|
8
|
-
define configurations for your treatments and also whitelisted keys. Read more in our docs!
|
|
9
|
-
|
|
10
|
-
6.2.0
|
|
11
|
-
Ensure SDK flushes information to Split servers on client destroy
|
|
12
|
-
Fix for compatibility issue between Faraday < 0.13 and net-http-persistent 3
|
|
13
|
-
Change default features refresh rate interval to 5 seconds
|
|
14
|
-
|
|
15
|
-
6.1.0
|
|
16
|
-
|
|
17
|
-
Review input validation for client API methods: get_treatment, get_treatments, track, manager. Add input validation to block_until_ready, client startup, and destroy
|
|
18
|
-
Add additional logging to the SDK Client in order to help debug matcher related issues
|
|
19
|
-
Fix for issue causing redis_url parameter to be ignored
|
|
20
|
-
|
|
21
|
-
6.0.1
|
|
22
|
-
|
|
23
|
-
Fix an issue in events and impressions API calls log messages introduced in 6.0.0
|
|
24
|
-
|
|
25
|
-
6.0.0
|
|
26
|
-
|
|
27
|
-
BREAKING CHANGE: Remove producer mode, make memory adapter mandatory in standalone mode, and Redis adapter mandatory in consumer mode.
|
|
28
|
-
BREAKING CHANGE: Reduce the total number of Redis operations of the SDK by changing the impressions storage format and adding a memory cache for splits and segments. It requires to have Split Synchronizer > v2.0.0 running if you are using Redis.
|
|
29
|
-
SDK is now compatible with net-http-persistent 3.0.
|
|
30
|
-
|
|
31
|
-
5.1.2
|
|
32
|
-
|
|
33
|
-
Add input validation for client API methods: get_treatment, get_treatments, track, manager
|
|
34
|
-
|
|
35
|
-
5.1.1
|
|
36
|
-
|
|
37
|
-
Reduces the number of calls to Redis when calling #client.get_treatments using such cache adapter.
|
|
38
|
-
|
|
39
|
-
5.1.0
|
|
40
|
-
|
|
41
|
-
Prevent unhandled exceptions from raising when API get calls fail on Segments and Treatments.
|
|
42
|
-
|
|
43
|
-
5.0.3
|
|
44
|
-
|
|
45
|
-
Creates a new configuration parameter (impressions_bulk_size) to manage the max number of impressions sent to the Split backend on each post.
|
|
46
|
-
Changes impressions_queue_size so that it manages only the queue size in the memory adapter.
|
|
47
|
-
A backwards compatibility fail safe is included for users of previous SDK versions.
|
|
48
|
-
|
|
49
|
-
5.0.2
|
|
50
|
-
|
|
51
|
-
Turn Impression Listener into an optional SDK feature.
|
|
52
|
-
Prevents the impression thread from being started if a listener is not in place
|
|
53
|
-
|
|
54
|
-
5.0.1
|
|
55
|
-
|
|
56
|
-
Adding stop! method to the factory.
|
|
57
|
-
With this method the user will be able to stop the threads that queries the Split Service. This will be used in the before_fork configuration in Puma and Unicorn to stop the threads in the master process.
|
|
58
|
-
|
|
59
|
-
5.0.0
|
|
60
|
-
|
|
61
|
-
This is a breaking change in how users buckets are allocated.
|
|
62
|
-
Ruby SDK was wrongly picking up the right buckets and defauled to
|
|
63
|
-
use a "legacy hashing" instead of our moder murmur3 algo which is
|
|
64
|
-
what other SDKs use. Please reach out to support@split.io for help
|
|
65
|
-
on how to upgrade to this release.
|
|
66
|
-
|
|
67
|
-
4.5.0
|
|
68
|
-
|
|
69
|
-
Add JRuby support
|
|
70
|
-
|
|
71
|
-
4.4.0
|
|
72
|
-
|
|
73
|
-
Add the ability to send event data to split service (.track() api)
|
|
74
|
-
|
|
75
|
-
4.3.0
|
|
76
|
-
|
|
77
|
-
Add support for impression listener, there is an ability to use user-defined class to capture all impressions
|
|
78
|
-
Now you can apply attribute matcher to the traffic type
|
|
79
|
-
|
|
80
|
-
4.2.0
|
|
81
|
-
|
|
82
|
-
Introduce new matchers: boolean and regexp (string).
|
|
83
|
-
Remove unneeded dependencies
|
|
84
|
-
Introduce dependency matcher, which allows treatment of one split to depend on the evaluation of another.
|
|
85
|
-
|
|
86
|
-
4.1.0
|
|
87
|
-
|
|
88
|
-
Introduce set matchers: part of set, contains all and contains any, starts with, ends with and contains.
|
|
89
|
-
|
|
90
|
-
4.0.0
|
|
91
|
-
|
|
92
|
-
Add support for murmur3 hashing algorithm
|
|
93
|
-
Optimize gem memory usage
|
|
94
|
-
|
|
95
|
-
3.3.0
|
|
96
|
-
|
|
97
|
-
Add support for traffic allocation
|
|
98
|
-
|
|
99
|
-
3.1.0
|
|
100
|
-
|
|
101
|
-
Now supporting Redis as a cache adapter
|
|
102
|
-
Factory is build now as SplitIoClient::SplitFactoryBuilder.build('<API_KEY>')
|
|
103
|
-
|
|
104
|
-
3.0.2
|
|
105
|
-
|
|
106
|
-
now support also client.get_treatment( { :matching_key = 'bb' , "bucketing_key = ''}, ....)
|
|
107
|
-
|
|
108
|
-
2.0.1
|
|
109
|
-
|
|
110
|
-
No news for this release
|
|
111
|
-
|
|
112
|
-
2.0.0
|
|
113
|
-
|
|
114
|
-
Instantiation of the split client is now through a factory:
|
|
115
|
-
|
|
116
|
-
factory = SplitIoClient::SplitFactory.new("rbk5je8be5qflpa047m17fe4ra", options)
|
|
117
|
-
client = factory.client
|
|
118
|
-
manager = factory.manager
|
|
119
|
-
|
|
120
|
-
1.0.4
|
|
121
|
-
|
|
122
|
-
Added AND combiner for conditions support. Added events_uri config param which is the url where the metrics post are send to.
|
|
123
|
-
|
|
124
|
-
1.0.3
|
|
125
|
-
|
|
126
|
-
This version of the gem fixes two minor bugs related to the config option for the refresh rates, as well as an inconsistency for the split definitions that are not created from the web app, but directly from the api instead.
|
|
127
|
-
|
|
128
|
-
1.0.2
|
|
129
|
-
|
|
130
|
-
Support for all the new matchers including: number comparison with >=, <=, =, between; date comparison with is on or before, is on or after, is on, between; attribute value in a defined set of values.
|
|
131
|
-
No other major updates for this release.
|
|
132
|
-
|
|
133
|
-
1.0.1
|
|
134
|
-
|
|
135
|
-
isTreatment was removed from the API
|
|
136
|
-
local environment file was removed to match the rest of the SDKs. "split".
|
|
137
|
-
No other major updates for this release.
|
|
138
|
-
|
|
139
|
-
1.0.0
|
|
140
|
-
|
|
141
|
-
No news for this release.
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
module Cache
|
|
3
|
-
module Repositories
|
|
4
|
-
module Metrics
|
|
5
|
-
class MemoryRepository
|
|
6
|
-
def initialize(_ = nil, adapter)
|
|
7
|
-
@counts = []
|
|
8
|
-
@latencies = []
|
|
9
|
-
@gauges = []
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def add_count(counter, delta)
|
|
13
|
-
counter_hash = @counts.find { |c| c[:name] == counter }
|
|
14
|
-
if counter_hash.nil?
|
|
15
|
-
counter_delta = SumAndCount.new
|
|
16
|
-
counter_delta.add_delta(delta)
|
|
17
|
-
@counts << { name: counter, delta: counter_delta }
|
|
18
|
-
else
|
|
19
|
-
counter_hash[:delta].add_delta(delta)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def add_latency(operation, time_in_ms, binary_search)
|
|
24
|
-
operation_hash = @latencies.find { |l| l[:operation] == operation }
|
|
25
|
-
if operation_hash.nil?
|
|
26
|
-
latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : [time_in_ms]
|
|
27
|
-
@latencies << { operation: operation, latencies: latencies_for_op }
|
|
28
|
-
else
|
|
29
|
-
latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : operation_hash[:latencies].push(time_in_ms)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def add_gauge(gauge, value)
|
|
34
|
-
gauge_hash = @gauges.find { |g| g[:name] == gauge }
|
|
35
|
-
if gauge_hash.nil?
|
|
36
|
-
gauge_value = ValueAndCount.new
|
|
37
|
-
gauge_value.set_value(value)
|
|
38
|
-
@gauges << { name: gauge, value: gauge_value }
|
|
39
|
-
else
|
|
40
|
-
gauge_hash[:value].set_value(value)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def counts
|
|
45
|
-
@counts.each_with_object({}) do |count, memo|
|
|
46
|
-
memo[count[:name]] = count[:delta].sum
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def latencies
|
|
51
|
-
@latencies.each_with_object({}) do |latency, memo|
|
|
52
|
-
memo[latency[:operation]] = latency[:latencies]
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def gauges
|
|
57
|
-
# TODO
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def clear_counts
|
|
61
|
-
@counts = []
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def clear_latencies
|
|
65
|
-
@latencies = []
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def clear_gauges
|
|
69
|
-
@gauges = []
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def clear
|
|
73
|
-
clear_counts
|
|
74
|
-
clear_latencies
|
|
75
|
-
clear_gauges
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
#
|
|
79
|
-
# small class to act as DTO for counts
|
|
80
|
-
#
|
|
81
|
-
class SumAndCount
|
|
82
|
-
attr_reader :count
|
|
83
|
-
attr_reader :sum
|
|
84
|
-
|
|
85
|
-
def initialize
|
|
86
|
-
@count = 0
|
|
87
|
-
@sum = 0
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def add_delta(delta)
|
|
91
|
-
@count += 1
|
|
92
|
-
@sum += delta
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def clear
|
|
96
|
-
@count = 0
|
|
97
|
-
@sum = 0
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
# small class to act as DTO for gauges
|
|
103
|
-
#
|
|
104
|
-
class ValueAndCount
|
|
105
|
-
attr_reader :count
|
|
106
|
-
attr_reader :value
|
|
107
|
-
|
|
108
|
-
def initialize
|
|
109
|
-
@count = 0
|
|
110
|
-
@value = 0
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def set_value(value)
|
|
114
|
-
@count += 1
|
|
115
|
-
@value = value
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def clear
|
|
119
|
-
@count = 0
|
|
120
|
-
@value = 0
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
module Cache
|
|
3
|
-
module Repositories
|
|
4
|
-
module Metrics
|
|
5
|
-
class RedisRepository < Repository
|
|
6
|
-
def initialize(adapter = nil)
|
|
7
|
-
@adapter = adapter
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def add_count(counter, delta)
|
|
11
|
-
prefixed_name = impressions_metrics_key("count.#{counter}")
|
|
12
|
-
counts = @adapter.find_strings_by_prefix(prefixed_name)
|
|
13
|
-
|
|
14
|
-
@adapter.inc(prefixed_name, delta)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def add_latency(operation, time_in_ms, binary_search)
|
|
18
|
-
prefixed_name = impressions_metrics_key("latency.#{operation}")
|
|
19
|
-
|
|
20
|
-
if operation == 'sdk.get_treatment'
|
|
21
|
-
@adapter.inc("#{prefixed_name}.#{binary_search.add_latency_millis(time_in_ms, true)}")
|
|
22
|
-
return
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
@adapter.append_to_string(prefixed_name, "#{time_in_ms},")
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def add_gauge(gauge, value)
|
|
29
|
-
# TODO
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def counts
|
|
33
|
-
keys = @adapter.find_strings_by_prefix(impressions_metrics_key("count"))
|
|
34
|
-
|
|
35
|
-
return [] if keys.empty?
|
|
36
|
-
|
|
37
|
-
@adapter.multiple_strings(keys).map do |name, data|
|
|
38
|
-
[name.gsub(impressions_metrics_key('count.'), ''), data]
|
|
39
|
-
end.to_h
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def latencies
|
|
43
|
-
collected_latencies = {}
|
|
44
|
-
latencies_array = Array.new(BinarySearchLatencyTracker::BUCKETS.length, 0)
|
|
45
|
-
keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
|
|
46
|
-
|
|
47
|
-
return [] if keys.empty?
|
|
48
|
-
|
|
49
|
-
found_latencies = @adapter.multiple_strings(keys).map do |name, data|
|
|
50
|
-
[name.gsub(impressions_metrics_key('latency.'), ''), data]
|
|
51
|
-
end.to_h
|
|
52
|
-
|
|
53
|
-
found_latencies.each do |key, value|
|
|
54
|
-
if key.start_with?('sdk.get_treatment')
|
|
55
|
-
index = key.gsub('sdk.get_treatment.', '').to_i
|
|
56
|
-
latencies_array[index] = value.to_i
|
|
57
|
-
|
|
58
|
-
next
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
collected_latencies[key] = value.split(',').map(&:to_f)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
collected_latencies['sdk.get_treatment'] = latencies_array unless latencies_array.reduce(:+) == 0
|
|
65
|
-
|
|
66
|
-
collected_latencies
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def gauges
|
|
70
|
-
# TODO
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def clear_counts
|
|
74
|
-
keys = @adapter.find_strings_by_prefix(impressions_metrics_key('count'))
|
|
75
|
-
@adapter.delete(keys)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def clear_latencies
|
|
79
|
-
keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
|
|
80
|
-
@adapter.delete(keys)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def clear_gauges
|
|
84
|
-
# TODO
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def clear
|
|
88
|
-
clear_counts
|
|
89
|
-
clear_latencies
|
|
90
|
-
clear_gauges
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
module Cache
|
|
3
|
-
module Repositories
|
|
4
|
-
# Repository which forwards impressions interface to the selected adapter
|
|
5
|
-
class MetricsRepository < Repository
|
|
6
|
-
extend Forwardable
|
|
7
|
-
def_delegators :@adapter, :add_count, :add_latency, :add_gauge, :counts, :latencies, :gauges,
|
|
8
|
-
:clear_counts, :clear_latencies, :clear_gauges, :clear
|
|
9
|
-
|
|
10
|
-
def initialize(adapter)
|
|
11
|
-
@adapter = case adapter.class.to_s
|
|
12
|
-
when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
|
|
13
|
-
Repositories::Metrics::MemoryRepository.new(adapter)
|
|
14
|
-
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
|
15
|
-
Repositories::Metrics::RedisRepository.new(adapter)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SplitIoClient
|
|
4
|
-
module Cache
|
|
5
|
-
module Senders
|
|
6
|
-
class MetricsSender
|
|
7
|
-
def initialize(metrics_repository, api_key)
|
|
8
|
-
@metrics_repository = metrics_repository
|
|
9
|
-
@api_key = api_key
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def call
|
|
13
|
-
return if ENV['SPLITCLIENT_ENV'] == 'test'
|
|
14
|
-
|
|
15
|
-
metrics_thread
|
|
16
|
-
|
|
17
|
-
if defined?(PhusionPassenger)
|
|
18
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
|
19
|
-
metrics_thread if forked
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def metrics_thread
|
|
27
|
-
SplitIoClient.configuration.threads[:metrics_sender] = Thread.new do
|
|
28
|
-
begin
|
|
29
|
-
SplitIoClient.configuration.logger.info('Starting metrics service')
|
|
30
|
-
|
|
31
|
-
loop do
|
|
32
|
-
post_metrics
|
|
33
|
-
|
|
34
|
-
sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.metrics_refresh_rate))
|
|
35
|
-
end
|
|
36
|
-
rescue SplitIoClient::SDKShutdownException
|
|
37
|
-
post_metrics
|
|
38
|
-
|
|
39
|
-
SplitIoClient.configuration.logger.info('Posting metrics due to shutdown')
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def post_metrics
|
|
45
|
-
metrics_api.post
|
|
46
|
-
rescue StandardError => error
|
|
47
|
-
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def metrics_api
|
|
51
|
-
@metrics_api ||= SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require 'thread'
|
|
2
|
-
require 'timeout'
|
|
3
|
-
|
|
4
|
-
module SplitIoClient
|
|
5
|
-
module Cache
|
|
6
|
-
module Stores
|
|
7
|
-
class SDKBlocker
|
|
8
|
-
attr_reader :splits_repository
|
|
9
|
-
|
|
10
|
-
def initialize(splits_repository, segments_repository)
|
|
11
|
-
@splits_repository = splits_repository
|
|
12
|
-
@segments_repository = segments_repository
|
|
13
|
-
|
|
14
|
-
@splits_repository.not_ready!
|
|
15
|
-
@segments_repository.not_ready!
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def splits_ready!
|
|
19
|
-
@splits_repository.ready!
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def segments_ready!
|
|
23
|
-
@segments_repository.ready!
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def block
|
|
27
|
-
begin
|
|
28
|
-
Timeout::timeout(SplitIoClient.configuration.block_until_ready) do
|
|
29
|
-
sleep 0.1 until ready?
|
|
30
|
-
end
|
|
31
|
-
rescue Timeout::Error
|
|
32
|
-
fail SDKBlockerTimeoutExpiredException, 'SDK start up timeout expired'
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
SplitIoClient.configuration.logger.info('SplitIO SDK is ready')
|
|
36
|
-
SplitIoClient.configuration.threads[:split_store].run
|
|
37
|
-
SplitIoClient.configuration.threads[:segment_store].run
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def ready?
|
|
41
|
-
@splits_repository.ready? && @segments_repository.ready?
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
module Cache
|
|
3
|
-
module Stores
|
|
4
|
-
class SegmentStore
|
|
5
|
-
attr_reader :segments_repository
|
|
6
|
-
|
|
7
|
-
def initialize(segments_repository, api_key, metrics, sdk_blocker = nil)
|
|
8
|
-
@segments_repository = segments_repository
|
|
9
|
-
@api_key = api_key
|
|
10
|
-
@metrics = metrics
|
|
11
|
-
@sdk_blocker = sdk_blocker
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call
|
|
15
|
-
if ENV['SPLITCLIENT_ENV'] == 'test'
|
|
16
|
-
store_segments
|
|
17
|
-
else
|
|
18
|
-
segments_thread
|
|
19
|
-
|
|
20
|
-
if defined?(PhusionPassenger)
|
|
21
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
|
22
|
-
segments_thread if forked
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def segments_thread
|
|
31
|
-
SplitIoClient.configuration.threads[:segment_store] = Thread.new do
|
|
32
|
-
SplitIoClient.configuration.logger.info('Starting segments fetcher service')
|
|
33
|
-
SplitIoClient.configuration.block_until_ready > 0 ? blocked_store : unblocked_store
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def blocked_store
|
|
38
|
-
loop do
|
|
39
|
-
next unless @sdk_blocker.splits_repository.ready?
|
|
40
|
-
|
|
41
|
-
store_segments
|
|
42
|
-
SplitIoClient.configuration.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if SplitIoClient.configuration.debug_enabled
|
|
43
|
-
|
|
44
|
-
unless @sdk_blocker.ready?
|
|
45
|
-
@sdk_blocker.segments_ready!
|
|
46
|
-
SplitIoClient.configuration.logger.info('segments are ready')
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
sleep_for = random_interval(SplitIoClient.configuration.segments_refresh_rate)
|
|
50
|
-
SplitIoClient.configuration.logger.debug("Segments store is sleeping for: #{sleep_for} seconds") if SplitIoClient.configuration.debug_enabled
|
|
51
|
-
sleep(sleep_for)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def unblocked_store
|
|
56
|
-
loop do
|
|
57
|
-
store_segments
|
|
58
|
-
|
|
59
|
-
sleep(random_interval(SplitIoClient.configuration.segments_refresh_rate))
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def store_segments
|
|
64
|
-
segments_api.store_segments_by_names(@segments_repository.used_segment_names)
|
|
65
|
-
rescue StandardError => error
|
|
66
|
-
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def random_interval(interval)
|
|
70
|
-
random_factor = Random.new.rand(50..100) / 100.0
|
|
71
|
-
|
|
72
|
-
interval * random_factor
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def segments_api
|
|
76
|
-
@segments_api ||= SplitIoClient::Api::Segments.new(@api_key, @metrics, @segments_repository)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
module Cache
|
|
3
|
-
module Stores
|
|
4
|
-
class SplitStore
|
|
5
|
-
attr_reader :splits_repository
|
|
6
|
-
|
|
7
|
-
def initialize(splits_repository, api_key, metrics, sdk_blocker = nil)
|
|
8
|
-
@splits_repository = splits_repository
|
|
9
|
-
@api_key = api_key
|
|
10
|
-
@metrics = metrics
|
|
11
|
-
@sdk_blocker = sdk_blocker
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call
|
|
15
|
-
if ENV['SPLITCLIENT_ENV'] == 'test'
|
|
16
|
-
store_splits
|
|
17
|
-
else
|
|
18
|
-
splits_thread
|
|
19
|
-
|
|
20
|
-
if defined?(PhusionPassenger)
|
|
21
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
|
22
|
-
splits_thread if forked
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def splits_thread
|
|
31
|
-
SplitIoClient.configuration.threads[:split_store] = Thread.new do
|
|
32
|
-
SplitIoClient.configuration.logger.info('Starting splits fetcher service')
|
|
33
|
-
loop do
|
|
34
|
-
store_splits
|
|
35
|
-
|
|
36
|
-
sleep(random_interval(SplitIoClient.configuration.features_refresh_rate))
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def store_splits
|
|
42
|
-
data = splits_since(@splits_repository.get_change_number)
|
|
43
|
-
|
|
44
|
-
data[:splits] && data[:splits].each do |split|
|
|
45
|
-
add_split_unless_archived(split)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
@splits_repository.set_segment_names(data[:segment_names])
|
|
49
|
-
@splits_repository.set_change_number(data[:till])
|
|
50
|
-
|
|
51
|
-
SplitIoClient.configuration.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if SplitIoClient.configuration.debug_enabled
|
|
52
|
-
|
|
53
|
-
if SplitIoClient.configuration.block_until_ready > 0 && !@sdk_blocker.ready?
|
|
54
|
-
@sdk_blocker.splits_ready!
|
|
55
|
-
SplitIoClient.configuration.logger.info('splits are ready')
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
rescue StandardError => error
|
|
59
|
-
SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def random_interval(interval)
|
|
63
|
-
random_factor = Random.new.rand(50..100) / 100.0
|
|
64
|
-
|
|
65
|
-
interval * random_factor
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def splits_since(since)
|
|
69
|
-
splits_api.since(since)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def add_split_unless_archived(split)
|
|
73
|
-
if Engine::Models::Split.archived?(split)
|
|
74
|
-
SplitIoClient.configuration.logger.debug("Seeing archived split #{split[:name]}") if SplitIoClient.configuration.debug_enabled
|
|
75
|
-
|
|
76
|
-
remove_archived_split(split)
|
|
77
|
-
else
|
|
78
|
-
store_split(split)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def remove_archived_split(split)
|
|
83
|
-
SplitIoClient.configuration.logger.debug("removing split from store(#{split})") if SplitIoClient.configuration.debug_enabled
|
|
84
|
-
|
|
85
|
-
@splits_repository.remove_split(split[:name])
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def store_split(split)
|
|
89
|
-
SplitIoClient.configuration.logger.debug("storing split (#{split[:name]})") if SplitIoClient.configuration.debug_enabled
|
|
90
|
-
|
|
91
|
-
@splits_repository.add_split(split)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
private
|
|
95
|
-
|
|
96
|
-
def splits_api
|
|
97
|
-
@splits_api ||= SplitIoClient::Api::Splits.new(@api_key, @metrics)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|