diff options
Diffstat (limited to 'spec/lib/gitlab/instrumentation')
4 files changed, 165 insertions, 3 deletions
diff --git a/spec/lib/gitlab/instrumentation/redis_base_spec.rb b/spec/lib/gitlab/instrumentation/redis_base_spec.rb index 5ea8f00114e..07be0ccf6e9 100644 --- a/spec/lib/gitlab/instrumentation/redis_base_spec.rb +++ b/spec/lib/gitlab/instrumentation/redis_base_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Instrumentation::RedisBase, :request_store do +RSpec.describe Gitlab::Instrumentation::RedisBase, :request_store do let(:instrumentation_class_a) do stub_const('InstanceA', Class.new(described_class)) end diff --git a/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb b/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb new file mode 100644 index 00000000000..2ca7465e775 --- /dev/null +++ b/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require 'support/helpers/rails_helpers' +require 'rspec-parameterized' + +RSpec.describe Gitlab::Instrumentation::RedisClusterValidator do + include RailsHelpers + + describe '.validate!' do + using RSpec::Parameterized::TableSyntax + + context 'Rails environments' do + where(:env, :should_raise) do + 'production' | false + 'staging' | false + 'development' | true + 'test' | true + end + + with_them do + it do + stub_rails_env(env) + + args = [:mget, 'foo', 'bar'] + + if should_raise + expect { described_class.validate!(args) } + .to raise_error(described_class::CrossSlotError) + else + expect { described_class.validate!(args) }.not_to raise_error + end + end + end + end + + where(:command, :arguments, :should_raise) do + :rename | %w(foo bar) | true + :RENAME | %w(foo bar) | true + 'rename' | %w(foo bar) | true + 'RENAME' | %w(foo bar) | true + :rename | %w(iaa ahy) | false # 'iaa' and 'ahy' hash to the same slot + :rename | %w({foo}:1 {foo}:2) | false + :rename | %w(foo foo bar) | false # This is not a valid command but should not raise here + :mget | %w(foo bar) | true + :mget | %w(foo foo bar) | true + :mget | %w(foo foo) | false + :blpop | %w(foo bar 1) | true + :blpop | %w(foo foo 1) | false + :mset | %w(foo a bar a) | true + :mset | %w(foo a foo a) | false + :del | %w(foo bar) | true + :del | [%w(foo bar)] | true # Arguments can be a nested array + :del | %w(foo foo) | false + :hset | %w(foo bar) | false # Not a multi-key command + end + + with_them do + it do + args = [command] + arguments + + if should_raise + expect { described_class.validate!(args) } + .to raise_error(described_class::CrossSlotError) + else + expect { described_class.validate!(args) }.not_to raise_error + end + end + end + end + + describe '.allow_cross_slot_commands' do + it 'does not raise for invalid arguments' do + expect do + described_class.allow_cross_slot_commands do + described_class.validate!([:mget, 'foo', 'bar']) + end + end.not_to raise_error + end + + it 'allows nested invocation' do + expect do + described_class.allow_cross_slot_commands do + described_class.allow_cross_slot_commands do + described_class.validate!([:mget, 'foo', 'bar']) + end + + described_class.validate!([:mget, 'foo', 'bar']) + end + end.not_to raise_error + end + end +end diff --git a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb index 25506d63091..5b0ad63ee72 100644 --- a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb +++ b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'rspec-parameterized' -describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_shared_state, :request_store do +RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_shared_state, :request_store do using RSpec::Parameterized::TableSyntax describe 'read and write' do @@ -42,4 +42,73 @@ describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_shared_s end end end + + describe 'counting' do + let(:instrumentation_class) { Gitlab::Redis::SharedState.instrumentation_class } + + it 'counts successful requests' do + expect(instrumentation_class).to receive(:instance_count_request).and_call_original + + Gitlab::Redis::SharedState.with { |redis| redis.call(:get, 'foobar') } + end + + it 'counts exceptions' do + expect(instrumentation_class).to receive(:instance_count_exception) + .with(instance_of(Redis::CommandError)).and_call_original + expect(instrumentation_class).to receive(:instance_count_request).and_call_original + + expect do + Gitlab::Redis::SharedState.with do |redis| + redis.call(:auth, 'foo', 'bar') + end + end.to raise_exception(Redis::CommandError) + end + end + + describe 'latency' do + let(:instrumentation_class) { Gitlab::Redis::SharedState.instrumentation_class } + + describe 'commands in the apdex' do + where(:command) do + [ + [[:get, 'foobar']], + [%w[GET foobar]] + ] + end + + with_them do + it 'measures requests we want in the apdex' do + expect(instrumentation_class).to receive(:instance_observe_duration).with(a_value > 0) + .and_call_original + + Gitlab::Redis::SharedState.with { |redis| redis.call(*command) } + end + end + end + + describe 'commands not in the apdex' do + where(:command) do + [ + [%w[brpop foobar 0.01]], + [%w[blpop foobar 0.01]], + [%w[brpoplpush foobar bazqux 0.01]], + [%w[bzpopmin foobar 0.01]], + [%w[bzpopmax foobar 0.01]], + [%w[xread block 1 streams mystream 0-0]], + [%w[xreadgroup group mygroup myconsumer block 1 streams foobar 0-0]] + ] + end + + with_them do + it 'skips requests we do not want in the apdex' do + expect(instrumentation_class).not_to receive(:instance_observe_duration) + + begin + Gitlab::Redis::SharedState.with { |redis| redis.call(*command) } + rescue Gitlab::Instrumentation::RedisClusterValidator::CrossSlotError, ::Redis::CommandError + end + end + end + end + end end diff --git a/spec/lib/gitlab/instrumentation/redis_spec.rb b/spec/lib/gitlab/instrumentation/redis_spec.rb index 8311c4f5bbb..e927f39cae2 100644 --- a/spec/lib/gitlab/instrumentation/redis_spec.rb +++ b/spec/lib/gitlab/instrumentation/redis_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Instrumentation::Redis do +RSpec.describe Gitlab::Instrumentation::Redis do def stub_storages(method, value) described_class::STORAGES.each do |storage| allow(storage).to receive(method) { value } |