Add Gitaly call details to the performance bar
The same as the SQL queries, show the details of Gitaly calls in the performance bar, as a modal that can be opened in the same way.
This commit is contained in:
parent
1bab4dcffc
commit
d30576c5a7
|
@ -18,6 +18,8 @@ export default class PerformanceBar {
|
|||
this.$sqlProfileModal = $container.find('#modal-peek-pg-queries');
|
||||
this.$lineProfileLink = $container.find('.js-toggle-modal-peek-line-profile');
|
||||
this.$lineProfileModal = $('#modal-peek-line-profile');
|
||||
this.$gitalyProfileLink = $container.find('.js-toggle-modal-peek-gitaly');
|
||||
this.$gitalyProfileModal = $container.find('#modal-peek-gitaly-details');
|
||||
this.initEventListeners();
|
||||
this.showModalOnLoad();
|
||||
}
|
||||
|
@ -25,6 +27,7 @@ export default class PerformanceBar {
|
|||
initEventListeners() {
|
||||
this.$sqlProfileLink.on('click', () => this.handleSQLProfileLink());
|
||||
this.$lineProfileLink.on('click', e => this.handleLineProfileLink(e));
|
||||
this.$gitalyProfileLink.on('click', () => this.handleGitalyProfileLink());
|
||||
$(document).on('click', '.js-lineprof-file', PerformanceBar.toggleLineProfileFile);
|
||||
}
|
||||
|
||||
|
@ -52,6 +55,10 @@ export default class PerformanceBar {
|
|||
}
|
||||
}
|
||||
|
||||
handleGitalyProfileLink() {
|
||||
PerformanceBar.toggleModal(this.$gitalyProfileModal);
|
||||
}
|
||||
|
||||
static toggleModal($modal) {
|
||||
if ($modal.length) {
|
||||
$modal.modal('toggle');
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
- local_assigns.fetch(:view)
|
||||
|
||||
%strong
|
||||
%span{ data: { defer_to: "#{view.defer_key}-duration" } } ...
|
||||
\/
|
||||
%span{ data: { defer_to: "#{view.defer_key}-calls" } } ...
|
||||
Gitaly
|
||||
%a.js-toggle-modal-peek-gitaly
|
||||
%span{ data: { defer_to: "#{view.defer_key}-duration" } }...
|
||||
\/
|
||||
%span{ data: { defer_to: "#{view.defer_key}-calls" } }...
|
||||
#modal-peek-gitaly-details.modal{ tabindex: -1 }
|
||||
.modal-dialog.modal-full
|
||||
.modal-content
|
||||
.modal-header
|
||||
%button.close.btn.btn-link.btn-sm{ type: 'button', data: { dismiss: 'modal' } } X
|
||||
%h4
|
||||
Gitaly requests
|
||||
.modal-body{ data: { defer_to: "#{view.defer_key}-details" } }...
|
||||
Gitaly
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add Gitaly call details to performance bar
|
||||
merge_request:
|
||||
author:
|
||||
type: added
|
|
@ -119,6 +119,8 @@ module Gitlab
|
|||
#
|
||||
def self.call(storage, service, rpc, request, remote_storage: nil, timeout: nil)
|
||||
start = Gitlab::Metrics::System.monotonic_time
|
||||
@last_request = request.is_a?(Google::Protobuf::MessageExts) ? request.to_h : nil
|
||||
|
||||
enforce_gitaly_request_limits(:call)
|
||||
|
||||
kwargs = request_kwargs(storage, timeout, remote_storage: remote_storage)
|
||||
|
@ -258,6 +260,9 @@ module Gitlab
|
|||
gitaly_migrate_call_duration_seconds.observe({ gitaly_enabled: is_enabled, feature: feature }, total_time)
|
||||
feature_stack.shift
|
||||
Thread.current[:gitaly_feature_stack] = nil if feature_stack.empty?
|
||||
add_call_details(feature: feature,
|
||||
duration: total_time,
|
||||
request: is_enabled ? @last_request : {})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -344,6 +349,19 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def self.add_call_details(details)
|
||||
return unless RequestStore.active? && RequestStore.store[:peek_enabled]
|
||||
|
||||
RequestStore.store['gitaly_call_details'] ||= []
|
||||
RequestStore.store['gitaly_call_details'] << details
|
||||
end
|
||||
|
||||
def self.call_details
|
||||
return [] unless RequestStore.active? && RequestStore.store[:peek_enabled]
|
||||
|
||||
RequestStore.store['gitaly_call_details'] || []
|
||||
end
|
||||
|
||||
def self.expected_server_version
|
||||
path = Rails.root.join(SERVER_VERSION_FILE)
|
||||
path.read.chomp
|
||||
|
|
|
@ -10,11 +10,28 @@ module Peek
|
|||
end
|
||||
|
||||
def results
|
||||
{ duration: formatted_duration, calls: calls }
|
||||
{
|
||||
duration: formatted_duration,
|
||||
calls: calls,
|
||||
details: details
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def details
|
||||
::Gitlab::GitalyClient.call_details
|
||||
.sort { |a, b| b[:duration] <=> a[:duration] }
|
||||
.map(&method(:format_call_details))
|
||||
end
|
||||
|
||||
def format_call_details(call)
|
||||
pretty_request = call[:request].reject { |k, v| v.blank? }.to_h.pretty_inspect
|
||||
|
||||
call.merge(duration: (call[:duration] * 1000).round(3),
|
||||
request: pretty_request)
|
||||
end
|
||||
|
||||
def formatted_duration
|
||||
ms = duration * 1000
|
||||
if ms >= 1000
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
*
|
||||
* - Removed the dependency on jquery.tipsy
|
||||
* - Removed the initializeTipsy and toggleBar functions
|
||||
* - Customized updatePerformanceBar to handle SQL queries report specificities
|
||||
* - Customized updatePerformanceBar to handle SQL query and Gitaly call lists
|
||||
* - Changed /peek/results to /-/peek/results
|
||||
* - Removed the keypress, pjax:end, page:change, and turbolinks:load handlers
|
||||
*/
|
||||
(function($) {
|
||||
var fetchRequestResults, getRequestId, peekEnabled, updatePerformanceBar;
|
||||
var fetchRequestResults, getRequestId, peekEnabled, updatePerformanceBar, createTable, createTableRow;
|
||||
getRequestId = function() {
|
||||
return $('#peek').data('requestId');
|
||||
};
|
||||
|
@ -16,40 +16,62 @@
|
|||
return $('#peek').length;
|
||||
};
|
||||
updatePerformanceBar = function(results) {
|
||||
var key, label, data, table, html, tr, duration_td, sql_td, strong;
|
||||
|
||||
Object.keys(results.data).forEach(function(key) {
|
||||
Object.keys(results.data[key]).forEach(function(label) {
|
||||
var data, table, target;
|
||||
|
||||
data = results.data[key][label];
|
||||
table = createTable(key, label, data);
|
||||
target = $("[data-defer-to=" + key + "-" + label + "]");
|
||||
|
||||
if (label == 'queries') {
|
||||
table = document.createElement('table');
|
||||
|
||||
for (var i = 0; i < data.length; i += 1) {
|
||||
tr = document.createElement('tr');
|
||||
duration_td = document.createElement('td');
|
||||
sql_td = document.createElement('td');
|
||||
strong = document.createElement('strong');
|
||||
|
||||
strong.append(data[i]['duration'] + 'ms');
|
||||
duration_td.appendChild(strong);
|
||||
tr.appendChild(duration_td);
|
||||
|
||||
sql_td.appendChild(document.createTextNode(data[i]['sql']));
|
||||
tr.appendChild(sql_td);
|
||||
|
||||
table.appendChild(tr);
|
||||
}
|
||||
|
||||
table.className = 'table';
|
||||
$("[data-defer-to=" + key + "-" + label + "]").html(table);
|
||||
if (table) {
|
||||
target.html(table);
|
||||
} else {
|
||||
$("[data-defer-to=" + key + "-" + label + "]").text(results.data[key][label]);
|
||||
target.text(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
return $(document).trigger('peek:render', [getRequestId(), results]);
|
||||
};
|
||||
createTable = function(key, label, data) {
|
||||
var table;
|
||||
|
||||
if (label != 'queries' && label != 'details') { return; }
|
||||
|
||||
table = document.createElement('table');
|
||||
|
||||
for (var i = 0; i < data.length; i += 1) {
|
||||
table.appendChild(createTableRow(data[i]));
|
||||
}
|
||||
|
||||
table.className = 'table';
|
||||
|
||||
return table;
|
||||
};
|
||||
createTableRow = function(row) {
|
||||
var tr, duration_td, strong;
|
||||
|
||||
tr = document.createElement('tr');
|
||||
duration_td = document.createElement('td');
|
||||
strong = document.createElement('strong');
|
||||
|
||||
strong.append(row['duration'] + 'ms');
|
||||
duration_td.appendChild(strong);
|
||||
tr.appendChild(duration_td);
|
||||
|
||||
['sql', 'feature', 'enabled', 'request'].forEach(function(key) {
|
||||
var td;
|
||||
|
||||
if (!row[key]) { return; }
|
||||
|
||||
td = document.createElement('td');
|
||||
td.appendChild(document.createTextNode(row[key]));
|
||||
|
||||
tr.appendChild(td);
|
||||
});
|
||||
|
||||
return tr;
|
||||
};
|
||||
fetchRequestResults = function() {
|
||||
return $.ajax('/-/peek/results', {
|
||||
data: {
|
||||
|
|
Loading…
Reference in New Issue