Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
08f4ce10
Commit
08f4ce10
authored
Sep 30, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
b4cdff15
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
442 additions
and
89 deletions
+442
-89
.gitlab/ci/qa.gitlab-ci.yml
.gitlab/ci/qa.gitlab-ci.yml
+2
-0
app/assets/javascripts/performance_bar/components/detailed_metric.vue
...avascripts/performance_bar/components/detailed_metric.vue
+14
-0
app/assets/javascripts/performance_bar/components/performance_bar_app.vue
...cripts/performance_bar/components/performance_bar_app.vue
+4
-4
app/assets/javascripts/performance_bar/components/request_selector.vue
...vascripts/performance_bar/components/request_selector.vue
+29
-0
app/assets/javascripts/performance_bar/components/request_warning.vue
...avascripts/performance_bar/components/request_warning.vue
+41
-0
app/assets/javascripts/performance_bar/index.js
app/assets/javascripts/performance_bar/index.js
+2
-2
app/assets/javascripts/performance_bar/stores/performance_bar_store.js
...vascripts/performance_bar/stores/performance_bar_store.js
+5
-3
app/models/clusters/platforms/kubernetes.rb
app/models/clusters/platforms/kubernetes.rb
+1
-0
app/views/admin/system_info/show.html.haml
app/views/admin/system_info/show.html.haml
+22
-22
changelogs/unreleased/dz-redesign-admin-system-info.yml
changelogs/unreleased/dz-redesign-admin-system-info.yml
+5
-0
changelogs/unreleased/performance-bar-warnings.yml
changelogs/unreleased/performance-bar-warnings.yml
+5
-0
doc/administration/monitoring/performance/img/performance_bar_gitaly_threshold.png
...ring/performance/img/performance_bar_gitaly_threshold.png
+0
-0
doc/administration/monitoring/performance/img/performance_bar_request_selector_warning.png
...formance/img/performance_bar_request_selector_warning.png
+0
-0
doc/administration/monitoring/performance/img/performance_bar_request_selector_warning_expanded.png
...img/performance_bar_request_selector_warning_expanded.png
+0
-0
doc/administration/monitoring/performance/performance_bar.md
doc/administration/monitoring/performance/performance_bar.md
+18
-0
locale/gitlab.pot
locale/gitlab.pot
+41
-0
spec/features/issues/issues_tabs_spec.rb
spec/features/issues/issues_tabs_spec.rb
+0
-56
spec/frontend/performance_bar/components/detailed_metric_spec.js
...ontend/performance_bar/components/detailed_metric_spec.js
+111
-0
spec/frontend/performance_bar/components/performance_bar_app_spec.js
...nd/performance_bar/components/performance_bar_app_spec.js
+20
-0
spec/frontend/performance_bar/components/request_selector_spec.js
...ntend/performance_bar/components/request_selector_spec.js
+64
-0
spec/frontend/performance_bar/components/request_warning_spec.js
...ontend/performance_bar/components/request_warning_spec.js
+33
-0
spec/support/helpers/kubernetes_helpers.rb
spec/support/helpers/kubernetes_helpers.rb
+25
-2
No files found.
.gitlab/ci/qa.gitlab-ci.yml
View file @
08f4ce10
...
...
@@ -19,6 +19,7 @@ package-and-qa-manual:
except
:
refs
:
-
master
-
/^\d+-\d+-auto-deploy-\d+$/
when
:
manual
needs
:
[
"
build-qa-image"
,
"
gitlab:assets:compile
pull-cache"
]
...
...
@@ -29,6 +30,7 @@ package-and-qa:
except
:
refs
:
-
master
-
/^\d+-\d+-auto-deploy-\d+$/
needs
:
[
"
build-qa-image"
,
"
gitlab:assets:compile
pull-cache"
]
allow_failure
:
true
...
...
app/assets/javascripts/performance_bar/components/detailed_metric.vue
View file @
08f4ce10
<
script
>
import
RequestWarning
from
'
./request_warning.vue
'
;
import
DeprecatedModal2
from
'
~/vue_shared/components/deprecated_modal_2.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
components
:
{
RequestWarning
,
GlModal
:
DeprecatedModal2
,
Icon
,
},
...
...
@@ -39,6 +42,16 @@ export default {
detailsList
()
{
return
this
.
metricDetails
.
details
;
},
warnings
()
{
return
this
.
metricDetails
.
warnings
||
[];
},
htmlId
()
{
if
(
this
.
currentRequest
)
{
return
`performance-bar-warning-
${
this
.
currentRequest
.
id
}
-
${
this
.
metric
}
`
;
}
return
''
;
},
},
};
</
script
>
...
...
@@ -105,5 +118,6 @@ export default {
<
div
slot
=
"
footer
"
><
/div
>
<
/gl-modal
>
{{
title
}}
<
request
-
warning
:
html
-
id
=
"
htmlId
"
:
warnings
=
"
warnings
"
/>
<
/div
>
<
/template
>
app/assets/javascripts/performance_bar/components/performance_bar_app.vue
View file @
08f4ce10
<
script
>
import
{
glEmojiTag
}
from
'
~/emoji
'
;
import
d
etailedMetric
from
'
./detailed_metric.vue
'
;
import
r
equestSelector
from
'
./request_selector.vue
'
;
import
D
etailedMetric
from
'
./detailed_metric.vue
'
;
import
R
equestSelector
from
'
./request_selector.vue
'
;
import
{
s__
}
from
'
~/locale
'
;
export
default
{
components
:
{
d
etailedMetric
,
r
equestSelector
,
D
etailedMetric
,
R
equestSelector
,
},
props
:
{
store
:
{
...
...
app/assets/javascripts/performance_bar/components/request_selector.vue
View file @
08f4ce10
<
script
>
import
{
glEmojiTag
}
from
'
~/emoji
'
;
import
{
n__
}
from
'
~/locale
'
;
import
{
GlPopover
}
from
'
@gitlab/ui
'
;
export
default
{
components
:
{
GlPopover
,
},
props
:
{
currentRequest
:
{
type
:
Object
,
...
...
@@ -15,6 +22,18 @@ export default {
currentRequestId
:
this
.
currentRequest
.
id
,
};
},
computed
:
{
requestsWithWarnings
()
{
return
this
.
requests
.
filter
(
request
=>
request
.
hasWarnings
);
},
warningMessage
()
{
return
n__
(
'
%d request with warnings
'
,
'
%d requests with warnings
'
,
this
.
requestsWithWarnings
.
length
,
);
},
},
watch
:
{
currentRequestId
(
newRequestId
)
{
this
.
$emit
(
'
change-current-request
'
,
newRequestId
);
...
...
@@ -31,6 +50,7 @@ export default {
return
truncated
;
},
glEmojiTag
,
},
};
</
script
>
...
...
@@ -44,7 +64,16 @@ export default {
class=
"qa-performance-bar-request"
>
{{
truncatedUrl
(
request
.
url
)
}}
<span
v-if=
"request.hasWarnings"
>
(!)
</span>
</option>
</select>
<span
v-if=
"requestsWithWarnings.length"
>
<span
id=
"performance-bar-request-selector-warning"
v-html=
"glEmojiTag('warning')"
></span>
<gl-popover
target=
"performance-bar-request-selector-warning"
:content=
"warningMessage"
triggers=
"hover focus"
/>
</span>
</div>
</
template
>
app/assets/javascripts/performance_bar/components/request_warning.vue
0 → 100644
View file @
08f4ce10
<
script
>
import
{
glEmojiTag
}
from
'
~/emoji
'
;
import
{
GlPopover
}
from
'
@gitlab/ui
'
;
export
default
{
components
:
{
GlPopover
,
},
props
:
{
htmlId
:
{
type
:
String
,
required
:
true
,
},
warnings
:
{
type
:
Array
,
required
:
true
,
},
},
computed
:
{
hasWarnings
()
{
return
this
.
warnings
&&
this
.
warnings
.
length
;
},
warningMessage
()
{
if
(
!
this
.
hasWarnings
)
{
return
''
;
}
return
this
.
warnings
.
join
(
'
\n
'
);
},
},
methods
:
{
glEmojiTag
,
},
};
</
script
>
<
template
>
<span
v-if=
"hasWarnings"
>
<span
:id=
"htmlId"
v-html=
"glEmojiTag('warning')"
></span>
<gl-popover
:target=
"htmlId"
:content=
"warningMessage"
triggers=
"hover focus"
/>
</span>
</
template
>
app/assets/javascripts/performance_bar/index.js
View file @
08f4ce10
...
...
@@ -6,7 +6,7 @@ export default ({ container }) =>
new
Vue
({
el
:
container
,
components
:
{
p
erformanceBarApp
:
()
=>
import
(
'
./components/performance_bar_app.vue
'
),
P
erformanceBarApp
:
()
=>
import
(
'
./components/performance_bar_app.vue
'
),
},
data
()
{
const
performanceBarData
=
document
.
querySelector
(
this
.
$options
.
el
).
dataset
;
...
...
@@ -41,7 +41,7 @@ export default ({ container }) =>
PerformanceBarService
.
fetchRequestDetails
(
this
.
peekUrl
,
requestId
)
.
then
(
res
=>
{
this
.
store
.
addRequestDetails
(
requestId
,
res
.
data
.
data
);
this
.
store
.
addRequestDetails
(
requestId
,
res
.
data
);
})
.
catch
(()
=>
// eslint-disable-next-line no-console
...
...
app/assets/javascripts/performance_bar/stores/performance_bar_store.js
View file @
08f4ce10
...
...
@@ -3,12 +3,13 @@ export default class PerformanceBarStore {
this
.
requests
=
[];
}
addRequest
(
requestId
,
requestUrl
,
requestDetails
)
{
addRequest
(
requestId
,
requestUrl
)
{
if
(
!
this
.
findRequest
(
requestId
))
{
this
.
requests
.
push
({
id
:
requestId
,
url
:
requestUrl
,
details
:
requestDetails
,
details
:
{},
hasWarnings
:
false
,
});
}
...
...
@@ -22,7 +23,8 @@ export default class PerformanceBarStore {
addRequestDetails
(
requestId
,
requestDetails
)
{
const
request
=
this
.
findRequest
(
requestId
);
request
.
details
=
requestDetails
;
request
.
details
=
requestDetails
.
data
;
request
.
hasWarnings
=
requestDetails
.
has_warnings
;
return
request
;
}
...
...
app/models/clusters/platforms/kubernetes.rb
View file @
08f4ce10
...
...
@@ -6,6 +6,7 @@ module Clusters
include
Gitlab
::
Kubernetes
include
EnumWithNil
include
AfterCommitQueue
include
ReactiveCaching
RESERVED_NAMESPACES
=
%w(gitlab-managed-apps)
.
freeze
...
...
app/views/admin/system_info/show.html.haml
View file @
08f4ce10
-
page_title
"System Info"
-
page_title
_
(
'System Info'
)
.prepend-top-default
.row
.col-sm
-4
.
card.
bg-light.light-well
%h4
CPU
.col-sm
.bg-light.light-well
%h4
=
_
(
'CPU'
)
.data
-
if
@cpus
%h
1
#{
@cpus
.
length
}
cores
%h
2
=
_
(
'%{cores} cores'
)
%
{
cores:
@cpus
.
length
}
-
else
=
icon
(
'warning'
,
class:
'text-warning'
)
Unable to collect CPU info
.col-sm-4
.card.bg-light.light-well
%h4
Memory Usage
=
_
(
'Unable to collect CPU info'
)
.bg-light.light-well.prepend-top-default
%h4
=
_
(
'Memory Usage'
)
.data
-
if
@memory
%h
1
#{
number_to_human_size
(
@memory
.
active_bytes
)
}
/
#{
number_to_human_size
(
@memory
.
total_bytes
)
}
%h
2
#{
number_to_human_size
(
@memory
.
active_bytes
)
}
/
#{
number_to_human_size
(
@memory
.
total_bytes
)
}
-
else
=
icon
(
'warning'
,
class:
'text-warning'
)
Unable to collect memory info
.col-sm-4
.card.bg-light.light-well
%h4
Disk Usage
=
_
(
'Unable to collect memory info'
)
.bg-light.light-well.prepend-top-default
%h4
=
_
(
'Uptime'
)
.data
-
@disks
.
each
do
|
disk
|
%h1
#{
number_to_human_size
(
disk
[
:bytes_used
])
}
/
#{
number_to_human_size
(
disk
[
:bytes_total
])
}
%p
=
disk
[
:disk_name
]
%p
=
disk
[
:mount_path
]
.col-sm-4
.card.bg-light.light-well
%h4
Uptime
%h2
=
distance_of_time_in_words_to_now
(
Rails
.
application
.
config
.
booted_at
)
.col-sm
.bg-light.light-well
%h4
=
_
(
'Disk Usage'
)
.data
%h1
=
distance_of_time_in_words_to_now
(
Rails
.
application
.
config
.
booted_at
)
%ul
-
@disks
.
each
do
|
disk
|
%li
%h2
#{
number_to_human_size
(
disk
[
:bytes_used
])
}
/
#{
number_to_human_size
(
disk
[
:bytes_total
])
}
%p
=
disk
[
:disk_name
]
%p
=
disk
[
:mount_path
]
changelogs/unreleased/dz-redesign-admin-system-info.yml
0 → 100644
View file @
08f4ce10
---
title
:
Improve admin/system_info page ui
merge_request
:
17829
author
:
type
:
changed
changelogs/unreleased/performance-bar-warnings.yml
0 → 100644
View file @
08f4ce10
---
title
:
Add warnings to performance bar when page shows signs of poor performance
merge_request
:
17612
author
:
type
:
changed
doc/administration/monitoring/performance/img/performance_bar_gitaly_threshold.png
0 → 100644
View file @
08f4ce10
63.8 KB
doc/administration/monitoring/performance/img/performance_bar_request_selector_warning.png
0 → 100644
View file @
08f4ce10
56.9 KB
doc/administration/monitoring/performance/img/performance_bar_request_selector_warning_expanded.png
0 → 100644
View file @
08f4ce10
61 KB
doc/administration/monitoring/performance/performance_bar.md
View file @
08f4ce10
...
...
@@ -21,6 +21,24 @@ 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
page was open. Only the first two requests per unique URL are captured.
## Request warnings
For requests exceeding pre-defined limits, a warning icon will be shown
next to the failing metric, along with an explanation. In this example,
the Gitaly call duration exceeded the threshold:
![
Gitaly call duration exceeded threshold
](
img/performance_bar_gitaly_threshold.png
)
If any requests on the current page generated warnings, the icon will
appear next to the request selector:
![
Request selector showing two requests with warnings
](
img/performance_bar_request_selector_warning.png
)
And requests with warnings are indicated in the request selector with a
`(!)`
after their path:
![
Request selector showing dropdown
](
img/performance_bar_request_selector_warning_expanded.png
)
## Enable the Performance Bar via the Admin panel
GitLab Performance Bar is disabled by default. To enable it for a given group,
...
...
locale/gitlab.pot
View file @
08f4ce10
...
...
@@ -150,6 +150,11 @@ msgid_plural "%d more comments"
msgstr[0] ""
msgstr[1] ""
msgid "%d request with warnings"
msgid_plural "%d requests with warnings"
msgstr[0] ""
msgstr[1] ""
msgid "%d second"
msgid_plural "%d seconds"
msgstr[0] ""
...
...
@@ -179,6 +184,9 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{cores} cores"
msgstr ""
msgid "%{count} LOC/commit"
msgstr ""
...
...
@@ -2695,6 +2703,9 @@ msgstr ""
msgid "CONTRIBUTING"
msgstr ""
msgid "CPU"
msgstr ""
msgid "Callback URL"
msgstr ""
...
...
@@ -5347,6 +5358,9 @@ msgstr ""
msgid "Discussion"
msgstr ""
msgid "Disk Usage"
msgstr ""
msgid "Dismiss"
msgstr ""
...
...
@@ -8923,6 +8937,9 @@ msgstr ""
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes API returned status code: %{error_code}"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
...
...
@@ -9654,6 +9671,9 @@ msgstr ""
msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
msgid "Memory Usage"
msgstr ""
msgid "Merge"
msgstr ""
...
...
@@ -11500,6 +11520,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
msgid "Pod not found"
msgstr ""
msgid "Pods in use"
msgstr ""
...
...
@@ -14565,6 +14588,9 @@ msgstr ""
msgid "Something went wrong on our end."
msgstr ""
msgid "Something went wrong on our end. %{message}"
msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
...
...
@@ -16779,6 +16805,12 @@ msgstr ""
msgid "Unable to build Slack link."
msgstr ""
msgid "Unable to collect CPU info"
msgstr ""
msgid "Unable to collect memory info"
msgstr ""
msgid "Unable to connect to Prometheus server"
msgstr ""
...
...
@@ -17055,6 +17087,9 @@ msgstr ""
msgid "Upstream"
msgstr ""
msgid "Uptime"
msgstr ""
msgid "Upvotes"
msgstr ""
...
...
@@ -18835,6 +18870,9 @@ msgstr ""
msgid "connecting"
msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
msgid "could not read private key, is the passphrase correct?"
msgstr ""
...
...
@@ -19405,6 +19443,9 @@ msgstr ""
msgid "pipeline"
msgstr ""
msgid "pod_name cannot be larger than %{max_length} chars"
msgstr ""
msgid "point"
msgid_plural "points"
msgstr[0] ""
...
...
spec/features/issues/issues_tabs_spec.rb
deleted
100644 → 0
View file @
b4cdff15
# frozen_string_literal: true
require
'spec_helper'
describe
'Issue page tabs'
,
:js
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:issue
)
{
create
(
:issue
,
author:
user
,
assignees:
[
user
],
project:
project
)
}
describe
'discussions tab counter'
do
before
do
stub_licensed_features
(
design_management:
true
)
stub_feature_flags
(
design_management_flag:
true
)
allow
(
Ability
).
to
receive
(
:allowed?
)
{
true
}
end
subject
do
sign_in
(
user
)
visit
project_issue_path
(
project
,
issue
)
wait_for_requests
find
(
'#discussion'
)
end
context
'new issue'
do
it
'displays count of 0'
do
is_expected
.
to
have_content
(
'Discussion 0'
)
end
end
context
'issue with 2 system notes and 1 discussion'
do
let!
(
:discussion
)
{
create
(
:discussion_note_on_issue
,
noteable:
issue
,
project:
project
,
note:
"This is good"
)
}
before
do
create
(
:system_note
,
noteable:
issue
,
project:
project
,
author:
user
,
note:
'description updated'
)
create
(
:system_note
,
noteable:
issue
,
project:
project
,
author:
user
,
note:
'description updated'
)
end
it
'displays count of 1'
do
is_expected
.
to
have_content
(
'Discussion 1'
)
end
context
'with 1 reply'
do
before
do
create
(
:note
,
noteable:
issue
,
in_reply_to:
discussion
,
discussion_id:
discussion
.
discussion_id
,
note:
'I also think this is good'
)
end
it
'displays count of 2'
do
is_expected
.
to
have_content
(
'Discussion 2'
)
end
end
end
end
end
spec/
javascripts
/performance_bar/components/detailed_metric_spec.js
→
spec/
frontend
/performance_bar/components/detailed_metric_spec.js
View file @
08f4ce10
import
Vue
from
'
vue
'
;
import
detailedMetric
from
'
~/performance_bar/components/detailed_metric
.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
DetailedMetric
from
'
~/performance_bar/components/detailed_metric.
vue
'
;
import
RequestWarning
from
'
~/performance_bar/components/request_warning
.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
describe
(
'
detailedMetric
'
,
()
=>
{
let
vm
;
afterEach
(()
=>
{
vm
.
$destroy
();
});
const
createComponent
=
props
=>
shallowMount
(
DetailedMetric
,
{
propsData
:
{
...
props
,
},
});
describe
(
'
when the current request has no details
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Vue
.
extend
(
detailedMetric
),
{
currentRequest
:
{},
metric
:
'
gitaly
'
,
header
:
'
Gitaly calls
'
,
details
:
'
details
'
,
keys
:
[
'
feature
'
,
'
request
'
],
});
const
wrapper
=
createComponent
({
currentRequest
:
{},
metric
:
'
gitaly
'
,
header
:
'
Gitaly calls
'
,
details
:
'
details
'
,
keys
:
[
'
feature
'
,
'
request
'
],
});
it
(
'
does not render the element
'
,
()
=>
{
expect
(
vm
.
$el
.
innerHTML
).
toEqual
(
undefined
);
expect
(
wrapper
.
isEmpty
()).
toBe
(
true
);
});
});
...
...
@@ -31,14 +30,15 @@ describe('detailedMetric', () => {
{
duration
:
'
23
'
,
feature
:
'
rebase_in_progress
'
,
request
:
''
,
backtrace
:
[
'
world
'
,
'
hello
'
]
},
];
beforeEach
(
()
=>
{
vm
=
mountComponent
(
Vue
.
extend
(
detailedMetric
),
{
describe
(
'
with a default metric name
'
,
()
=>
{
const
wrapper
=
createComponent
(
{
currentRequest
:
{
details
:
{
gitaly
:
{
duration
:
'
123ms
'
,
calls
:
'
456
'
,
details
:
requestDetails
,
warnings
:
[
'
gitaly calls: 456 over 30
'
],
},
},
},
...
...
@@ -46,63 +46,65 @@ describe('detailedMetric', () => {
header
:
'
Gitaly calls
'
,
keys
:
[
'
feature
'
,
'
request
'
],
});
});
it
(
'
di
plays details
'
,
()
=>
{
expect
(
vm
.
$el
.
innerText
.
replace
(
/
\s
+/g
,
'
'
)).
toContain
(
'
123ms / 456
'
);
});
it
(
'
dis
plays details
'
,
()
=>
{
expect
(
wrapper
.
text
()
.
replace
(
/
\s
+/g
,
'
'
)).
toContain
(
'
123ms / 456
'
);
});
it
(
'
adds a modal with a table of the details
'
,
()
=>
{
vm
.
$el
.
querySelector
All
(
'
.performance-bar-modal td:nth-child(1)
'
)
.
forEach
((
duration
,
index
)
=>
{
expect
(
duration
.
innerText
).
toContain
(
requestDetails
[
index
].
duration
);
});
it
(
'
adds a modal with a table of the details
'
,
()
=>
{
wrapper
.
find
All
(
'
.performance-bar-modal td:nth-child(1)
'
)
.
wrappers
.
forEach
((
duration
,
index
)
=>
{
expect
(
duration
.
text
()
).
toContain
(
requestDetails
[
index
].
duration
);
});
vm
.
$el
.
querySelector
All
(
'
.performance-bar-modal td:nth-child(2)
'
)
.
forEach
((
feature
,
index
)
=>
{
expect
(
feature
.
innerText
).
toContain
(
requestDetails
[
index
].
feature
);
});
wrapper
.
find
All
(
'
.performance-bar-modal td:nth-child(2)
'
)
.
wrappers
.
forEach
((
feature
,
index
)
=>
{
expect
(
feature
.
text
()
).
toContain
(
requestDetails
[
index
].
feature
);
});
vm
.
$el
.
querySelector
All
(
'
.performance-bar-modal td:nth-child(2)
'
)
.
forEach
((
request
,
index
)
=>
{
expect
(
request
.
innerText
).
toContain
(
requestDetails
[
index
].
request
);
});
wrapper
.
find
All
(
'
.performance-bar-modal td:nth-child(2)
'
)
.
wrappers
.
forEach
((
request
,
index
)
=>
{
expect
(
request
.
text
()
).
toContain
(
requestDetails
[
index
].
request
);
});
expect
(
vm
.
$el
.
querySelector
(
'
.text-expander.js-toggle-button
'
)).
not
.
toBeNull
();
expect
(
wrapper
.
find
(
'
.text-expander.js-toggle-button
'
)).
not
.
toBeNull
();
vm
.
$el
.
querySelectorAll
(
'
.performance-bar-modal td:nth-child(2)
'
).
forEach
(
request
=>
{
expect
(
request
.
innerText
).
toContain
(
'
world
'
);
wrapper
.
findAll
(
'
.performance-bar-modal td:nth-child(2)
'
).
wrappers
.
forEach
(
request
=>
{
expect
(
request
.
text
()).
toContain
(
'
world
'
);
});
});
});
it
(
'
displays the metric title
'
,
()
=>
{
expect
(
vm
.
$el
.
innerText
).
toContain
(
'
gitaly
'
);
it
(
'
displays the metric title
'
,
()
=>
{
expect
(
wrapper
.
text
()).
toContain
(
'
gitaly
'
);
});
it
(
'
displays request warnings
'
,
()
=>
{
expect
(
wrapper
.
find
(
RequestWarning
).
exists
()).
toBe
(
true
);
});
});
describe
(
'
when using a custom metric title
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Vue
.
extend
(
detailedMetric
),
{
currentRequest
:
{
details
:
{
gitaly
:
{
duration
:
'
123ms
'
,
calls
:
'
456
'
,
details
:
requestDetails
,
},
const
wrapper
=
createComponent
({
currentRequest
:
{
details
:
{
gitaly
:
{
duration
:
'
123ms
'
,
calls
:
'
456
'
,
details
:
requestDetails
,
},
},
metric
:
'
gitaly
'
,
title
:
'
custom
'
,
header
:
'
Gitaly calls
'
,
keys
:
[
'
feature
'
,
'
request
'
]
,
});
}
,
metric
:
'
gitaly
'
,
title
:
'
custom
'
,
header
:
'
Gitaly calls
'
,
keys
:
[
'
feature
'
,
'
request
'
],
});
it
(
'
displays the custom title
'
,
()
=>
{
expect
(
vm
.
$el
.
innerText
).
toContain
(
'
custom
'
);
expect
(
wrapper
.
text
()
).
toContain
(
'
custom
'
);
});
});
});
...
...
spec/
javascripts
/performance_bar/components/performance_bar_app_spec.js
→
spec/
frontend
/performance_bar/components/performance_bar_app_spec.js
View file @
08f4ce10
import
Vue
from
'
vue
'
;
import
performanceBarApp
from
'
~/performance_bar/components/performance_bar_app.vue
'
;
import
PerformanceBarApp
from
'
~/performance_bar/components/performance_bar_app.vue
'
;
import
PerformanceBarStore
from
'
~/performance_bar/stores/performance_bar_store
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
describe
(
'
performance bar app
'
,
()
=>
{
let
vm
;
beforeEach
(()
=>
{
const
store
=
new
PerformanceBarStore
();
vm
=
mountComponent
(
Vue
.
extend
(
performanceBarApp
),
{
const
store
=
new
PerformanceBarStore
();
const
wrapper
=
shallowMount
(
PerformanceBarApp
,
{
propsData
:
{
store
,
env
:
'
development
'
,
requestId
:
'
123
'
,
peekUrl
:
'
/-/peek/results
'
,
profileUrl
:
'
?lineprofiler=true
'
,
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
},
});
it
(
'
sets the class to match the environment
'
,
()
=>
{
expect
(
vm
.
$el
.
getAttribute
(
'
class
'
)).
toContain
(
'
development
'
);
expect
(
wrapper
.
element
.
getAttribute
(
'
class
'
)).
toContain
(
'
development
'
);
});
});
spec/
javascripts
/performance_bar/components/request_selector_spec.js
→
spec/
frontend
/performance_bar/components/request_selector_spec.js
View file @
08f4ce10
import
Vue
from
'
vue
'
;
import
requestSelector
from
'
~/performance_bar/components/request_selector.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
RequestSelector
from
'
~/performance_bar/components/request_selector.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
describe
(
'
request selector
'
,
()
=>
{
const
requests
=
[
{
id
:
'
123
'
,
url
:
'
https://gitlab.com/
'
},
{
id
:
'
123
'
,
url
:
'
https://gitlab.com/
'
,
hasWarnings
:
false
,
},
{
id
:
'
456
'
,
url
:
'
https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1
'
,
hasWarnings
:
false
,
},
{
id
:
'
789
'
,
url
:
'
https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1.json?serializer=widget
'
,
hasWarnings
:
false
,
},
{
id
:
'
abc
'
,
url
:
'
https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1/discussions.json
'
,
hasWarnings
:
true
,
},
];
let
vm
;
beforeEach
(()
=>
{
vm
=
mountComponent
(
Vue
.
extend
(
requestSelector
),
{
const
wrapper
=
shallowMount
(
RequestSelector
,
{
propsData
:
{
requests
,
currentRequest
:
requests
[
1
],
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
},
});
function
optionText
(
requestId
)
{
return
vm
.
$el
.
querySelector
(
`[value='
${
requestId
}
']`
).
innerText
.
trim
();
return
wrapper
.
find
(
`[value='
${
requestId
}
']`
)
.
text
()
.
trim
();
}
it
(
'
displays the last component of the path
'
,
()
=>
{
...
...
@@ -43,4 +50,15 @@ describe('request selector', () => {
it
(
'
ignores trailing slashes
'
,
()
=>
{
expect
(
optionText
(
requests
[
0
].
id
)).
toEqual
(
'
gitlab.com
'
);
});
it
(
'
has a warning icon if any requests have warnings
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
span > gl-emoji
'
).
element
.
dataset
.
name
).
toEqual
(
'
warning
'
);
});
it
(
'
adds a warning glyph to requests with warnings
'
,
()
=>
{
const
requestValue
=
wrapper
.
find
(
'
[value="abc"]
'
).
text
();
expect
(
requestValue
).
toContain
(
'
discussions.json
'
);
expect
(
requestValue
).
toContain
(
'
(!)
'
);
});
});
spec/frontend/performance_bar/components/request_warning_spec.js
0 → 100644
View file @
08f4ce10
import
RequestWarning
from
'
~/performance_bar/components/request_warning.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
describe
(
'
request warning
'
,
()
=>
{
const
htmlId
=
'
request-123
'
;
describe
(
'
when the request has warnings
'
,
()
=>
{
const
wrapper
=
shallowMount
(
RequestWarning
,
{
propsData
:
{
htmlId
,
warnings
:
[
'
gitaly calls: 30 over 10
'
,
'
gitaly duration: 1500 over 1000
'
],
},
});
it
(
'
adds a warning emoji with the correct ID
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
span[id]
'
).
attributes
(
'
id
'
)).
toEqual
(
htmlId
);
expect
(
wrapper
.
find
(
'
span[id] gl-emoji
'
).
element
.
dataset
.
name
).
toEqual
(
'
warning
'
);
});
});
describe
(
'
when the request does not have warnings
'
,
()
=>
{
const
wrapper
=
shallowMount
(
RequestWarning
,
{
propsData
:
{
htmlId
,
warnings
:
[],
},
});
it
(
'
does nothing
'
,
()
=>
{
expect
(
wrapper
.
isEmpty
()).
toBe
(
true
);
});
});
});
spec/support/helpers/kubernetes_helpers.rb
View file @
08f4ce10
...
...
@@ -11,6 +11,10 @@ module KubernetesHelpers
kube_response
(
kube_pods_body
)
end
def
kube_pod_response
kube_response
(
kube_pod
)
end
def
kube_logs_response
kube_response
(
kube_logs_body
)
end
...
...
@@ -63,11 +67,30 @@ module KubernetesHelpers
WebMock
.
stub_request
(
:get
,
pods_url
).
to_return
(
response
||
kube_pods_response
)
end
def
stub_kubeclient_
logs
(
pod_name
,
namespace
,
status:
nil
)
def
stub_kubeclient_
pod_details
(
pod
,
namespace
,
status:
nil
)
stub_kubeclient_discover
(
service
.
api_url
)
logs_url
=
service
.
api_url
+
"/api/v1/namespaces/
#{
namespace
}
/pods/
#{
pod_name
}
/log?tailLines=
#{
Clusters
::
Platforms
::
Kubernetes
::
LOGS_LIMIT
}
"
pod_url
=
service
.
api_url
+
"/api/v1/namespaces/
#{
namespace
}
/pods/
#{
pod
}
"
response
=
{
status:
status
}
if
status
WebMock
.
stub_request
(
:get
,
pod_url
).
to_return
(
response
||
kube_pod_response
)
end
def
stub_kubeclient_logs
(
pod_name
,
namespace
,
container:
nil
,
status:
nil
,
message:
nil
)
stub_kubeclient_discover
(
service
.
api_url
)
if
container
container_query_param
=
"container=
#{
container
}
&"
end
logs_url
=
service
.
api_url
+
"/api/v1/namespaces/
#{
namespace
}
/pods/
#{
pod_name
}
"
\
"/log?
#{
container_query_param
}
tailLines=
#{
Clusters
::
Platforms
::
Kubernetes
::
LOGS_LIMIT
}
"
if
status
response
=
{
status:
status
}
response
[
:body
]
=
{
message:
message
}.
to_json
if
message
end
WebMock
.
stub_request
(
:get
,
logs_url
).
to_return
(
response
||
kube_logs_response
)
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment