From 1ee1295549734922937ef6285f2fac5844a8fd6a Mon Sep 17 00:00:00 2001 From: Mauro Sanz Date: Wed, 26 May 2021 09:53:20 -0300 Subject: [PATCH 1/3] init implementation --- lib/splitclient-rb/engine/api/telemetry_api.rb | 18 +++++++++++++++--- .../telemetry/memory/memory_synchronizer.rb | 5 +++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/splitclient-rb/engine/api/telemetry_api.rb b/lib/splitclient-rb/engine/api/telemetry_api.rb index af3061c0..00c6f3df 100644 --- a/lib/splitclient-rb/engine/api/telemetry_api.rb +++ b/lib/splitclient-rb/engine/api/telemetry_api.rb @@ -9,8 +9,20 @@ def initialize(config, api_key, telemetry_runtime_producer) @telemetry_runtime_producer = telemetry_runtime_producer end - def record_init - # TODO: implement + def record_init(config_init) + start = Time.now + response = post_api("#{@config.telemetry_service_url}/metrics/config", @api_key, config_init) + + if response.success? + @config.split_logger.log_if_debug("Telemetry post success: record init.") + + bucket = BinarySearchLatencyTracker.get_bucket((Time.now - start) * 1000.0) + @telemetry_runtime_producer.record_sync_latency(Telemetry::Domain::Constants::TELEMETRY_SYNC, bucket) + @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::TELEMETRY_SYNC, (Time.now.to_f * 1000.0).to_i) + else + @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::TELEMETRY_SYNC, response.status) + @config.logger.error("Unexpected status code while posting telemetry config: #{response.status}.") + end end def record_stats(stats) @@ -25,7 +37,7 @@ def record_stats(stats) @telemetry_runtime_producer.record_successful_sync(Telemetry::Domain::Constants::TELEMETRY_SYNC, (Time.now.to_f * 1000.0).to_i) else @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::TELEMETRY_SYNC, response.status) - @config.logger.error("Unexpected status code while posting telemetry: #{response.status}.") + @config.logger.error("Unexpected status code while posting telemetry usage: #{response.status}.") end end end diff --git a/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb b/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb index 1e7672c9..ab7d0525 100644 --- a/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +++ b/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb @@ -39,12 +39,13 @@ def synchronize_stats @telemetry_api.record_stats(format_stats(usage)) rescue StandardError => error - p error @config.log_found_exception(__method__.to_s, error) end def synchronize_config(init_config, timed_until_ready, factory_instances, tags) - # implement + + rescue StandardError => error + @config.log_found_exception(__method__.to_s, error) end private From d30356016b8f0d7a2838767402f8c79519565572 Mon Sep 17 00:00:00 2001 From: Mauro Sanz Date: Wed, 26 May 2021 17:55:50 -0300 Subject: [PATCH 2/3] init implementation and tests --- lib/splitclient-rb/split_config.rb | 4 + lib/splitclient-rb/split_factory.rb | 2 +- lib/splitclient-rb/split_factory_registry.rb | 12 + .../telemetry/memory/memory_synchronizer.rb | 81 +++++- .../telemetry/redis/redis_init_producer.rb | 6 +- .../telemetry/redis/redis_synchronizer.rb | 17 +- lib/splitclient-rb/telemetry/synchronizer.rb | 10 +- spec/splitclient/split_factory_spec.rb | 22 ++ spec/telemetry/synchronizer_spec.rb | 238 ++++++++++++------ spec/telemetry/telemetry_init_spec.rb | 6 +- 10 files changed, 304 insertions(+), 94 deletions(-) diff --git a/lib/splitclient-rb/split_config.rb b/lib/splitclient-rb/split_config.rb index 70316e5a..468c3b0a 100644 --- a/lib/splitclient-rb/split_config.rb +++ b/lib/splitclient-rb/split_config.rb @@ -111,6 +111,8 @@ def initialize(opts = {}) @telemetry_refresh_rate = SplitConfig.init_telemetry_refresh_rate(opts[:telemetry_refresh_rate]) @telemetry_service_url = opts[:telemetry_service_url] || SplitConfig.default_telemetry_service_url + @sdk_start_time = Time.now + startup_log end @@ -274,6 +276,8 @@ def initialize(opts = {}) attr_accessor :telemetry_service_url + attr_accessor :sdk_start_time + def self.default_impressions_mode :optimized end diff --git a/lib/splitclient-rb/split_factory.rb b/lib/splitclient-rb/split_factory.rb index e087de42..0efa87b2 100644 --- a/lib/splitclient-rb/split_factory.rb +++ b/lib/splitclient-rb/split_factory.rb @@ -38,7 +38,7 @@ def initialize(api_key, config_hash = {}) @impression_counter = SplitIoClient::Engine::Common::ImpressionCounter.new @impressions_manager = SplitIoClient::Engine::Common::ImpressionManager.new(@config, @impressions_repository, @impression_counter, @runtime_producer) @telemetry_api = SplitIoClient::Api::TelemetryApi.new(@config, @api_key, @runtime_producer) - @telemetry_synchronizer = Telemetry::Synchronizer.new(@config, @telemetry_consumers, @splits_repository, @segments_repository, @telemetry_api) + @telemetry_synchronizer = Telemetry::Synchronizer.new(@config, @telemetry_consumers, @init_producer, repositories, @telemetry_api) start! diff --git a/lib/splitclient-rb/split_factory_registry.rb b/lib/splitclient-rb/split_factory_registry.rb index 859e3015..9e3f7e39 100644 --- a/lib/splitclient-rb/split_factory_registry.rb +++ b/lib/splitclient-rb/split_factory_registry.rb @@ -47,5 +47,17 @@ def number_of_factories_for(api_key) def other_factories return !@api_keys_hash.empty? end + + def active_factories + @api_keys_hash.length + end + + def redundant_active_factories + to_return = 0 + + @api_keys_hash.each { |key| to_return += (key[1]-1) } + + to_return + end end end diff --git a/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb b/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb index ab7d0525..577ba157 100644 --- a/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +++ b/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb @@ -5,15 +5,14 @@ module Telemetry class MemorySynchronizer < Synchronizer def initialize(config, telemtry_consumers, - splits_repository, - segments_repository, + repositories, telemetry_api) @config = config @telemetry_init_consumer = telemtry_consumers[:init] @telemetry_runtime_consumer = telemtry_consumers[:runtime] @telemtry_evaluation_consumer = telemtry_consumers[:evaluation] - @splits_repository = splits_repository - @segments_repository = segments_repository + @splits_repository = repositories[:splits] + @segments_repository = repositories[:segments] @telemetry_api = telemetry_api end @@ -42,14 +41,80 @@ def synchronize_stats @config.log_found_exception(__method__.to_s, error) end - def synchronize_config(init_config, timed_until_ready, factory_instances, tags) - + def synchronize_config(active_factories = nil, redundant_active_factories = nil, time_until_ready = nil) + rates = Rates.new(@config.features_refresh_rate, + @config.segments_refresh_rate, + @config.impressions_refresh_rate, + @config.events_push_rate, + @config.telemetry_refresh_rate) + + url_overrides = UrlOverrides.new(@config.base_uri != SplitConfig.default_base_uri.chomp('/'), + @config.events_uri != SplitConfig.default_events_uri.chomp('/'), + @config.auth_service_url != SplitConfig.default_auth_service_url, + @config.streaming_service_url != SplitConfig.default_streaming_service_url, + @config.telemetry_service_url != SplitConfig.default_telemetry_service_url) + + active_factories ||= SplitIoClient.split_factory_registry.active_factories + redundant_active_factories ||= SplitIoClient.split_factory_registry.redundant_active_factories + + init_config = ConfigInit.new(@config.mode, + 'memory', + active_factories, + redundant_active_factories, + @telemetry_runtime_consumer.pop_tags, + @config.streaming_enabled, + rates, + url_overrides, + @config.impressions_queue_size, + @config.events_queue_size, + @config.impressions_mode, + !@config.impression_listener.nil?, + http_proxy_detected?, + time_until_ready || Time.now - @config.sdk_start_time, + @telemetry_init_consumer.bur_timeouts, + @telemetry_init_consumer.non_ready_usages) + + @telemetry_api.record_init(fornat_init_config(init_config)) rescue StandardError => error @config.log_found_exception(__method__.to_s, error) end private + def fornat_init_config(init) + { + oM: init.om, + sE: init.se, + st: init.st, + rR: { + sp: init.rr.sp, + se: init.rr.se, + im: init.rr.im, + ev: init.rr.ev, + te: init.rr.te + }, + iQ: init.iq, + eQ: init.eq, + iM: init.im, + uO: { + s: init.uo.s, + e: init.uo.e, + a: init.uo.a, + st: init.uo.st, + t: init.uo.t + }, + iL: init.il, + hP: init.hp, + aF: init.af, + rF: init.rf, + tR: init.tr, + bT: init.bt, + nR: init.nr, + t: init.t, + i: init.i + } + end + def format_stats(usage) { lS: usage.ls.to_h, @@ -100,6 +165,10 @@ def format_stats(usage) t: usage.t } end + + def http_proxy_detected? + !ENV['HTTP_PROXY'].nil? || !ENV['HTTPS_PROXY'].nil? + end end end end diff --git a/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb b/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb index 83443ab7..acca24c6 100644 --- a/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +++ b/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb @@ -10,10 +10,10 @@ def initialize(config) def record_config(config_data) return if config_data.nil? - +p config_data data = { m: { i: @config.machine_ip, n: @config.machine_name, s: "#{@config.language}-#{@config.version}" }, - t: { om: config_data.om, st: config_data.st, af: config_data.af, rf: config_data.rf, t: config_data.t } } - + t: { oM: config_data.om, st: config_data.st, aF: config_data.af, rF: config_data.rf, t: config_data.t } } +p data.to_json @adapter.add_to_queue(config_key, data.to_json) rescue StandardError => error @config.log_found_exception(__method__.to_s, error) diff --git a/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb b/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb index a031b3c4..d8c2297a 100644 --- a/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb +++ b/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb @@ -3,16 +3,25 @@ module SplitIoClient module Telemetry class RedisSynchronizer < Synchronizer - def initialize(telemetry_init_consumer) - @telemetry_init_consumer = telemetry_init_consumer + def initialize(config, + telemetry_init_producer) + @config = config + @telemetry_init_producer = telemetry_init_producer end def synchronize_stats # No-op end - def synchronize_config(init_config, timed_until_ready, factory_instances, tags) - # implement + def synchronize_config(active_factories = nil, redundant_active_factories = nil, tags = nil) + active_factories ||= SplitIoClient.split_factory_registry.active_factories + redundant_active_factories ||= SplitIoClient.split_factory_registry.redundant_active_factories + + init_config = ConfigInit.new(@config.mode, 'redis', active_factories, redundant_active_factories, tags) + + @telemetry_init_producer.record_config(init_config) + rescue StandardError => error + @config.log_found_exception(__method__.to_s, error) end end end diff --git a/lib/splitclient-rb/telemetry/synchronizer.rb b/lib/splitclient-rb/telemetry/synchronizer.rb index b1bcceb7..723e8f8e 100644 --- a/lib/splitclient-rb/telemetry/synchronizer.rb +++ b/lib/splitclient-rb/telemetry/synchronizer.rb @@ -10,17 +10,17 @@ class Synchronizer def initialize(config, telemtry_consumers, - splits_repository, - segments_repository, + telemetry_init_producer, + repositories, telemetry_api) @synchronizer = case config.telemetry_adapter.class.to_s when 'SplitIoClient::Cache::Adapters::RedisAdapter' - SplitIoClient::Telemetry::RedisSynchronizer.new(telemtry_consumers[:init]) + SplitIoClient::Telemetry::RedisSynchronizer.new(config, + telemetry_init_producer) else SplitIoClient::Telemetry::MemorySynchronizer.new(config, telemtry_consumers, - splits_repository, - segments_repository, + repositories, telemetry_api) end end diff --git a/spec/splitclient/split_factory_spec.rb b/spec/splitclient/split_factory_spec.rb index 2c3c0b84..361dfca6 100644 --- a/spec/splitclient/split_factory_spec.rb +++ b/spec/splitclient/split_factory_spec.rb @@ -180,5 +180,27 @@ expect(SplitIoClient.split_factory_registry.number_of_factories_for('API_KEY')).to eq 0 end + + it 'active and redundant factories' do + stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + .to_return(status: 200, body: []) + + described_class.new('API_KEY', options) + + described_class.new('ANOTHER_API_KEY', options) + described_class.new('ANOTHER_API_KEY', options) + + described_class.new('ANOTHER_API_KEY-2', options) + described_class.new('ANOTHER_API_KEY-2', options) + described_class.new('ANOTHER_API_KEY-2', options) + + described_class.new('API_KEY-2', options) + described_class.new('API_KEY-2', options) + described_class.new('API_KEY-2', options) + described_class.new('API_KEY-2', options) + + expect(SplitIoClient.split_factory_registry.active_factories).to be(4) + expect(SplitIoClient.split_factory_registry.redundant_active_factories).to be(6) + end end end diff --git a/spec/telemetry/synchronizer_spec.rb b/spec/telemetry/synchronizer_spec.rb index 232be56a..87864852 100644 --- a/spec/telemetry/synchronizer_spec.rb +++ b/spec/telemetry/synchronizer_spec.rb @@ -5,6 +5,31 @@ describe SplitIoClient::Telemetry::Synchronizer do let(:log) { StringIO.new } + context 'Redis' do + let(:config) { SplitIoClient::SplitConfig.new(logger: Logger.new(log), cache_adapter: :redis, mode: :consumer) } + let(:adapter) { config.telemetry_adapter } + let(:init_producer) { SplitIoClient::Telemetry::InitProducer.new(config) } + let(:synchronizer) { SplitIoClient::Telemetry::Synchronizer.new(config, nil, init_producer, nil, nil) } + let(:config_key) { 'SPLITIO.telemetry.config' } + + it 'synchronize_config with data' do + adapter.redis.del(config_key) + synchronizer.synchronize_config(5, 1, ['tag-1']) + + result = JSON.parse(adapter.redis.lrange(config_key, 0, -1)[0], symbolize_names: true) + + expect(result[:m][:i]).to eq(config.machine_ip) + expect(result[:m][:n]).to eq(config.machine_name) + expect(result[:m][:s]).to eq("#{config.language}-#{config.version}") + + expect(result[:t][:oM]).to eq('consumer') + expect(result[:t][:st]).to eq('redis') + expect(result[:t][:aF]).to eq(5) + expect(result[:t][:rF]).to eq(1) + expect(result[:t][:t]).to eq(%w[tag-1]) + end + end + context 'Memory' do let(:config) { SplitIoClient::SplitConfig.new(logger: Logger.new(log)) } let(:evaluation_consumer) { SplitIoClient::Telemetry::EvaluationConsumer.new(config) } @@ -15,88 +40,157 @@ let(:api_key) { 'api-key-test' } let(:runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } let(:evaluation_producer) { SplitIoClient::Telemetry::EvaluationProducer.new(config) } + let(:init_producer) { SplitIoClient::Telemetry::InitProducer.new(config) } let(:telemetry_api) { SplitIoClient::Api::TelemetryApi.new(config, api_key, runtime_producer) } let(:telemetry_consumers) do { init: init_consumer, runtime: runtime_consumer, evaluation: evaluation_consumer } end let(:body_usage) { "{\"lS\":{\"sp\":111111222,\"se\":111111222,\"im\":111111222,\"ic\":111111222,\"ev\":111111222,\"te\":111111222,\"to\":111111222},\"mL\":{\"t\":[1,3,2,1],\"ts\":[2,3],\"tc\":[],\"tcs\":[],\"tr\":[3]},\"mE\":{\"t\":2,\"ts\":1,\"tc\":1,\"tcs\":0,\"tr\":1},\"hE\":{\"sp\":[],\"se\":[{\"400\":1}],\"im\":[],\"ic\":[],\"ev\":[{\"500\":2},{\"501\":1}],\"te\":[],\"to\":[]},\"hL\":{\"sp\":[6],\"se\":[],\"im\":[],\"ic\":[],\"ev\":[2,1],\"te\":[],\"to\":[]},\"tR\":1,\"aR\":1,\"iQ\":3,\"iDe\":1,\"iDr\":2,\"spC\":3,\"seC\":3,\"skC\":7,\"sL\":444555,\"eQ\":4,\"eD\":1,\"sE\":[{\"e\":\"token_refresh\",\"d\":222222333,\"t\":222222333},{\"e\":\"sync_mode\",\"d\":0,\"t\":222222333},{\"e\":\"sync_mode\",\"d\":1,\"t\":222222333}],\"t\":[\"tag-1\",\"tag-2\"]}" } - let(:empty_body_usage) { "{\"lS\":{\"sp\":0,\"se\":0,\"im\":0,\"ic\":0,\"ev\":0,\"te\":0,\"to\":0},\"mL\":{\"t\":[],\"ts\":[],\"tc\":[],\"tcs\":[],\"tr\":[]},\"mE\":{\"t\":0,\"ts\":0,\"tc\":0,\"tcs\":0,\"tr\":0},\"hE\":{\"sp\":[],\"se\":[],\"im\":[],\"ic\":[],\"ev\":[],\"te\":[],\"to\":[]},\"hL\":{\"sp\":[],\"se\":[],\"im\":[],\"ic\":[],\"ev\":[],\"te\":[],\"to\":[]},\"tR\":0,\"aR\":0,\"iQ\":0,\"iDe\":0,\"iDr\":0,\"spC\":0,\"seC\":0,\"skC\":0,\"sL\":0,\"eQ\":0,\"eD\":0,\"sE\":[],\"t\":[]}" } - let(:synchronizer) do - SplitIoClient::Telemetry::Synchronizer.new(config, - telemetry_consumers, - splits_repository, - segments_repository, - telemetry_api) - end + let(:empty_body_usage) { "{\"lS\":{\"sp\":0,\"se\":0,\"im\":0,\"ic\":0,\"ev\":0,\"te\":0,\"to\":0},\"mL\":{\"t\":[],\"ts\":[],\"tc\":[],\"tcs\":[],\"tr\":[]},\"mE\":{\"t\":0,\"ts\":0,\"tc\":0,\"tcs\":0,\"tr\":0},\"hE\":{\"sp\":[],\"se\":[],\"im\":[],\"ic\":[],\"ev\":[],\"te\":[],\"to\":[]},\"hL\":{\"sp\":[],\"se\":[],\"im\":[],\"ic\":[],\"ev\":[],\"te\":[],\"to\":[]},\"tR\":0,\"aR\":0,\"iQ\":0,\"iDe\":0,\"iDr\":0,\"spC\":0,\"seC\":0,\"skC\":0,\"sL\":0,\"eQ\":0,\"eD\":0,\"sE\":[],\"t\":[]}" } + let(:body_custom_config) { "{\"oM\":\"standalone\",\"sE\":true,\"st\":\"memory\",\"rR\":{\"sp\":100,\"se\":110,\"im\":120,\"ev\":130,\"te\":140},\"iQ\":5000,\"eQ\":500,\"iM\":\"optimized\",\"uO\":{\"s\":true,\"e\":true,\"a\":true,\"st\":false,\"t\":false},\"iL\":false,\"hP\":false,\"aF\":1,\"rF\":1,\"tR\":100,\"bT\":2,\"nR\":1,\"t\":[],\"i\":null}" } + let(:body_default_config) { "{\"oM\":\"standalone\",\"sE\":true,\"st\":\"memory\",\"rR\":{\"sp\":5,\"se\":60,\"im\":300,\"ev\":60,\"te\":3600},\"iQ\":5000,\"eQ\":500,\"iM\":\"optimized\",\"uO\":{\"s\":false,\"e\":false,\"a\":false,\"st\":false,\"t\":false},\"iL\":false,\"hP\":false,\"aF\":1,\"rF\":1,\"tR\":500,\"bT\":0,\"nR\":0,\"t\":[],\"i\":null}" } + let(:body_proxy_config) { "{\"oM\":\"standalone\",\"sE\":true,\"st\":\"memory\",\"rR\":{\"sp\":5,\"se\":60,\"im\":300,\"ev\":60,\"te\":3600},\"iQ\":5000,\"eQ\":500,\"iM\":\"optimized\",\"uO\":{\"s\":false,\"e\":false,\"a\":false,\"st\":false,\"t\":false},\"iL\":false,\"hP\":true,\"aF\":1,\"rF\":1,\"tR\":500,\"bT\":0,\"nR\":0,\"t\":[],\"i\":null}" } + + context 'synchronize_stats' do + before do + stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') + .to_return(status: 200, body: 'ok') + end + + let(:synchronizer) do + SplitIoClient::Telemetry::Synchronizer.new(config, + telemetry_consumers, + init_producer, + { splits: splits_repository, segments: segments_repository }, + telemetry_api) + end + + it 'with data' do + splits_repository.add_split(name: 'foo', trafficTypeName: 'tt_name_1') + splits_repository.add_split(name: 'bar', trafficTypeName: 'tt_name_2') + splits_repository.add_split(name: 'baz', trafficTypeName: 'tt_name_1') + + segments_repository.add_to_segment(name: 'foo-1', added: [1, 2, 3], removed: []) + segments_repository.add_to_segment(name: 'foo-2', added: [1, 2, 3, 4], removed: []) + segments_repository.add_to_segment(name: 'foo-3', added: [], removed: []) - it 'synchronize_stats with data' do - stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') - .to_return(status: 200, body: 'ok') - - splits_repository.add_split(name: 'foo', trafficTypeName: 'tt_name_1') - splits_repository.add_split(name: 'bar', trafficTypeName: 'tt_name_2') - splits_repository.add_split(name: 'baz', trafficTypeName: 'tt_name_1') - - segments_repository.add_to_segment(name: 'foo-1', added: [1, 2, 3], removed: []) - segments_repository.add_to_segment(name: 'foo-2', added: [1, 2, 3, 4], removed: []) - segments_repository.add_to_segment(name: 'foo-3', added: [], removed: []) - - splits_repository.set_segment_names(['foo-1', 'foo-2', 'foo-3']) - - runtime_producer.add_tag('tag-1') - runtime_producer.add_tag('tag-2') - runtime_producer.record_impressions_stats(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_QUEUED, 3) - runtime_producer.record_impressions_stats(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_DROPPED, 2) - runtime_producer.record_impressions_stats(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_DEDUPE, 1) - runtime_producer.record_events_stats(SplitIoClient::Telemetry::Domain::Constants::EVENTS_QUEUED, 4) - runtime_producer.record_events_stats(SplitIoClient::Telemetry::Domain::Constants::EVENTS_DROPPED, 1) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 111_111_222) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::SPLIT_SYNC, 111_111_222) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::SEGMENT_SYNC, 111_111_222) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_SYNC, 111_111_222) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::IMPRESSION_COUNT_SYNC, 111_111_222) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::TELEMETRY_SYNC, 111_111_222) - runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::TOKEN_SYNC, 111_111_222) - runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 500) - runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 501) - runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 500) - runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::SEGMENT_SYNC, 400) - runtime_producer.record_sync_latency(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 2) - runtime_producer.record_sync_latency(SplitIoClient::Telemetry::Domain::Constants::SPLIT_SYNC, 6) - runtime_producer.record_sync_latency(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 1) - runtime_producer.record_auth_rejections - runtime_producer.record_token_refreshes - runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::TOKEN_REFRESH, 222_222_333, 222_222_333) - runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::SYNC_MODE, 0, 222_222_333) - runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::SYNC_MODE, 1, 222_222_333) - runtime_producer.record_session_length(444_555) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 1) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 3) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 2) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 1) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENTS, 2) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENTS, 3) - evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TRACK, 3) - evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENT) - evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENT) - evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENTS) - evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TRACK) - evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENT_WITH_CONFIG) - - synchronizer.synchronize_stats - - expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') - .with(body: body_usage)).to have_been_made + splits_repository.set_segment_names(['foo-1', 'foo-2', 'foo-3']) + + runtime_producer.add_tag('tag-1') + runtime_producer.add_tag('tag-2') + runtime_producer.record_impressions_stats(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_QUEUED, 3) + runtime_producer.record_impressions_stats(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_DROPPED, 2) + runtime_producer.record_impressions_stats(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_DEDUPE, 1) + runtime_producer.record_events_stats(SplitIoClient::Telemetry::Domain::Constants::EVENTS_QUEUED, 4) + runtime_producer.record_events_stats(SplitIoClient::Telemetry::Domain::Constants::EVENTS_DROPPED, 1) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 111_111_222) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::SPLIT_SYNC, 111_111_222) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::SEGMENT_SYNC, 111_111_222) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::IMPRESSIONS_SYNC, 111_111_222) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::IMPRESSION_COUNT_SYNC, 111_111_222) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::TELEMETRY_SYNC, 111_111_222) + runtime_producer.record_successful_sync(SplitIoClient::Telemetry::Domain::Constants::TOKEN_SYNC, 111_111_222) + runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 500) + runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 501) + runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 500) + runtime_producer.record_sync_error(SplitIoClient::Telemetry::Domain::Constants::SEGMENT_SYNC, 400) + runtime_producer.record_sync_latency(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 2) + runtime_producer.record_sync_latency(SplitIoClient::Telemetry::Domain::Constants::SPLIT_SYNC, 6) + runtime_producer.record_sync_latency(SplitIoClient::Telemetry::Domain::Constants::EVENT_SYNC, 1) + runtime_producer.record_auth_rejections + runtime_producer.record_token_refreshes + runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::TOKEN_REFRESH, 222_222_333, 222_222_333) + runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::SYNC_MODE, 0, 222_222_333) + runtime_producer.record_streaming_event(SplitIoClient::Telemetry::Domain::Constants::SYNC_MODE, 1, 222_222_333) + runtime_producer.record_session_length(444_555) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 1) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 3) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 2) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENT, 1) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENTS, 2) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TREATMENTS, 3) + evaluation_producer.record_latency(SplitIoClient::Telemetry::Domain::Constants::TRACK, 3) + evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENT) + evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENT) + evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENTS) + evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TRACK) + evaluation_producer.record_exception(SplitIoClient::Telemetry::Domain::Constants::TREATMENT_WITH_CONFIG) + + synchronizer.synchronize_stats + + expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') + .with(body: body_usage)).to have_been_made + end + + it 'without data' do + synchronizer.synchronize_stats + + expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') + .with(body: empty_body_usage)).to have_been_made + end end - it 'synchronize_stats without data' do - stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') - .to_return(status: 200, body: 'ok') + context 'synchronize_config' do + before do + stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') + .to_return(status: 200, body: 'ok') + + SplitIoClient.load_factory_registry + end + + it 'with custom data' do + config.features_refresh_rate = 100 + config.segments_refresh_rate = 110 + config.impressions_refresh_rate = 120 + config.events_push_rate = 130 + config.telemetry_refresh_rate = 140 + config.base_uri = 'https://sdk.test.io/api/' + config.events_uri = 'https://events.test.io/api/' + config.auth_service_url = 'https://auth.test.io/api/auth' + + init_producer.record_bur_timeout + init_producer.record_bur_timeout + init_producer.record_non_ready_usages + + synchronizer = SplitIoClient::Telemetry::Synchronizer.new(config, + telemetry_consumers, + init_producer, + { splits: splits_repository, segments: segments_repository }, + telemetry_api) + + synchronizer.synchronize_config(1, 1, 100) + + expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') + .with(body: body_custom_config)).to have_been_made + end + + it 'with default data' do + synchronizer = SplitIoClient::Telemetry::Synchronizer.new(config, + telemetry_consumers, + init_producer, + { splits: splits_repository, segments: segments_repository }, + telemetry_api) + + synchronizer.synchronize_config(1, 1, 500) + + expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') + .with(body: body_default_config)).to have_been_made + end + + it 'with proxy' do + ENV['HTTPS_PROXY'] = 'https://proxy.test.io/api/v1/metrics/config' + + synchronizer = SplitIoClient::Telemetry::Synchronizer.new(config, + telemetry_consumers, + init_producer, + { splits: splits_repository, segments: segments_repository }, + telemetry_api) - synchronizer.synchronize_stats + synchronizer.synchronize_config(1, 1, 500) - expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') - .with(body: empty_body_usage)).to have_been_made + expect(a_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') + .with(body: body_proxy_config)).to have_been_made + end end end end diff --git a/spec/telemetry/telemetry_init_spec.rb b/spec/telemetry/telemetry_init_spec.rb index a4d05ad3..da9ccf6b 100644 --- a/spec/telemetry/telemetry_init_spec.rb +++ b/spec/telemetry/telemetry_init_spec.rb @@ -71,10 +71,10 @@ expect(result[:m][:n]).to eq(config.machine_name) expect(result[:m][:s]).to eq("#{config.language}-#{config.version}") - expect(result[:t][:om]).to eq('CONSUMER') + expect(result[:t][:oM]).to eq('CONSUMER') expect(result[:t][:st]).to eq('REDIS') - expect(result[:t][:af]).to eq(1) - expect(result[:t][:rf]).to eq(0) + expect(result[:t][:aF]).to eq(1) + expect(result[:t][:rF]).to eq(0) expect(result[:t][:t]).to eq(%w[t1 t2]) end From 636c2a9767a885dff581a3cbace80e5056142ab0 Mon Sep 17 00:00:00 2001 From: Mauro Sanz Date: Wed, 26 May 2021 17:58:49 -0300 Subject: [PATCH 3/3] fixed rubocop --- .rubocop.yml | 2 ++ lib/splitclient-rb/telemetry/redis/redis_init_producer.rb | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 9f355616..5fb0085e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -13,6 +13,8 @@ Metrics/MethodLength: Metrics/ClassLength: Max: 150 + Exclude: + - lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb Metrics/CyclomaticComplexity: Max: 8 diff --git a/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb b/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb index acca24c6..841a3c48 100644 --- a/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +++ b/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb @@ -10,10 +10,10 @@ def initialize(config) def record_config(config_data) return if config_data.nil? -p config_data + data = { m: { i: @config.machine_ip, n: @config.machine_name, s: "#{@config.language}-#{@config.version}" }, t: { oM: config_data.om, st: config_data.st, aF: config_data.af, rF: config_data.rf, t: config_data.t } } -p data.to_json + @adapter.add_to_queue(config_key, data.to_json) rescue StandardError => error @config.log_found_exception(__method__.to_s, error)