Commit 01ca0e53 authored by Rémy Coutable's avatar Rémy Coutable

[EE] Improve & fix the performance bar UI and behavior

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent da230da9
...@@ -60,6 +60,7 @@ import ShortcutsBlob from './shortcuts_blob'; ...@@ -60,6 +60,7 @@ import ShortcutsBlob from './shortcuts_blob';
import initSettingsPanels from './settings_panels'; import initSettingsPanels from './settings_panels';
import initExperimentalFlags from './experimental_flags'; import initExperimentalFlags from './experimental_flags';
import OAuthRememberMe from './oauth_remember_me'; import OAuthRememberMe from './oauth_remember_me';
import PerformanceBar from './performance_bar';
// EE-only // EE-only
import ApproversSelect from './approvers_select'; import ApproversSelect from './approvers_select';
...@@ -541,6 +542,10 @@ import AuditLogs from './audit_logs'; ...@@ -541,6 +542,10 @@ import AuditLogs from './audit_logs';
if (!shortcut_handler) { if (!shortcut_handler) {
new Shortcuts(); new Shortcuts();
} }
if (document.querySelector('#peek')) {
new PerformanceBar({ container: '#peek' });
}
}; };
Dispatcher.prototype.initSearch = function() { Dispatcher.prototype.initSearch = function() {
......
import 'vendor/peek';
import 'vendor/peek.performance_bar';
$(document).on('click', '#peek-show-queries', (e) => {
e.preventDefault();
$('.peek-rblineprof-modal').hide();
const $modal = $('#modal-peek-pg-queries');
if ($modal.length) {
$modal.modal('toggle');
}
});
$(document).on('click', '.js-lineprof-file', (e) => {
e.preventDefault();
$(e.target).parents('.peek-rblineprof-file').find('.data').toggle();
});
import 'vendor/peek';
import 'vendor/peek.performance_bar';
export default class PerformanceBar {
constructor(opts) {
if (!PerformanceBar.singleton) {
this.init(opts);
PerformanceBar.singleton = this;
}
return PerformanceBar.singleton;
}
init(opts) {
const $container = $(opts.container);
this.$sqlProfileLink = $container.find('.js-toggle-modal-peek-sql');
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.initEventListeners();
this.showModalOnLoad();
}
initEventListeners() {
this.$sqlProfileLink.on('click', () => this.handleSQLProfileLink());
this.$lineProfileLink.on('click', e => this.handleLineProfileLink(e));
$(document).on('click', '.js-lineprof-file', PerformanceBar.toggleLineProfileFile);
}
showModalOnLoad() {
// When a lineprofiler query-string param is present, we show the line
// profiler modal upon page load
if (/lineprofiler/.test(window.location.search)) {
PerformanceBar.toggleModal(this.$lineProfileModal);
}
}
handleSQLProfileLink() {
PerformanceBar.toggleModal(this.$sqlProfileModal);
}
handleLineProfileLink(e) {
const lineProfilerParameter = gl.utils.getParameterValues('lineprofiler');
const lineProfilerParameterRegex = new RegExp(`lineprofiler=${lineProfilerParameter[0]}`);
const shouldToggleModal = lineProfilerParameter.length > 0 &&
lineProfilerParameterRegex.test(e.currentTarget.href);
if (shouldToggleModal) {
e.preventDefault();
PerformanceBar.toggleModal(this.$lineProfileModal);
}
}
static toggleModal($modal) {
if ($modal.length) {
$modal.modal('toggle');
}
}
static toggleLineProfileFile(e) {
$(e.currentTarget).parents('.peek-rblineprof-file').find('.data').toggle();
}
}
...@@ -21,3 +21,9 @@ body.modal-open { ...@@ -21,3 +21,9 @@ body.modal-open {
width: 860px; width: 860px;
} }
} }
@media (min-width: $screen-lg-min) {
.modal-full {
width: 98%;
}
}
...@@ -614,3 +614,15 @@ Convdev Index ...@@ -614,3 +614,15 @@ Convdev Index
$color-high-score: $green-400; $color-high-score: $green-400;
$color-average-score: $orange-400; $color-average-score: $orange-400;
$color-low-score: $red-400; $color-low-score: $red-400;
/*
Performance Bar
*/
$perf-bar-text: #999;
$perf-bar-production: #222;
$perf-bar-staging: #291430;
$perf-bar-development: #4c1210;
$perf-bar-bucket-bg: #111;
$perf-bar-bucket-color: #ccc;
$perf-bar-bucket-box-shadow-from: rgba($white-light, .2);
$perf-bar-bucket-box-shadow-to: rgba($black, .25);
//= require peek/views/performance_bar @import "framework/variables";
//= require peek/views/rblineprof @import "peek/views/performance_bar";
@import "peek/views/rblineprof";
header.navbar-gitlab.with-peek {
top: 35px;
}
#peek { #peek {
height: 35px; height: 35px;
background: #000; background: $black;
line-height: 35px; line-height: 35px;
color: #999; color: $perf-bar-text;
&.disabled { &.disabled {
display: none; display: none;
} }
&.production { &.production {
background-color: #222; background-color: $perf-bar-production;
} }
&.staging { &.staging {
background-color: #291430; background-color: $perf-bar-staging;
} }
&.development { &.development {
background-color: #4c1210; background-color: $perf-bar-development;
} }
.wrapper { .wrapper {
width: 800px; width: 1000px;
margin: 0 auto; margin: 0 auto;
} }
// UI Elements // UI Elements
.bucket { .bucket {
background: #111; background: $perf-bar-bucket-bg;
display: inline-block; display: inline-block;
padding: 4px 6px; padding: 4px 6px;
font-family: Consolas, "Liberation Mono", Courier, monospace; font-family: Consolas, "Liberation Mono", Courier, monospace;
line-height: 1; line-height: 1;
color: #ccc; color: $perf-bar-bucket-color;
border-radius: 3px; border-radius: 3px;
box-shadow: 0 1px 0 rgba(255,255,255,.2), inset 0 1px 2px rgba(0,0,0,.25); box-shadow: 0 1px 0 $perf-bar-bucket-box-shadow-from, inset 0 1px 2px $perf-bar-bucket-box-shadow-to;
.hidden { .hidden {
display: none; display: none;
...@@ -53,12 +50,14 @@ header.navbar-gitlab.with-peek { ...@@ -53,12 +50,14 @@ header.navbar-gitlab.with-peek {
} }
strong { strong {
color: #fff; color: $white-light;
} }
table { table {
color: $black;
strong { strong {
color: #000; color: $black;
} }
} }
...@@ -90,5 +89,15 @@ header.navbar-gitlab.with-peek { ...@@ -90,5 +89,15 @@ header.navbar-gitlab.with-peek {
} }
#modal-peek-pg-queries-content { #modal-peek-pg-queries-content {
color: #000; color: $black;
}
.peek-rblineprof-file {
pre.duration {
width: 280px;
}
.data {
overflow: visible;
}
} }
...@@ -23,7 +23,6 @@ module NavHelper ...@@ -23,7 +23,6 @@ module NavHelper
def nav_header_class def nav_header_class
class_name = '' class_name = ''
class_name << " with-horizontal-nav" if defined?(nav) && nav class_name << " with-horizontal-nav" if defined?(nav) && nav
class_name << " with-peek" if peek_enabled?
class_name class_name
end end
......
module PerformanceBarHelper
# This is a hack since using `alias_method :performance_bar_enabled?, :peek_enabled?`
# in WithPerformanceBar breaks tests (but works in the browser).
def performance_bar_enabled?
peek_enabled?
end
end
...@@ -27,10 +27,11 @@ ...@@ -27,10 +27,11 @@
%td.shortcut %td.shortcut
.key f .key f
%td Focus Filter %td Focus Filter
%tr - if performance_bar_enabled?
%td.shortcut %tr
.key p b %td.shortcut
%td Show/hide the Performance Bar .key p b
%td Show/hide the Performance Bar
%tr %tr
%td.shortcut %td.shortcut
.key ? .key ?
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
= stylesheet_link_tag "application", media: "all" = stylesheet_link_tag "application", media: "all"
= stylesheet_link_tag "print", media: "print" = stylesheet_link_tag "print", media: "print"
= stylesheet_link_tag "test", media: "all" if Rails.env.test? = stylesheet_link_tag "test", media: "all" if Rails.env.test?
= stylesheet_link_tag 'peek' if peek_enabled? = stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
- if show_new_nav? - if show_new_nav?
= stylesheet_link_tag "new_nav", media: "all" = stylesheet_link_tag "new_nav", media: "all"
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
= webpack_bundle_tag "main" = webpack_bundle_tag "main"
= webpack_bundle_tag "raven" if current_application_settings.clientside_sentry_enabled = webpack_bundle_tag "raven" if current_application_settings.clientside_sentry_enabled
= webpack_bundle_tag "test" if Rails.env.test? = webpack_bundle_tag "test" if Rails.env.test?
= webpack_bundle_tag 'peek' if peek_enabled? = webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
- if content_for?(:page_specific_javascripts) - if content_for?(:page_specific_javascripts)
= yield :page_specific_javascripts = yield :page_specific_javascripts
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
= render "layouts/head" = render "layouts/head"
%body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } } %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } }
= render "layouts/init_auto_complete" if @gfm_form = render "layouts/init_auto_complete" if @gfm_form
= render 'peek/bar'
- if show_new_nav? - if show_new_nav?
= render "layouts/header/new" = render "layouts/header/new"
- else - else
...@@ -11,3 +10,5 @@ ...@@ -11,3 +10,5 @@
= render 'layouts/page', sidebar: sidebar, nav: nav = render 'layouts/page', sidebar: sidebar, nav: nav
= yield :scripts_body = yield :scripts_body
= render 'peek/bar'
Profile:
= link_to 'all', url_for(lineprofiler: 'true'), class: 'js-toggle-modal-peek-line-profile'
\/
= link_to 'app & lib', url_for(lineprofiler: 'app'), class: 'js-toggle-modal-peek-line-profile'
\/
= link_to 'views', url_for(lineprofiler: 'views'), class: 'js-toggle-modal-peek-line-profile'
%strong %strong
%a#peek-show-queries{ href: '#' } %a.js-toggle-modal-peek-sql
%span{ data: { defer_to: "#{view.defer_key}-duration" } }... %span{ data: { defer_to: "#{view.defer_key}-duration" } }...
\/ \/
%span{ data: { defer_to: "#{view.defer_key}-calls" } }... %span{ data: { defer_to: "#{view.defer_key}-calls" } }...
#modal-peek-pg-queries.modal{ tabindex: -1 } #modal-peek-pg-queries.modal{ tabindex: -1 }
.modal-dialog .modal-dialog.modal-full
#modal-peek-pg-queries-content.modal-content .modal-content
.modal-header .modal-header
%a.close{ href: "#", "data-dismiss" => "modal" } × %button.close.btn.btn-link.btn-sm{ type: 'button', data: { dismiss: 'modal' } } X
%h4 %h4
SQL queries SQL queries
.modal-body{ data: { defer_to: "#{view.defer_key}-queries" } }... .modal-body{ data: { defer_to: "#{view.defer_key}-queries" } }...
...@@ -111,7 +111,7 @@ module Gitlab ...@@ -111,7 +111,7 @@ module Gitlab
config.assets.precompile << "katex.css" config.assets.precompile << "katex.css"
config.assets.precompile << "katex.js" config.assets.precompile << "katex.js"
config.assets.precompile << "xterm/xterm.css" config.assets.precompile << "xterm/xterm.css"
config.assets.precompile << "peek.css" config.assets.precompile << "performance_bar.css"
config.assets.precompile << "lib/ace.js" config.assets.precompile << "lib/ace.js"
config.assets.precompile << "vendor/assets/fonts/*" config.assets.precompile << "vendor/assets/fonts/*"
config.assets.precompile << "test.css" config.assets.precompile << "test.css"
......
...@@ -74,7 +74,7 @@ var config = { ...@@ -74,7 +74,7 @@ var config = {
raven: './raven/index.js', raven: './raven/index.js',
vue_merge_request_widget: './vue_merge_request_widget/index.js', vue_merge_request_widget: './vue_merge_request_widget/index.js',
test: './test.js', test: './test.js',
peek: './peek.js', performance_bar: './performance_bar.js',
webpack_runtime: './webpack.js', webpack_runtime: './webpack.js',
}, },
......
module Gitlab module Gitlab
module PerformanceBar module PerformanceBar
def self.enabled? def self.enabled?
Feature.enabled?('gitlab_performance_bar') Rails.env.development? || Feature.enabled?('gitlab_performance_bar')
end end
end end
end end
...@@ -41,9 +41,14 @@ module Peek ...@@ -41,9 +41,14 @@ module Peek
] ]
end.sort_by{ |a,b,c,d,e,f| -f } end.sort_by{ |a,b,c,d,e,f| -f }
output = '' output = "<div class='modal-dialog modal-full'><div class='modal-content'>"
per_file.each do |file_name, lines, file_wall, file_cpu, file_idle, file_sort| output << "<div class='modal-header'>"
output << "<button class='close btn btn-link btn-sm' type='button' data-dismiss='modal'>X</button>"
output << "<h4>Line profiling: #{human_description(params[:lineprofiler])}</h4>"
output << "</div>"
output << "<div class='modal-body'>"
per_file.each do |file_name, lines, file_wall, file_cpu, file_idle, file_sort|
output << "<div class='peek-rblineprof-file'><div class='heading'>" output << "<div class='peek-rblineprof-file'><div class='heading'>"
show_src = file_sort > min show_src = file_sort > min
...@@ -86,11 +91,32 @@ module Peek ...@@ -86,11 +91,32 @@ module Peek
output << "</div></div>" # .data then .peek-rblineprof-file output << "</div></div>" # .data then .peek-rblineprof-file
end end
response.body += "<div class='peek-rblineprof-modal' id='line-profile'>#{output}</div>".html_safe output << "</div></div></div>"
response.body += "<div class='modal' id='modal-peek-line-profile' tabindex=-1>#{output}</div>".html_safe
end end
ret ret
end end
private
def human_description(lineprofiler_param)
case lineprofiler_param
when 'app'
'app/ & lib/'
when 'views'
'app/view/'
when 'gems'
'vendor/gems'
when 'all'
'everything in Rails.root'
when 'stdlib'
'everything in the Ruby standard library'
else
'app/, config/, lib/, vendor/ & plugin/'
end
end
end end
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