Commit 7b5fd874 authored by Yorick Peterse's avatar Yorick Peterse

Track the amount of times views are rendered

parent cdaa9744
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
%thead %thead
%tr %tr
%th= t('sherlock.time_inclusive') %th= t('sherlock.time_inclusive')
%th= t('sherlock.count')
%th= t('sherlock.path') %th= t('sherlock.path')
%th %th
%tbody %tbody
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
%td %td
= sample.duration.round(2) = sample.duration.round(2)
= t('sherlock.milliseconds') = t('sherlock.milliseconds')
%td= @transaction.view_counts.fetch(sample.file, 1)
%td= sample.relative_path %td= sample.relative_path
%td %td
= link_to(t('sherlock.view'), = link_to(t('sherlock.view'),
......
...@@ -34,3 +34,4 @@ en: ...@@ -34,3 +34,4 @@ en:
query_plan: Query Plan query_plan: Query Plan
events: Events events: Events
percent: '%' percent: '%'
count: Count
...@@ -2,7 +2,7 @@ module Gitlab ...@@ -2,7 +2,7 @@ module Gitlab
module Sherlock module Sherlock
class Transaction class Transaction
attr_reader :id, :type, :path, :queries, :file_samples, :started_at, attr_reader :id, :type, :path, :queries, :file_samples, :started_at,
:finished_at :finished_at, :view_counts
# type - The type of transaction (e.g. "GET", "POST", etc) # type - The type of transaction (e.g. "GET", "POST", etc)
# path - The path of the transaction (e.g. the HTTP request path) # path - The path of the transaction (e.g. the HTTP request path)
...@@ -15,20 +15,19 @@ module Gitlab ...@@ -15,20 +15,19 @@ module Gitlab
@started_at = nil @started_at = nil
@finished_at = nil @finished_at = nil
@thread = Thread.current @thread = Thread.current
@view_counts = Hash.new(0)
end end
# Runs the transaction and returns the block's return value. # Runs the transaction and returns the block's return value.
def run def run
@started_at = Time.now @started_at = Time.now
subscriber = subscribe_to_active_record retval = with_subscriptions do
profile_lines { yield }
retval = profile_lines { yield } end
@finished_at = Time.now @finished_at = Time.now
ActiveSupport::Notifications.unsubscribe(subscriber)
retval retval
end end
...@@ -81,21 +80,51 @@ module Gitlab ...@@ -81,21 +80,51 @@ module Gitlab
retval retval
end end
def subscribe_to_active_record
ActiveSupport::Notifications.subscribe('sql.active_record') do |_, start, finish, _, data|
next unless same_thread?
track_query(data[:sql].strip, data[:binds], start, finish)
end
end
def subscribe_to_action_view
regex = /render_(template|partial)\.action_view/
ActiveSupport::Notifications.subscribe(regex) do |_, start, finish, _, data|
next unless same_thread?
track_view(data[:identifier])
end
end
private private
def track_query(query, bindings, start, finish) def track_query(query, bindings, start, finish)
@queries << Query.new_with_bindings(query, bindings, start, finish) @queries << Query.new_with_bindings(query, bindings, start, finish)
end end
def subscribe_to_active_record def track_view(path)
ActiveSupport::Notifications.subscribe('sql.active_record') do |_, start, finish, _, data| @view_counts[path] += 1
# In case somebody uses a multi-threaded server locally (e.g. Puma) we end
# _only_ want to track queries that originate from the transaction
# thread.
next unless Thread.current == @thread
track_query(data[:sql].strip, data[:binds], start, finish) def with_subscriptions
ar_subscriber = subscribe_to_active_record
av_subscriber = subscribe_to_action_view
retval = yield
ActiveSupport::Notifications.unsubscribe(ar_subscriber)
ActiveSupport::Notifications.unsubscribe(av_subscriber)
retval
end end
# In case somebody uses a multi-threaded server locally (e.g. Puma) we
# _only_ want to track notifications that originate from the transaction
# thread.
def same_thread?
Thread.current == @thread
end end
end end
end end
......
...@@ -53,6 +53,16 @@ describe Gitlab::Sherlock::Transaction do ...@@ -53,6 +53,16 @@ describe Gitlab::Sherlock::Transaction do
end end
end end
describe '#view_counts' do
it 'returns a Hash' do
expect(transaction.view_counts).to be_an_instance_of(Hash)
end
it 'sets the default value of a key to 0' do
expect(transaction.view_counts['cats.rb']).to be_zero
end
end
describe '#run' do describe '#run' do
it 'runs the transaction' do it 'runs the transaction' do
allow(transaction).to receive(:profile_lines).and_yield allow(transaction).to receive(:profile_lines).and_yield
...@@ -162,4 +172,51 @@ describe Gitlab::Sherlock::Transaction do ...@@ -162,4 +172,51 @@ describe Gitlab::Sherlock::Transaction do
end end
end end
end end
describe '#subscribe_to_active_record' do
let(:subscription) { transaction.subscribe_to_active_record }
let(:time) { Time.now }
let(:query_data) { { sql: 'SELECT 1', binds: [] } }
after do
ActiveSupport::Notifications.unsubscribe(subscription)
end
it 'tracks executed queries' do
expect(transaction).to receive(:track_query).
with('SELECT 1', [], time, time)
subscription.publish('test', time, time, nil, query_data)
end
it 'only tracks queries triggered from the transaction thread' do
expect(transaction).to_not receive(:track_query)
Thread.new { subscription.publish('test', time, time, nil, query_data) }.
join
end
end
describe '#subscribe_to_action_view' do
let(:subscription) { transaction.subscribe_to_action_view }
let(:time) { Time.now }
let(:view_data) { { identifier: 'foo.rb' } }
after do
ActiveSupport::Notifications.unsubscribe(subscription)
end
it 'tracks rendered views' do
expect(transaction).to receive(:track_view).with('foo.rb')
subscription.publish('test', time, time, nil, view_data)
end
it 'only tracks views rendered from the transaction thread' do
expect(transaction).to_not receive(:track_view)
Thread.new { subscription.publish('test', time, time, nil, view_data) }.
join
end
end
end end
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