diff options
Diffstat (limited to 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb')
-rw-r--r-- | spec/lib/gitlab/metrics/subscribers/active_record_spec.rb | 233 |
1 files changed, 149 insertions, 84 deletions
diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb index a78d048908d..2fd5dd1d83b 100644 --- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Metrics::Subscribers::ActiveRecord do +RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do let(:env) { {} } let(:transaction) { Gitlab::Metrics::WebTransaction.new(env) } let(:subscriber) { described_class.new } @@ -28,60 +28,45 @@ describe Gitlab::Metrics::Subscribers::ActiveRecord do end describe 'with a current transaction' do - shared_examples 'read only query' do - it 'increments only db count value' do + shared_examples 'track executed query' do + before do allow(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) - - expect(transaction).to receive(:increment) - .with(:db_count, 1) - - expect(transaction).not_to receive(:increment) - .with(:db_cached_count, 1) - - expect(transaction).not_to receive(:increment) - .with(:db_write_count, 1) - - subscriber.sql(event) + .at_least(:once) + .and_return(transaction) end - end - - shared_examples 'write query' do - it 'increments db_write_count and db_count value' do - expect(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) - expect(transaction).to receive(:increment) - .with(:db_count, 1) - - expect(transaction).not_to receive(:increment) - .with(:db_cached_count, 1) - - expect(transaction).to receive(:increment) - .with(:db_write_count, 1) + it 'increments only db count value' do + described_class::DB_COUNTERS.each do |counter| + if expected_counters[counter] > 0 + expect(transaction).to receive(:increment).with(counter, 1) + else + expect(transaction).not_to receive(:increment).with(counter, 1) + end + end subscriber.sql(event) end - end - shared_examples 'cached query' do - it 'increments db_cached_count and db_count value' do - expect(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) - - expect(transaction).to receive(:increment) - .with(:db_count, 1) - - expect(transaction).to receive(:increment) - .with(:db_cached_count, 1) - - expect(transaction).not_to receive(:increment) - .with(:db_write_count, 1) - - subscriber.sql(event) + context 'when RequestStore is enabled' do + it 'caches db count value', :request_store, :aggregate_failures do + subscriber.sql(event) + + described_class::DB_COUNTERS.each do |counter| + expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] + end + end + + it 'prevents db counters from leaking to the next transaction' do + 2.times do + Gitlab::WithRequestStore.with_request_store do + subscriber.sql(event) + + described_class::DB_COUNTERS.each do |counter| + expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] + end + end + end + end end end @@ -93,66 +78,96 @@ describe Gitlab::Metrics::Subscribers::ActiveRecord do subscriber.sql(event) end - it_behaves_like 'read only query' + context 'with read query' do + let(:expected_counters) do + { + db_count: 1, + db_write_count: 0, + db_cached_count: 0 + } + end + + it_behaves_like 'track executed query' - context 'with select for update sql event' do - let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10 FOR UPDATE' } } + context 'with only select' do + let(:payload) { { sql: 'WITH active_milestones AS (SELECT COUNT(*), state FROM milestones GROUP BY state) SELECT * FROM active_milestones' } } - it_behaves_like 'write query' + it_behaves_like 'track executed query' + end end - context 'with common table expression' do - context 'with insert' do - let(:payload) { { sql: 'WITH archived_rows AS (SELECT * FROM users WHERE archived = true) INSERT INTO products_log SELECT * FROM archived_rows' } } + context 'write query' do + let(:expected_counters) do + { + db_count: 1, + db_write_count: 1, + db_cached_count: 0 + } + end + + context 'with select for update sql event' do + let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10 FOR UPDATE' } } - it_behaves_like 'write query' + it_behaves_like 'track executed query' end - context 'with only select' do - let(:payload) { { sql: 'WITH active_milestones AS (SELECT COUNT(*), state FROM milestones GROUP BY state) SELECT * FROM active_milestones' } } + context 'with common table expression' do + context 'with insert' do + let(:payload) { { sql: 'WITH archived_rows AS (SELECT * FROM users WHERE archived = true) INSERT INTO products_log SELECT * FROM archived_rows' } } - it_behaves_like 'read only query' + it_behaves_like 'track executed query' + end end - end - context 'with delete sql event' do - let(:payload) { { sql: 'DELETE FROM users where id = 10' } } + context 'with delete sql event' do + let(:payload) { { sql: 'DELETE FROM users where id = 10' } } - it_behaves_like 'write query' - end + it_behaves_like 'track executed query' + end - context 'with insert sql event' do - let(:payload) { { sql: 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' } } + context 'with insert sql event' do + let(:payload) { { sql: 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' } } - it_behaves_like 'write query' - end + it_behaves_like 'track executed query' + end - context 'with update sql event' do - let(:payload) { { sql: 'UPDATE users SET admin = true WHERE id = 10' } } + context 'with update sql event' do + let(:payload) { { sql: 'UPDATE users SET admin = true WHERE id = 10' } } - it_behaves_like 'write query' + it_behaves_like 'track executed query' + end end - context 'with cached payload ' do - let(:payload) do + context 'with cached query' do + let(:expected_counters) do { - sql: 'SELECT * FROM users WHERE id = 10', - cached: true + db_count: 1, + db_write_count: 0, + db_cached_count: 1 } end - it_behaves_like 'cached query' - end + context 'with cached payload ' do + let(:payload) do + { + sql: 'SELECT * FROM users WHERE id = 10', + cached: true + } + end - context 'with cached payload name' do - let(:payload) do - { - sql: 'SELECT * FROM users WHERE id = 10', - name: 'CACHE' - } + it_behaves_like 'track executed query' end - it_behaves_like 'cached query' + context 'with cached payload name' do + let(:payload) do + { + sql: 'SELECT * FROM users WHERE id = 10', + name: 'CACHE' + } + end + + it_behaves_like 'track executed query' + end end context 'events are internal to Rails or irrelevant' do @@ -215,4 +230,54 @@ describe Gitlab::Metrics::Subscribers::ActiveRecord do end end end + + describe 'self.db_counter_payload' do + before do + allow(subscriber).to receive(:current_transaction) + .at_least(:once) + .and_return(transaction) + end + + context 'when RequestStore is enabled', :request_store do + context 'when query is executed' do + let(:expected_payload) do + { + db_count: 1, + db_cached_count: 0, + db_write_count: 0 + } + end + + it 'returns correct payload' do + subscriber.sql(event) + + expect(described_class.db_counter_payload).to eq(expected_payload) + end + end + + context 'when query is not executed' do + let(:expected_payload) do + { + db_count: 0, + db_cached_count: 0, + db_write_count: 0 + } + end + + it 'returns correct payload' do + expect(described_class.db_counter_payload).to eq(expected_payload) + end + end + end + + context 'when RequestStore is disabled' do + let(:expected_payload) { {} } + + it 'returns empty payload' do + subscriber.sql(event) + + expect(described_class.db_counter_payload).to eq(expected_payload) + end + end + end end |