Commit 0b4d2dd5 authored by Quang-Minh Nguyen's avatar Quang-Minh Nguyen

Add summary to peek ActiveRecord

Issue https://gitlab.com/gitlab-org/gitlab/-/issues/324649
parent 57733910
...@@ -11,11 +11,23 @@ module EE ...@@ -11,11 +11,23 @@ module EE
detail = super detail = super
if ::Gitlab::Database::LoadBalancing.enable? if ::Gitlab::Database::LoadBalancing.enable?
detail[:db_role] = ::Gitlab::Database::LoadBalancing.db_role_for_connection(data[:connection]) detail[:db_role] = ::Gitlab::Database::LoadBalancing.db_role_for_connection(data[:connection]).to_s.capitalize
end end
detail detail
end end
override :summary
def summary
if ::Gitlab::Database::LoadBalancing.enable?
detail_store.each_with_object(super) do |item, count|
count[item[:db_role]] ||= 0
count[item[:db_role]] += 1
end
else
super
end
end
end end
end end
end end
......
...@@ -6,14 +6,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -6,14 +6,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } } subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } }
let(:connection_replica) { double(:connection_replica) } let(:connection_replica) { double(:connection_replica) }
let(:connection_primary) { double(:connection_primary) } let(:connection_primary_1) { double(:connection_primary) }
let(:connection_primary_2) { double(:connection_primary) }
let(:event_1) do let(:event_1) do
{ {
name: 'SQL', name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10', sql: 'SELECT * FROM users WHERE id = 10',
cached: false, cached: false,
connection: connection_primary connection: connection_primary_1
} }
end end
...@@ -31,12 +32,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -31,12 +32,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL', name: 'SQL',
sql: 'UPDATE users SET admin = true WHERE id = 10', sql: 'UPDATE users SET admin = true WHERE id = 10',
cached: false, cached: false,
connection: connection_primary connection: connection_primary_2
} }
end end
before do before do
allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true) allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).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)
end end
context 'when database load balancing is not enabled' do context 'when database load balancing is not enabled' do
...@@ -48,22 +52,32 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -48,22 +52,32 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
end end
expect(subject.results).to match( expect(subject.results).to match(
calls: '3 (1 cached)', calls: 3,
summary: {
"Cached" => 1,
"In a transaction" => 1
},
duration: '6000.00ms', duration: '6000.00ms',
warnings: ["active-record duration: 6000.0 over 3000"], warnings: ["active-record duration: 6000.0 over 3000"],
details: contain_exactly( details: contain_exactly(
a_hash_including( a_hash_including(
start: be_a(Time),
cached: '', cached: '',
transaction: '',
duration: 1000.0, duration: 1000.0,
sql: 'SELECT * FROM users WHERE id = 10' sql: 'SELECT * FROM users WHERE id = 10'
), ),
a_hash_including( a_hash_including(
cached: 'cached', start: be_a(Time),
cached: 'Cached',
transaction: '',
duration: 2000.0, duration: 2000.0,
sql: 'SELECT * FROM users WHERE id = 10' sql: 'SELECT * FROM users WHERE id = 10'
), ),
a_hash_including( a_hash_including(
start: be_a(Time),
cached: '', cached: '',
transaction: 'In a transaction',
duration: 3000.0, duration: 3000.0,
sql: 'UPDATE users SET admin = true WHERE id = 10' sql: 'UPDATE users SET admin = true WHERE id = 10'
) )
...@@ -76,7 +90,8 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -76,7 +90,8 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
before do before do
allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true) 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_replica).and_return(:replica)
allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_primary).and_return(:primary) 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)
end end
it 'includes db role data' do it 'includes db role data' do
...@@ -87,27 +102,39 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -87,27 +102,39 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
end end
expect(subject.results).to match( expect(subject.results).to match(
calls: '3 (1 cached)', calls: 3,
summary: {
"Cached" => 1,
"In a transaction" => 1,
"Primary" => 2,
"Replica" => 1
},
duration: '6000.00ms', duration: '6000.00ms',
warnings: ["active-record duration: 6000.0 over 3000"], warnings: ["active-record duration: 6000.0 over 3000"],
details: contain_exactly( details: contain_exactly(
a_hash_including( a_hash_including(
start: be_a(Time),
cached: '', cached: '',
transaction: '',
duration: 1000.0, duration: 1000.0,
sql: 'SELECT * FROM users WHERE id = 10', sql: 'SELECT * FROM users WHERE id = 10',
db_role: :primary db_role: 'Primary'
), ),
a_hash_including( a_hash_including(
cached: 'cached', start: be_a(Time),
cached: 'Cached',
transaction: '',
duration: 2000.0, duration: 2000.0,
sql: 'SELECT * FROM users WHERE id = 10', sql: 'SELECT * FROM users WHERE id = 10',
db_role: :replica db_role: 'Replica'
), ),
a_hash_including( a_hash_including(
start: be_a(Time),
cached: '', cached: '',
transaction: 'In a transaction',
duration: 3000.0, duration: 3000.0,
sql: 'UPDATE users SET admin = true WHERE id = 10', sql: 'UPDATE users SET admin = true WHERE id = 10',
db_role: :primary db_role: 'Primary'
) )
) )
) )
......
...@@ -17,22 +17,28 @@ module Peek ...@@ -17,22 +17,28 @@ module Peek
} }
}.freeze }.freeze
def results
super.merge(calls: detailed_calls)
end
def self.thresholds def self.thresholds
@thresholds ||= THRESHOLDS.fetch(Rails.env.to_sym, DEFAULT_THRESHOLDS) @thresholds ||= THRESHOLDS.fetch(Rails.env.to_sym, DEFAULT_THRESHOLDS)
end end
def results
super.merge(summary: summary)
end
private private
def detailed_calls def summary
"#{calls} (#{cached_calls} cached)" detail_store.each_with_object({}) do |item, count|
if item[:cached].present?
count[item[:cached]] ||= 0
count[item[:cached]] += 1
end end
def cached_calls if item[:transaction].present?
detail_store.count { |item| item[:cached] == 'cached' } count[item[:transaction]] ||= 0
count[item[:transaction]] += 1
end
end
end end
def setup_subscribers def setup_subscribers
...@@ -45,10 +51,12 @@ module Peek ...@@ -45,10 +51,12 @@ module Peek
def generate_detail(start, finish, data) def generate_detail(start, finish, data)
{ {
start: start,
duration: finish - start, duration: finish - start,
sql: data[:sql].strip, sql: data[:sql].strip,
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller), backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller),
cached: data[:cached] ? 'cached' : '' cached: data[:cached] ? 'Cached' : '',
transaction: data[:connection].transaction_open? ? 'In a transaction' : ''
} }
end end
end end
......
...@@ -5,14 +5,16 @@ require 'spec_helper' ...@@ -5,14 +5,16 @@ require 'spec_helper'
RSpec.describe Peek::Views::ActiveRecord, :request_store do RSpec.describe Peek::Views::ActiveRecord, :request_store do
subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } } subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } }
let(:connection) { double(:connection) } let(:connection_1) { double(:connection) }
let(:connection_2) { double(:connection) }
let(:connection_3) { double(:connection) }
let(:event_1) do let(:event_1) do
{ {
name: 'SQL', name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10', sql: 'SELECT * FROM users WHERE id = 10',
cached: false, cached: false,
connection: connection connection: connection_1
} }
end end
...@@ -21,7 +23,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -21,7 +23,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL', name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10', sql: 'SELECT * FROM users WHERE id = 10',
cached: true, cached: true,
connection: connection connection: connection_2
} }
end end
...@@ -30,12 +32,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -30,12 +32,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL', name: 'SQL',
sql: 'UPDATE users SET admin = true WHERE id = 10', sql: 'UPDATE users SET admin = true WHERE id = 10',
cached: false, cached: false,
connection: connection connection: connection_3
} }
end end
before do before do
allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true) 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)
end end
it 'subscribes and store data into peek views' do it 'subscribes and store data into peek views' do
...@@ -46,22 +51,32 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do ...@@ -46,22 +51,32 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
end end
expect(subject.results).to match( expect(subject.results).to match(
calls: '3 (1 cached)', calls: 3,
summary: {
"Cached" => 1,
"In a transaction" => 1
},
duration: '6000.00ms', duration: '6000.00ms',
warnings: ["active-record duration: 6000.0 over 3000"], warnings: ["active-record duration: 6000.0 over 3000"],
details: contain_exactly( details: contain_exactly(
a_hash_including( a_hash_including(
start: be_a(Time),
cached: '', cached: '',
transaction: '',
duration: 1000.0, duration: 1000.0,
sql: 'SELECT * FROM users WHERE id = 10' sql: 'SELECT * FROM users WHERE id = 10'
), ),
a_hash_including( a_hash_including(
cached: 'cached', start: be_a(Time),
cached: 'Cached',
transaction: '',
duration: 2000.0, duration: 2000.0,
sql: 'SELECT * FROM users WHERE id = 10' sql: 'SELECT * FROM users WHERE id = 10'
), ),
a_hash_including( a_hash_including(
start: be_a(Time),
cached: '', cached: '',
transaction: 'In a transaction',
duration: 3000.0, duration: 3000.0,
sql: 'UPDATE users SET admin = true WHERE id = 10' sql: 'UPDATE users SET admin = true WHERE id = 10'
) )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment