summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/views/sherlock/transactions/_file_samples.html.haml2
-rw-r--r--config/locales/sherlock.en.yml1
-rw-r--r--lib/gitlab/sherlock/transaction.rb57
-rw-r--r--spec/lib/gitlab/sherlock/transaction_spec.rb57
4 files changed, 103 insertions, 14 deletions
diff --git a/app/views/sherlock/transactions/_file_samples.html.haml b/app/views/sherlock/transactions/_file_samples.html.haml
index 0afdbc8dffa..4349c9b7ace 100644
--- a/app/views/sherlock/transactions/_file_samples.html.haml
+++ b/app/views/sherlock/transactions/_file_samples.html.haml
@@ -7,6 +7,7 @@
%thead
%tr
%th= t('sherlock.time_inclusive')
+ %th= t('sherlock.count')
%th= t('sherlock.path')
%th
%tbody
@@ -15,6 +16,7 @@
%td
= sample.duration.round(2)
= t('sherlock.milliseconds')
+ %td= @transaction.view_counts.fetch(sample.file, 1)
%td= sample.relative_path
%td
= link_to(t('sherlock.view'),
diff --git a/config/locales/sherlock.en.yml b/config/locales/sherlock.en.yml
index 5c146b172b1..683b09dc329 100644
--- a/config/locales/sherlock.en.yml
+++ b/config/locales/sherlock.en.yml
@@ -34,3 +34,4 @@ en:
query_plan: Query Plan
events: Events
percent: '%'
+ count: Count
diff --git a/lib/gitlab/sherlock/transaction.rb b/lib/gitlab/sherlock/transaction.rb
index 4641f15ee33..d87a4c9bb4a 100644
--- a/lib/gitlab/sherlock/transaction.rb
+++ b/lib/gitlab/sherlock/transaction.rb
@@ -2,7 +2,7 @@ module Gitlab
module Sherlock
class Transaction
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)
# path - The path of the transaction (e.g. the HTTP request path)
@@ -15,20 +15,19 @@ module Gitlab
@started_at = nil
@finished_at = nil
@thread = Thread.current
+ @view_counts = Hash.new(0)
end
# Runs the transaction and returns the block's return value.
def run
@started_at = Time.now
- subscriber = subscribe_to_active_record
-
- retval = profile_lines { yield }
+ retval = with_subscriptions do
+ profile_lines { yield }
+ end
@finished_at = Time.now
- ActiveSupport::Notifications.unsubscribe(subscriber)
-
retval
end
@@ -81,21 +80,51 @@ module Gitlab
retval
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
def track_query(query, bindings, start, finish)
@queries << Query.new_with_bindings(query, bindings, start, finish)
end
- def subscribe_to_active_record
- ActiveSupport::Notifications.subscribe('sql.active_record') do |_, start, finish, _, data|
- # In case somebody uses a multi-threaded server locally (e.g. Puma) we
- # _only_ want to track queries that originate from the transaction
- # thread.
- next unless Thread.current == @thread
+ def track_view(path)
+ @view_counts[path] += 1
+ end
- track_query(data[:sql].strip, data[:binds], start, finish)
- end
+ 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
+
+ # 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
diff --git a/spec/lib/gitlab/sherlock/transaction_spec.rb b/spec/lib/gitlab/sherlock/transaction_spec.rb
index bb4ff42e6e1..bb49fb65cf8 100644
--- a/spec/lib/gitlab/sherlock/transaction_spec.rb
+++ b/spec/lib/gitlab/sherlock/transaction_spec.rb
@@ -53,6 +53,16 @@ describe Gitlab::Sherlock::Transaction do
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
it 'runs the transaction' do
allow(transaction).to receive(:profile_lines).and_yield
@@ -162,4 +172,51 @@ describe Gitlab::Sherlock::Transaction do
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