diff options
Diffstat (limited to 'spec/lib/peek')
-rw-r--r-- | spec/lib/peek/views/active_record_spec.rb | 175 | ||||
-rw-r--r-- | spec/lib/peek/views/memory_spec.rb | 53 |
2 files changed, 184 insertions, 44 deletions
diff --git a/spec/lib/peek/views/active_record_spec.rb b/spec/lib/peek/views/active_record_spec.rb index 9eeeca4de61..e5aae2822ed 100644 --- a/spec/lib/peek/views/active_record_spec.rb +++ b/spec/lib/peek/views/active_record_spec.rb @@ -5,16 +5,17 @@ require 'spec_helper' RSpec.describe Peek::Views::ActiveRecord, :request_store do subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } } - let(:connection_1) { double(:connection) } - let(:connection_2) { double(:connection) } - let(:connection_3) { double(:connection) } + let(:connection_replica) { double(:connection_replica) } + let(:connection_primary_1) { double(:connection_primary) } + let(:connection_primary_2) { double(:connection_primary) } + let(:connection_unknown) { double(:connection_unknown) } let(:event_1) do { name: 'SQL', sql: 'SELECT * FROM users WHERE id = 10', cached: false, - connection: connection_1 + connection: connection_primary_1 } end @@ -23,7 +24,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do name: 'SQL', sql: 'SELECT * FROM users WHERE id = 10', cached: true, - connection: connection_2 + connection: connection_replica } end @@ -32,55 +33,141 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do name: 'SQL', sql: 'UPDATE users SET admin = true WHERE id = 10', cached: false, - connection: connection_3 + connection: connection_primary_2 + } + end + + let(:event_4) do + { + name: 'SCHEMA', + sql: 'SELECT VERSION()', + cached: false, + connection: connection_unknown } end before do allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true) - allow(connection_1).to receive(:transaction_open?).and_return(false) - allow(connection_2).to receive(:transaction_open?).and_return(false) - allow(connection_3).to receive(:transaction_open?).and_return(true) + allow(connection_replica).to receive(:transaction_open?).and_return(false) + allow(connection_primary_1).to receive(:transaction_open?).and_return(false) + allow(connection_primary_2).to receive(:transaction_open?).and_return(true) + allow(connection_unknown).to receive(:transaction_open?).and_return(false) end - it 'subscribes and store data into peek views' do - Timecop.freeze(2021, 2, 23, 10, 0) do - ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1) - ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2) - ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3) + context 'when database load balancing is not enabled' do + it 'subscribes and store data into peek views' do + Timecop.freeze(2021, 2, 23, 10, 0) do + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1) + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2) + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3) + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 4.seconds, '4', event_4) + end + + expect(subject.results).to match( + calls: 4, + summary: { + "Cached" => 1, + "In a transaction" => 1 + }, + duration: '10000.00ms', + warnings: ["active-record duration: 10000.0 over 3000"], + details: contain_exactly( + a_hash_including( + start: be_a(Time), + cached: '', + transaction: '', + duration: 1000.0, + sql: 'SELECT * FROM users WHERE id = 10' + ), + a_hash_including( + start: be_a(Time), + cached: 'Cached', + transaction: '', + duration: 2000.0, + sql: 'SELECT * FROM users WHERE id = 10' + ), + a_hash_including( + start: be_a(Time), + cached: '', + transaction: 'In a transaction', + duration: 3000.0, + sql: 'UPDATE users SET admin = true WHERE id = 10' + ), + a_hash_including( + start: be_a(Time), + cached: '', + transaction: '', + duration: 4000.0, + sql: 'SELECT VERSION()' + ) + ) + ) + end + end + + context 'when database load balancing is enabled' do + before do + allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true) + allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_replica).and_return(:replica) + allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_primary_1).and_return(:primary) + allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_primary_2).and_return(:primary) + allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_unknown).and_return(nil) end - expect(subject.results).to match( - calls: 3, - summary: { - "Cached" => 1, - "In a transaction" => 1 - }, - duration: '6000.00ms', - warnings: ["active-record duration: 6000.0 over 3000"], - details: contain_exactly( - a_hash_including( - start: be_a(Time), - cached: '', - transaction: '', - duration: 1000.0, - sql: 'SELECT * FROM users WHERE id = 10' - ), - a_hash_including( - start: be_a(Time), - cached: 'Cached', - transaction: '', - duration: 2000.0, - sql: 'SELECT * FROM users WHERE id = 10' - ), - a_hash_including( - start: be_a(Time), - cached: '', - transaction: 'In a transaction', - duration: 3000.0, - sql: 'UPDATE users SET admin = true WHERE id = 10' + it 'includes db role data' do + Timecop.freeze(2021, 2, 23, 10, 0) do + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1) + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2) + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3) + ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 4.seconds, '4', event_4) + end + + expect(subject.results).to match( + calls: 4, + summary: { + "Cached" => 1, + "In a transaction" => 1, + "Primary" => 2, + "Replica" => 1, + "Unknown" => 1 + }, + duration: '10000.00ms', + warnings: ["active-record duration: 10000.0 over 3000"], + details: contain_exactly( + a_hash_including( + start: be_a(Time), + cached: '', + transaction: '', + duration: 1000.0, + sql: 'SELECT * FROM users WHERE id = 10', + db_role: 'Primary' + ), + a_hash_including( + start: be_a(Time), + cached: 'Cached', + transaction: '', + duration: 2000.0, + sql: 'SELECT * FROM users WHERE id = 10', + db_role: 'Replica' + ), + a_hash_including( + start: be_a(Time), + cached: '', + transaction: 'In a transaction', + duration: 3000.0, + sql: 'UPDATE users SET admin = true WHERE id = 10', + db_role: 'Primary' + ), + a_hash_including( + start: be_a(Time), + cached: '', + transaction: '', + duration: 4000.0, + sql: 'SELECT VERSION()', + db_role: 'Unknown' + ) ) ) - ) + end end end diff --git a/spec/lib/peek/views/memory_spec.rb b/spec/lib/peek/views/memory_spec.rb new file mode 100644 index 00000000000..1f88aadfc54 --- /dev/null +++ b/spec/lib/peek/views/memory_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Peek::Views::Memory, :request_store do + subject! { described_class.new } + + before do + stub_memory_instrumentation + end + + context 'with process_action.action_controller notification' do + it 'returns empty results when it has not yet fired' do + expect(subject.results).to eq({}) + end + + it 'returns memory instrumentation data when it has fired' do + publish_notification + + expect(subject.results[:calls]).to eq('2 MB') + expect(subject.results[:details]).to all(have_key(:item_header)) + expect(subject.results[:details]).to all(have_key(:item_content)) + expect(subject.results[:summary]).to include('Objects allocated' => '200 k') + expect(subject.results[:summary]).to include('Allocator calls' => '500') + expect(subject.results[:summary]).to include('Large allocations' => '1 KB') + end + end + + def stub_memory_instrumentation + start_memory = { + total_malloc_bytes: 1, + total_mallocs: 2, + total_allocated_objects: 3 + } + allow(Gitlab::Memory::Instrumentation).to receive(:start_thread_memory_allocations).and_return(start_memory) + allow(Gitlab::Memory::Instrumentation).to receive(:measure_thread_memory_allocations).with(start_memory).and_return({ + mem_total_bytes: 2_097_152, + mem_bytes: 1024, + mem_mallocs: 500, + mem_objects: 200_000 + }) + Gitlab::InstrumentationHelper.init_instrumentation_data + end + + def publish_notification + headers = double + allow(headers).to receive(:env).and_return('action_dispatch.request_id': 'req-42') + + ActiveSupport::Notifications.publish( + 'process_action.action_controller', Time.current - 1.second, Time.current, 'id', headers: headers + ) + end +end |