diff options
Diffstat (limited to 'spec/lib/gitlab/metrics')
-rw-r--r-- | spec/lib/gitlab/metrics/background_transaction_spec.rb | 56 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb | 66 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/subscribers/active_record_spec.rb | 119 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/transaction_spec.rb | 8 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/web_transaction_spec.rb | 6 |
5 files changed, 75 insertions, 180 deletions
diff --git a/spec/lib/gitlab/metrics/background_transaction_spec.rb b/spec/lib/gitlab/metrics/background_transaction_spec.rb deleted file mode 100644 index b2a53fe1626..00000000000 --- a/spec/lib/gitlab/metrics/background_transaction_spec.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Metrics::BackgroundTransaction do - let(:test_worker_class) { double(:class, name: 'TestWorker') } - let(:prometheus_metric) { instance_double(Prometheus::Client::Metric, base_labels: {}) } - - before do - allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric) - end - - subject { described_class.new(test_worker_class) } - - RSpec.shared_examples 'metric with worker labels' do |metric_method| - it 'measures with correct labels and value' do - value = 1 - expect(prometheus_metric).to receive(metric_method).with({ controller: 'TestWorker', action: 'perform', feature_category: '' }, value) - - subject.send(metric_method, :bau, value) - end - end - - describe '#label' do - it 'returns labels based on class name' do - expect(subject.labels).to eq(controller: 'TestWorker', action: 'perform', feature_category: '') - end - - it 'contains only the labels defined for metrics' do - expect(subject.labels.keys).to contain_exactly(*described_class.superclass::BASE_LABEL_KEYS) - end - - it 'includes the feature category if there is one' do - expect(test_worker_class).to receive(:get_feature_category).and_return('source_code_management') - expect(subject.labels).to include(feature_category: 'source_code_management') - end - end - - describe '#increment' do - let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, :increment, base_labels: {}) } - - it_behaves_like 'metric with worker labels', :increment - end - - describe '#set' do - let(:prometheus_metric) { instance_double(Prometheus::Client::Gauge, :set, base_labels: {}) } - - it_behaves_like 'metric with worker labels', :set - end - - describe '#observe' do - let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, :observe, base_labels: {}) } - - it_behaves_like 'metric with worker labels', :observe - end -end diff --git a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb deleted file mode 100644 index 047d1e5d205..00000000000 --- a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Metrics::SidekiqMiddleware do - let(:middleware) { described_class.new } - let(:message) { { 'args' => ['test'], 'enqueued_at' => Time.new(2016, 6, 23, 6, 59).to_f } } - - describe '#call' do - it 'tracks the transaction' do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - expect_next_instance_of(Gitlab::Metrics::BackgroundTransaction) do |transaction| - expect(transaction).to receive(:set).with(:gitlab_transaction_sidekiq_queue_duration_total, instance_of(Float)) - expect(transaction).to receive(:increment).with(:gitlab_transaction_db_count_total, 1) - end - - middleware.call(worker, message, :test) do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - end - end - - it 'prevents database counters from leaking to the next transaction' do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - 2.times do - Gitlab::WithRequestStore.with_request_store do - middleware.call(worker, message, :test) do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - end - end - end - - expect(message).to include(db_count: 1, db_write_count: 0, db_cached_count: 0) - end - - it 'tracks the transaction (for messages without `enqueued_at`)', :aggregate_failures do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - expect(Gitlab::Metrics::BackgroundTransaction).to receive(:new) - .with(worker.class) - .and_call_original - - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) - .with(:gitlab_transaction_sidekiq_queue_duration_total, instance_of(Float)) - - middleware.call(worker, {}, :test) { nil } - end - - it 'tracks any raised exceptions', :aggregate_failures, :request_store do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - expect_any_instance_of(Gitlab::Metrics::Transaction) - .to receive(:add_event).with(:sidekiq_exception) - - expect do - middleware.call(worker, message, :test) do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - raise RuntimeError - end - end.to raise_error(RuntimeError) - - expect(message).to include(db_count: 1, db_write_count: 0, db_cached_count: 0) - end - end -end diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb index a31686b8061..edcd5b31941 100644 --- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb @@ -18,59 +18,73 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do end describe '#sql' do - describe 'without a current transaction' do - it 'simply returns' do - expect_any_instance_of(Gitlab::Metrics::Transaction) - .not_to receive(:increment) + shared_examples 'track query in metrics' do + before do + allow(subscriber).to receive(:current_transaction) + .at_least(:once) + .and_return(transaction) + end + + it 'increments only db count value' do + described_class::DB_COUNTERS.each do |counter| + prometheus_counter = "gitlab_transaction_#{counter}_total".to_sym + if expected_counters[counter] > 0 + expect(transaction).to receive(:increment).with(prometheus_counter, 1) + else + expect(transaction).not_to receive(:increment).with(prometheus_counter, 1) + end + end subscriber.sql(event) end end - describe 'with a current transaction' do - shared_examples 'track executed query' do - before do - allow(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) - end + shared_examples 'track query in RequestStore' do + context 'when RequestStore is enabled' do + it 'caches db count value', :request_store, :aggregate_failures do + subscriber.sql(event) - it 'increments only db count value' do described_class::DB_COUNTERS.each do |counter| - prometheus_counter = "gitlab_transaction_#{counter}_total".to_sym - if expected_counters[counter] > 0 - expect(transaction).to receive(:increment).with(prometheus_counter, 1) - else - expect(transaction).not_to receive(:increment).with(prometheus_counter, 1) - end + expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] end - - subscriber.sql(event) end - context 'when RequestStore is enabled' do - it 'caches db count value', :request_store, :aggregate_failures do - subscriber.sql(event) + 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] + described_class::DB_COUNTERS.each do |counter| + expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] + end end end + end + end + end + + describe 'without a current transaction' do + it 'does not track any metrics' do + expect_any_instance_of(Gitlab::Metrics::Transaction) + .not_to receive(:increment) - it 'prevents db counters from leaking to the next transaction' do - 2.times do - Gitlab::WithRequestStore.with_request_store do - subscriber.sql(event) + subscriber.sql(event) + end - described_class::DB_COUNTERS.each do |counter| - expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] - end - end - end - end + 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 query in RequestStore' end + end + describe 'with a current transaction' do it 'observes sql_duration metric' do expect(subscriber).to receive(:current_transaction) .at_least(:once) @@ -96,12 +110,14 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do } end - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' 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 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end @@ -117,33 +133,38 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do context 'with select for update sql event' do let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10 FOR UPDATE' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' 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' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end context 'with delete sql event' do let(:payload) { { sql: 'DELETE FROM users where id = 10' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with insert sql event' do let(:payload) { { sql: 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with update sql event' do let(:payload) { { sql: 'UPDATE users SET admin = true WHERE id = 10' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end @@ -164,18 +185,20 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do } end - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with cached payload name' do let(:payload) do { - sql: 'SELECT * FROM users WHERE id = 10', - name: 'CACHE' + sql: 'SELECT * FROM users WHERE id = 10', + name: 'CACHE' } end - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end @@ -227,8 +250,8 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do it 'skips schema/begin/commit sql commands' do allow(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) + .at_least(:once) + .and_return(transaction) expect(transaction).not_to receive(:increment) diff --git a/spec/lib/gitlab/metrics/transaction_spec.rb b/spec/lib/gitlab/metrics/transaction_spec.rb index 88293f11149..d4e5a1a94f2 100644 --- a/spec/lib/gitlab/metrics/transaction_spec.rb +++ b/spec/lib/gitlab/metrics/transaction_spec.rb @@ -20,14 +20,6 @@ RSpec.describe Gitlab::Metrics::Transaction do end end - describe '#thread_cpu_duration' do - it 'returns the duration of a transaction in seconds' do - transaction.run { } - - expect(transaction.thread_cpu_duration).to be > 0 - end - end - describe '#run' do it 'yields the supplied block' do expect { |b| transaction.run(&b) }.to yield_control diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb index 6903ce53f65..6ee9564ef75 100644 --- a/spec/lib/gitlab/metrics/web_transaction_spec.rb +++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb @@ -80,13 +80,15 @@ RSpec.describe Gitlab::Metrics::WebTransaction do context 'when request goes to Grape endpoint' do before do route = double(:route, request_method: 'GET', path: '/:version/projects/:id/archive(.:format)') - endpoint = double(:endpoint, route: route) + endpoint = double(:endpoint, route: route, + options: { for: API::Projects, path: [":id/archive"] }, + namespace: "/projects") env['api.endpoint'] = endpoint end it 'provides labels with the method and path of the route in the grape endpoint' do - expect(transaction.labels).to eq({ controller: 'Grape', action: 'GET /projects/:id/archive', feature_category: '' }) + expect(transaction.labels).to eq({ controller: 'Grape', action: 'GET /projects/:id/archive', feature_category: 'projects' }) end it 'contains only the labels defined for transactions' do |