summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/instrumentation
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/instrumentation')
-rw-r--r--spec/lib/gitlab/instrumentation/redis_base_spec.rb2
-rw-r--r--spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb93
-rw-r--r--spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb71
-rw-r--r--spec/lib/gitlab/instrumentation/redis_spec.rb2
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 }