Commit be54e55c authored by Sean McGivern's avatar Sean McGivern

Allow adding requests to performance bar manually

Add a '+' button in the performance bar. When clicked, it allows you to
enter a request ID or a URL. A request ID will fetch performance bar
results for that request, and a URL will fetch that URL and then its
performance bar data.

Because of the way it's triggered, the URL will use the current user's
credentials, and it must be to a JSON endpoint - that's the content type
it will request. A request ID can be for any request (HTML, JSON, XML,
images) and can be for any user.
parent bf02f772
import { __ } from '~/locale';
<script>
export default {
data() {
return {
inputEnabled: false,
urlOrRequestId: '',
};
},
methods: {
toggleInput() {
this.inputEnabled = !this.inputEnabled;
},
addRequest() {
this.$emit('add-request', this.urlOrRequestId);
this.clearForm();
},
clearForm() {
this.urlOrRequestId = '';
this.toggleInput();
},
},
};
</script>
<template>
<div id="peek-view-add-request" class="view">
<form class="form-inline" @submit.prevent>
<button
class="btn-blank btn-link bold"
type="button"
:title="__(`Add request manually`)"
@click="toggleInput"
>
+
</button>
<input
v-if="inputEnabled"
v-model="urlOrRequestId"
type="text"
:placeholder="__(`URL or request ID`)"
class="form-control form-control-sm d-inline-block ml-1"
@keyup.enter="addRequest"
@keyup.esc="clearForm"
/>
</form>
</div>
</template>
<script> <script>
import { glEmojiTag } from '~/emoji'; import { glEmojiTag } from '~/emoji';
import AddRequest from './add_request.vue';
import DetailedMetric from './detailed_metric.vue'; import DetailedMetric from './detailed_metric.vue';
import RequestSelector from './request_selector.vue'; import RequestSelector from './request_selector.vue';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
export default { export default {
components: { components: {
AddRequest,
DetailedMetric, DetailedMetric,
RequestSelector, RequestSelector,
}, },
...@@ -118,6 +120,7 @@ export default { ...@@ -118,6 +120,7 @@ export default {
> >
<a :href="currentRequest.details.tracing.tracing_url">{{ s__('PerformanceBar|trace') }}</a> <a :href="currentRequest.details.tracing.tracing_url">{{ s__('PerformanceBar|trace') }}</a>
</div> </div>
<add-request v-on="$listeners" />
<request-selector <request-selector
v-if="currentRequest" v-if="currentRequest"
:current-request="currentRequest" :current-request="currentRequest"
......
import Vue from 'vue'; import Vue from 'vue';
import axios from '~/lib/utils/axios_utils';
import PerformanceBarService from './services/performance_bar_service'; import PerformanceBarService from './services/performance_bar_service';
import PerformanceBarStore from './stores/performance_bar_store'; import PerformanceBarStore from './stores/performance_bar_store';
...@@ -32,6 +34,15 @@ export default ({ container }) => ...@@ -32,6 +34,15 @@ export default ({ container }) =>
PerformanceBarService.removeInterceptor(this.interceptor); PerformanceBarService.removeInterceptor(this.interceptor);
}, },
methods: { methods: {
addRequestManually(urlOrRequestId) {
if (urlOrRequestId.startsWith('https://') || urlOrRequestId.startsWith('http://')) {
// We don't need to do anything with the response, we just
// want to trace the request.
axios.get(urlOrRequestId);
} else {
this.loadRequestDetails(urlOrRequestId, urlOrRequestId);
}
},
loadRequestDetails(requestId, requestUrl) { loadRequestDetails(requestId, requestUrl) {
if (!this.store.canTrackRequest(requestUrl)) { if (!this.store.canTrackRequest(requestUrl)) {
return; return;
...@@ -58,6 +69,9 @@ export default ({ container }) => ...@@ -58,6 +69,9 @@ export default ({ container }) =>
peekUrl: this.peekUrl, peekUrl: this.peekUrl,
profileUrl: this.profileUrl, profileUrl: this.profileUrl,
}, },
on: {
'add-request': this.addRequestManually,
},
}); });
}, },
}); });
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
width: 200px; width: 200px;
} }
input {
color: $gl-gray-400;
width: $input-short-width - 60px;
}
&.disabled { &.disabled {
display: none; display: none;
} }
...@@ -25,7 +30,8 @@ ...@@ -25,7 +30,8 @@
&.production { &.production {
background-color: $perf-bar-production; background-color: $perf-bar-production;
select { select,
input {
background: $perf-bar-production; background: $perf-bar-production;
} }
} }
...@@ -33,7 +39,8 @@ ...@@ -33,7 +39,8 @@
&.staging { &.staging {
background-color: $perf-bar-staging; background-color: $perf-bar-staging;
select { select,
input {
background: $perf-bar-staging; background: $perf-bar-staging;
} }
} }
...@@ -41,7 +48,8 @@ ...@@ -41,7 +48,8 @@
&.development { &.development {
background-color: $perf-bar-development; background-color: $perf-bar-development;
select { select,
input {
background: $perf-bar-development; background: $perf-bar-development;
} }
} }
......
---
title: Allow adding requests to performance bar manually
merge_request: 18464
author:
type: other
...@@ -8,14 +8,17 @@ activated, it looks as follows: ...@@ -8,14 +8,17 @@ activated, it looks as follows:
It allows you to see (from left to right): It allows you to see (from left to right):
- the current host serving the page - the current host serving the page
- time taken and number of DB queries, click through for details of these queries - time taken and number of DB queries; click through for details of these queries
![SQL profiling using the Performance Bar](img/performance_bar_sql_queries.png) ![SQL profiling using the Performance Bar](img/performance_bar_sql_queries.png)
- time taken and number of [Gitaly] calls, click through for details of these calls - time taken and number of [Gitaly] calls; click through for details of these calls
![Gitaly profiling using the Performance Bar](img/performance_bar_gitaly_calls.png) ![Gitaly profiling using the Performance Bar](img/performance_bar_gitaly_calls.png)
- time taken and number of [Rugged] calls, click through for details of these calls - time taken and number of [Rugged] calls; click through for details of these calls
![Rugged profiling using the Performance Bar](img/performance_bar_rugged_calls.png) ![Rugged profiling using the Performance Bar](img/performance_bar_rugged_calls.png)
- time taken and number of Redis calls, click through for details of these calls - time taken and number of Redis calls; click through for details of these calls
![Redis profiling using the Performance Bar](img/performance_bar_redis_calls.png) ![Redis profiling using the Performance Bar](img/performance_bar_redis_calls.png)
- a link to add a request's details to the performance bar; the request can be
added by its full URL (authenticated as the current user), or by the value of
its `X-Request-Id` header
On the far right is a request selector that allows you to view the same metrics On the far right is a request selector that allows you to view the same metrics
(excluding the page timing and line profiler) for any requests made while the (excluding the page timing and line profiler) for any requests made while the
......
...@@ -979,6 +979,9 @@ msgstr "" ...@@ -979,6 +979,9 @@ msgstr ""
msgid "Add reaction" msgid "Add reaction"
msgstr "" msgstr ""
msgid "Add request manually"
msgstr ""
msgid "Add to Slack" msgid "Add to Slack"
msgstr "" msgstr ""
...@@ -17575,6 +17578,9 @@ msgstr "" ...@@ -17575,6 +17578,9 @@ msgstr ""
msgid "URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...)." msgid "URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...)."
msgstr "" msgstr ""
msgid "URL or request ID"
msgstr ""
msgid "Unable to apply suggestions to a deleted line." msgid "Unable to apply suggestions to a deleted line."
msgstr "" msgstr ""
......
import AddRequest from '~/performance_bar/components/add_request.vue';
import { shallowMount } from '@vue/test-utils';
describe('add request form', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(AddRequest);
});
afterEach(() => {
wrapper.destroy();
});
it('hides the input on load', () => {
expect(wrapper.find('input').exists()).toBe(false);
});
describe('when clicking the button', () => {
beforeEach(() => {
wrapper.find('button').trigger('click');
});
it('shows the form', () => {
expect(wrapper.find('input').exists()).toBe(true);
});
describe('when pressing escape', () => {
beforeEach(() => {
wrapper.find('input').trigger('keyup.esc');
});
it('hides the input', () => {
expect(wrapper.find('input').exists()).toBe(false);
});
});
describe('when submitting the form', () => {
beforeEach(() => {
wrapper.find('input').setValue('http://gitlab.example.com/users/root/calendar.json');
wrapper.find('input').trigger('keyup.enter');
});
it('emits an event to add the request', () => {
expect(wrapper.emitted()['add-request']).toBeTruthy();
expect(wrapper.emitted()['add-request'][0]).toEqual([
'http://gitlab.example.com/users/root/calendar.json',
]);
});
it('hides the input', () => {
expect(wrapper.find('input').exists()).toBe(false);
});
it('clears the value for next time', () => {
wrapper.find('button').trigger('click');
expect(wrapper.find('input').text()).toEqual('');
});
});
});
});
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