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
d774d714
Commit
d774d714
authored
Oct 05, 2018
by
Simon Knox
Committed by
Mike Greiling
Oct 05, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Resolve "Show alert thresholds on dashboard"
parent
592ff4e9
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
426 additions
and
66 deletions
+426
-66
app/assets/javascripts/monitoring/components/dashboard.vue
app/assets/javascripts/monitoring/components/dashboard.vue
+14
-0
app/assets/javascripts/monitoring/components/graph.vue
app/assets/javascripts/monitoring/components/graph.vue
+7
-2
app/assets/javascripts/monitoring/utils/multiple_time_series.js
...sets/javascripts/monitoring/utils/multiple_time_series.js
+69
-34
ee/app/assets/javascripts/monitoring/components/alert_widget.vue
...assets/javascripts/monitoring/components/alert_widget.vue
+22
-6
ee/app/assets/javascripts/monitoring/components/dashboard_mixin.js
...sets/javascripts/monitoring/components/dashboard_mixin.js
+10
-0
ee/app/assets/javascripts/monitoring/components/threshold_lines.vue
...ets/javascripts/monitoring/components/threshold_lines.vue
+88
-0
ee/changelogs/unreleased/6036-graphalerts.yml
ee/changelogs/unreleased/6036-graphalerts.yml
+5
-0
ee/spec/javascripts/monitoring/components/dashboard_spec.js
ee/spec/javascripts/monitoring/components/dashboard_spec.js
+85
-0
ee/spec/javascripts/monitoring/components/threshold_lines_spec.js
...javascripts/monitoring/components/threshold_lines_spec.js
+84
-0
spec/javascripts/monitoring/alert_widget_spec.js
spec/javascripts/monitoring/alert_widget_spec.js
+16
-1
spec/javascripts/monitoring/dashboard_spec.js
spec/javascripts/monitoring/dashboard_spec.js
+20
-18
spec/javascripts/monitoring/graph/legend_spec.js
spec/javascripts/monitoring/graph/legend_spec.js
+1
-1
spec/javascripts/monitoring/graph/track_info_spec.js
spec/javascripts/monitoring/graph/track_info_spec.js
+1
-1
spec/javascripts/monitoring/graph/track_line_spec.js
spec/javascripts/monitoring/graph/track_line_spec.js
+1
-1
spec/javascripts/monitoring/graph_path_spec.js
spec/javascripts/monitoring/graph_path_spec.js
+1
-1
spec/javascripts/monitoring/mock_data.js
spec/javascripts/monitoring/mock_data.js
+1
-0
spec/javascripts/monitoring/utils/multiple_time_series_spec.js
...javascripts/monitoring/utils/multiple_time_series_spec.js
+1
-1
No files found.
app/assets/javascripts/monitoring/components/dashboard.vue
View file @
d774d714
...
...
@@ -252,12 +252,26 @@ export default {
:small-graph=
"forceSmallGraph"
>
<!-- EE content -->
<template
slot=
"additionalSvgContent"
scope=
"
{ graphDrawData }"
>
<threshold-lines
v-for=
"(alert, alertName) in alertData[graphData.id]"
:key=
"alertName"
:operator=
"alert.operator"
:threshold=
"alert.threshold"
:graph-draw-data=
"graphDrawData"
/>
</
template
>
<alert-widget
v-if=
"alertsEndpoint && graphData.id"
:alerts-endpoint=
"alertsEndpoint"
:label=
"getGraphLabel(graphData)"
:current-alerts=
"getQueryAlerts(graphData)"
:custom-metric-id=
"graphData.id"
:alert-data=
"alertData[graphData.id]"
@
setAlerts=
"setAlerts"
/>
</graph>
</graph-group>
...
...
app/assets/javascripts/monitoring/components/graph.vue
View file @
d774d714
...
...
@@ -82,6 +82,7 @@ export default {
showFlag
:
false
,
showFlagContent
:
false
,
timeSeries
:
[],
graphDrawData
:
{},
realPixelRatio
:
1
,
seriesUnderMouse
:
[],
};
...
...
@@ -180,12 +181,12 @@ export default {
});
},
renderAxesPaths
()
{
this
.
timeSeries
=
createTimeSeries
(
({
timeSeries
:
this
.
timeSeries
,
graphDrawData
:
this
.
graphDrawData
}
=
createTimeSeries
(
this
.
graphData
.
queries
,
this
.
graphWidth
,
this
.
graphHeight
,
this
.
graphHeightOffset
,
);
)
)
;
if
(
_
.
findWhere
(
this
.
timeSeries
,
{
renderCanary
:
true
}))
{
this
.
timeSeries
=
this
.
timeSeries
.
map
(
series
=>
({
...
series
,
renderCanary
:
true
}));
...
...
@@ -288,6 +289,10 @@ export default {
:viewBox=
"innerViewBox"
class=
"graph-data"
>
<slot
name=
"additionalSvgContent"
:graphDrawData=
"graphDrawData"
/>
<graph-path
v-for=
"(path, index) in timeSeries"
:key=
"index"
...
...
app/assets/javascripts/monitoring/utils/multiple_time_series.js
View file @
d774d714
...
...
@@ -30,7 +30,7 @@ const defaultColorOrder = ['blue', 'orange', 'red', 'green', 'purple'];
const
defaultStyleOrder
=
[
'
solid
'
,
'
dashed
'
,
'
dotted
'
];
function
queryTimeSeries
(
query
,
graph
Width
,
graphHeight
,
graphHeightOffset
,
xDom
,
yDom
,
lineStyle
)
{
function
queryTimeSeries
(
query
,
graph
DrawData
,
lineStyle
)
{
let
usedColors
=
[];
let
renderCanary
=
false
;
const
timeSeriesParsed
=
[];
...
...
@@ -64,7 +64,7 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
// but we need a regularly-spaced set of time/value pairs
// this gives us a complete range of one minute intervals
// offset the same amount as the original data
const
[
minX
,
maxX
]
=
xDom
;
const
[
minX
,
maxX
]
=
graphDrawData
.
xDom
;
const
offset
=
d3
.
timeMinute
(
minX
)
-
Number
(
minX
);
const
datesWithoutGaps
=
d3
.
timeSecond
.
every
(
60
)
.
range
(
d3
.
timeMinute
.
offset
(
minX
,
-
1
),
maxX
)
...
...
@@ -84,31 +84,6 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
renderCanary
=
true
;
}
const
timeSeriesScaleX
=
d3
.
scaleTime
().
range
([
0
,
graphWidth
-
70
]);
const
timeSeriesScaleY
=
d3
.
scaleLinear
().
range
([
graphHeight
-
graphHeightOffset
,
0
]);
timeSeriesScaleX
.
domain
(
xDom
);
timeSeriesScaleX
.
ticks
(
d3
.
timeMinute
,
60
);
timeSeriesScaleY
.
domain
(
yDom
);
const
defined
=
d
=>
!
Number
.
isNaN
(
d
.
value
)
&&
d
.
value
!=
null
;
const
lineFunction
=
d3
.
line
()
.
defined
(
defined
)
.
curve
(
d3
.
curveLinear
)
// d3 v4 uses curbe instead of interpolate
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y
(
d
=>
timeSeriesScaleY
(
d
.
value
));
const
areaFunction
=
d3
.
area
()
.
defined
(
defined
)
.
curve
(
d3
.
curveLinear
)
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y0
(
graphHeight
-
graphHeightOffset
)
.
y1
(
d
=>
timeSeriesScaleY
(
d
.
value
));
const
timeSeriesMetricLabel
=
timeSeries
.
metric
[
Object
.
keys
(
timeSeries
.
metric
)[
0
]];
const
seriesCustomizationData
=
query
.
series
!=
null
&&
_
.
findWhere
(
query
.
series
[
0
].
when
,
{
value
:
timeSeriesMetricLabel
});
...
...
@@ -144,10 +119,10 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
}));
timeSeriesParsed
.
push
({
linePath
:
lineFunction
(
values
),
areaPath
:
areaFunction
(
values
),
timeSeriesScaleX
,
timeSeriesScaleY
,
linePath
:
graphDrawData
.
lineFunction
(
values
),
areaPath
:
graphDrawData
.
areaBelowLine
(
values
),
timeSeriesScaleX
:
graphDrawData
.
timeSeriesScaleX
,
timeSeriesScaleY
:
graphDrawData
.
timeSeriesScaleY
,
values
:
timeSeries
.
values
,
max
:
maximumValue
,
average
:
accum
/
timeSeries
.
values
.
length
,
...
...
@@ -164,7 +139,7 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
return
timeSeriesParsed
;
}
export
default
function
createTimeSeries
(
queries
,
graphWidth
,
graphHeight
,
graphHeightOffset
)
{
function
xyDomain
(
queries
)
{
const
allValues
=
queries
.
reduce
(
(
allQueryResults
,
query
)
=>
allQueryResults
.
concat
(
...
...
@@ -176,10 +151,70 @@ export default function createTimeSeries(queries, graphWidth, graphHeight, graph
const
xDom
=
d3
.
extent
(
allValues
,
d
=>
d
.
time
);
const
yDom
=
[
0
,
d3
.
max
(
allValues
.
map
(
d
=>
d
.
value
))];
return
queries
.
reduce
((
series
,
query
,
index
)
=>
{
return
{
xDom
,
yDom
,
};
}
export
function
generateGraphDrawData
(
queries
,
graphWidth
,
graphHeight
,
graphHeightOffset
)
{
const
{
xDom
,
yDom
}
=
xyDomain
(
queries
);
const
timeSeriesScaleX
=
d3
.
scaleTime
().
range
([
0
,
graphWidth
-
70
]);
const
timeSeriesScaleY
=
d3
.
scaleLinear
().
range
([
graphHeight
-
graphHeightOffset
,
0
]);
timeSeriesScaleX
.
domain
(
xDom
);
timeSeriesScaleX
.
ticks
(
d3
.
timeMinute
,
60
);
timeSeriesScaleY
.
domain
(
yDom
);
const
defined
=
d
=>
!
Number
.
isNaN
(
d
.
value
)
&&
d
.
value
!=
null
;
const
lineFunction
=
d3
.
line
()
.
defined
(
defined
)
.
curve
(
d3
.
curveLinear
)
// d3 v4 uses curbe instead of interpolate
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y
(
d
=>
timeSeriesScaleY
(
d
.
value
));
const
areaBelowLine
=
d3
.
area
()
.
defined
(
defined
)
.
curve
(
d3
.
curveLinear
)
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y0
(
graphHeight
-
graphHeightOffset
)
.
y1
(
d
=>
timeSeriesScaleY
(
d
.
value
));
const
areaAboveLine
=
d3
.
area
()
.
defined
(
defined
)
.
curve
(
d3
.
curveLinear
)
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y0
(
0
)
.
y1
(
d
=>
timeSeriesScaleY
(
d
.
value
));
return
{
lineFunction
,
areaBelowLine
,
areaAboveLine
,
xDom
,
yDom
,
timeSeriesScaleX
,
timeSeriesScaleY
,
};
}
export
default
function
createTimeSeries
(
queries
,
graphWidth
,
graphHeight
,
graphHeightOffset
)
{
const
graphDrawData
=
generateGraphDrawData
(
queries
,
graphWidth
,
graphHeight
,
graphHeightOffset
);
const
timeSeries
=
queries
.
reduce
((
series
,
query
,
index
)
=>
{
const
lineStyle
=
defaultStyleOrder
[
index
%
defaultStyleOrder
.
length
];
return
series
.
concat
(
queryTimeSeries
(
query
,
graph
Width
,
graphHeight
,
graphHeightOffset
,
xDom
,
yDom
,
lineStyle
),
queryTimeSeries
(
query
,
graph
DrawData
,
lineStyle
),
);
},
[]);
return
{
timeSeries
,
graphDrawData
,
};
}
ee/app/assets/javascripts/monitoring/components/alert_widget.vue
View file @
d774d714
...
...
@@ -28,6 +28,11 @@ export default {
require
:
false
,
default
:
null
,
},
alertData
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
({}),
},
},
data
()
{
return
{
...
...
@@ -36,7 +41,6 @@ export default {
isLoading
:
false
,
isOpen
:
false
,
alerts
:
this
.
currentAlerts
,
alertData
:
{},
};
},
computed
:
{
...
...
@@ -59,7 +63,7 @@ export default {
:
s__
(
'
PrometheusAlerts|Add alert
'
);
},
hasAlerts
()
{
return
this
.
alerts
.
length
>
0
;
return
Object
.
keys
(
this
.
alertData
)
.
length
>
0
;
},
firstAlert
()
{
return
this
.
hasAlerts
?
this
.
alerts
[
0
]
:
undefined
;
...
...
@@ -95,7 +99,12 @@ export default {
this
.
alerts
.
map
(
alertPath
=>
this
.
service
.
readAlert
(
alertPath
)
.
then
(
alertData
=>
this
.
$set
(
this
.
alertData
,
alertPath
,
alertData
)),
.
then
(
alertData
=>
{
this
.
$emit
(
'
setAlerts
'
,
this
.
customMetricId
,
{
...
this
.
alertData
,
[
alertPath
]:
alertData
,
});
}),
),
)
.
then
(()
=>
{
...
...
@@ -125,7 +134,10 @@ export default {
.
then
(
response
=>
{
const
alertPath
=
response
.
alert_path
;
this
.
alerts
.
unshift
(
alertPath
);
this
.
$set
(
this
.
alertData
,
alertPath
,
newAlert
);
this
.
$emit
(
'
setAlerts
'
,
this
.
customMetricId
,
{
...
this
.
alertData
,
[
alertPath
]:
newAlert
,
});
this
.
isLoading
=
false
;
this
.
handleDropdownClose
();
})
...
...
@@ -140,7 +152,10 @@ export default {
this
.
service
.
updateAlert
(
alert
,
updatedAlert
)
.
then
(()
=>
{
this
.
$set
(
this
.
alertData
,
alert
,
updatedAlert
);
this
.
$emit
(
'
setAlerts
'
,
this
.
customMetricId
,
{
...
this
.
alertData
,
[
alert
]:
updatedAlert
,
});
this
.
isLoading
=
false
;
this
.
handleDropdownClose
();
})
...
...
@@ -154,7 +169,8 @@ export default {
this
.
service
.
deleteAlert
(
alert
)
.
then
(()
=>
{
this
.
$delete
(
this
.
alertData
,
alert
);
const
{
[
alert
]:
_
,
...
otherItems
}
=
this
.
alertData
;
this
.
$emit
(
'
setAlerts
'
,
this
.
customMetricId
,
otherItems
);
this
.
alerts
=
this
.
alerts
.
filter
(
alertPath
=>
alert
!==
alertPath
);
this
.
isLoading
=
false
;
this
.
handleDropdownClose
();
...
...
ee/app/assets/javascripts/monitoring/components/dashboard_mixin.js
View file @
d774d714
import
AlertWidget
from
'
./alert_widget.vue
'
;
import
ThresholdLines
from
'
./threshold_lines.vue
'
;
export
default
{
components
:
{
AlertWidget
,
ThresholdLines
,
},
props
:
{
alertsEndpoint
:
{
...
...
@@ -11,6 +13,11 @@ export default {
default
:
null
,
},
},
data
()
{
return
{
alertData
:
{},
};
},
methods
:
{
getGraphLabel
(
graphData
)
{
if
(
!
graphData
.
queries
||
!
graphData
.
queries
[
0
])
return
undefined
;
...
...
@@ -20,5 +27,8 @@ export default {
if
(
!
graphData
.
queries
)
return
[];
return
graphData
.
queries
.
map
(
query
=>
query
.
alert_path
).
filter
(
Boolean
);
},
setAlerts
(
metricId
,
alertData
)
{
this
.
$set
(
this
.
alertData
,
metricId
,
alertData
);
},
},
};
ee/app/assets/javascripts/monitoring/components/threshold_lines.vue
0 → 100644
View file @
d774d714
<
script
>
const
red50
=
'
#fef6f5
'
;
const
red400
=
'
#e05842
'
;
export
default
{
props
:
{
operator
:
{
type
:
String
,
required
:
true
,
validator
:
val
=>
[
'
=
'
,
'
<
'
,
'
>
'
].
includes
(
val
),
},
threshold
:
{
type
:
Number
,
required
:
true
,
},
graphDrawData
:
{
type
:
Object
,
required
:
true
,
},
},
computed
:
{
thresholdData
()
{
if
(
!
this
.
graphDrawData
.
xDom
)
{
return
[];
}
const
[
xMin
,
xMax
]
=
this
.
graphDrawData
.
xDom
;
const
[
yMin
,
yMax
]
=
this
.
graphDrawData
.
yDom
;
const
outOfRange
=
(
this
.
operator
===
'
>
'
&&
this
.
threshold
>
yMax
)
||
(
this
.
operator
===
'
<
'
&&
this
.
threshold
<
yMin
);
if
(
outOfRange
)
{
return
[];
}
return
[
{
time
:
xMin
,
value
:
this
.
threshold
},
{
time
:
xMax
,
value
:
this
.
threshold
},
];
},
linePath
()
{
if
(
!
this
.
graphDrawData
.
lineFunction
)
{
return
''
;
}
return
this
.
graphDrawData
.
lineFunction
(
this
.
thresholdData
);
},
areaPath
()
{
if
(
this
.
operator
===
'
>
'
)
{
if
(
!
this
.
graphDrawData
.
areaAboveLine
)
{
return
''
;
}
return
this
.
graphDrawData
.
areaAboveLine
(
this
.
thresholdData
);
}
else
if
(
this
.
operator
===
'
<
'
)
{
if
(
!
this
.
graphDrawData
.
areaBelowLine
)
{
return
''
;
}
return
this
.
graphDrawData
.
areaBelowLine
(
this
.
thresholdData
);
}
return
''
;
},
},
created
()
{
this
.
red50
=
red50
;
this
.
red400
=
red400
;
},
};
</
script
>
<
template
>
<g
v-if=
"thresholdData.length"
transform=
"translate(-5, 20)"
class=
"js-threshold-lines"
>
<path
v-if=
"areaPath"
:d=
"areaPath"
:fill=
"red50"
/>
<path
:d=
"linePath"
fill=
"none"
:stroke=
"red400"
stroke-width=
"1"
stroke-dasharray=
"solid"
/>
</g>
</
template
>
ee/changelogs/unreleased/6036-graphalerts.yml
0 → 100644
View file @
d774d714
---
title
:
Show Alert Thresholds on monitoring dashboards
merge_request
:
7538
author
:
type
:
added
ee/spec/javascripts/monitoring/components/dashboard_spec.js
0 → 100644
View file @
d774d714
import
Vue
from
'
vue
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
Dashboard
from
'
~/monitoring/components/dashboard.vue
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
{
metricsGroupsAPIResponse
,
mockApiEndpoint
}
from
'
spec/monitoring/mock_data
'
;
import
propsData
from
'
spec/monitoring/dashboard_spec
'
;
describe
(
'
Dashboard
'
,
()
=>
{
let
Component
;
let
mock
;
let
vm
;
beforeEach
(()
=>
{
setFixtures
(
`
<div class="prometheus-graphs"></div>
<div class="nav-sidebar"></div>
`
);
mock
=
new
MockAdapter
(
axios
);
Component
=
Vue
.
extend
(
Dashboard
);
});
afterEach
(()
=>
{
mock
.
restore
();
});
describe
(
'
metrics without alerts
'
,
()
=>
{
it
(
'
does not show threshold lines
'
,
(
done
)
=>
{
vm
=
new
Component
({
el
:
document
.
querySelector
(
'
.prometheus-graphs
'
),
propsData
:
{
...
propsData
,
hasMetrics
:
true
,
},
});
setTimeout
(()
=>
{
expect
(
vm
.
$el
).
not
.
toContainElement
(
'
.js-threshold-lines
'
);
done
();
});
});
});
describe
(
'
metrics with alert
'
,
()
=>
{
const
metricId
=
5
;
const
alertParams
=
{
operator
:
'
<
'
,
threshold
:
4
,
prometheus_metric_id
:
metricId
,
};
beforeEach
(()
=>
{
mock
.
onGet
(
mockApiEndpoint
).
reply
(
200
,
metricsGroupsAPIResponse
);
vm
=
new
Component
({
el
:
document
.
querySelector
(
'
.prometheus-graphs
'
),
propsData
:
{
...
propsData
,
hasMetrics
:
true
,
},
});
});
it
(
'
shows single threshold line
'
,
(
done
)
=>
{
vm
.
setAlerts
(
metricId
,
{
alertName
:
alertParams
,
});
setTimeout
(()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-threshold-lines
'
).
length
).
toEqual
(
1
);
done
();
});
});
it
(
'
shows multiple threshold lines
'
,
(
done
)
=>
{
vm
.
setAlerts
(
metricId
,
{
someAlert
:
alertParams
,
otherAlert
:
alertParams
,
});
setTimeout
(()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-threshold-lines
'
).
length
).
toEqual
(
2
);
done
();
});
});
});
});
ee/spec/javascripts/monitoring/components/threshold_lines_spec.js
0 → 100644
View file @
d774d714
import
Vue
from
'
vue
'
;
import
ThresholdLines
from
'
ee/monitoring/components/threshold_lines.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
generateGraphDrawData
}
from
'
~/monitoring/utils/multiple_time_series
'
;
import
{
singleRowMetricsMultipleSeries
,
convertDatesMultipleSeries
}
from
'
spec/monitoring/mock_data
'
;
const
width
=
500
;
const
height
=
200
;
const
heightOffset
=
50
;
describe
(
'
ThresholdLines
'
,
()
=>
{
let
Component
;
let
vm
;
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
{
queries
}
=
convertedMetrics
[
0
];
const
graphDrawData
=
generateGraphDrawData
(
queries
,
width
,
height
,
heightOffset
);
beforeEach
(()
=>
{
Component
=
Vue
.
extend
(
ThresholdLines
);
spyOn
(
graphDrawData
,
'
areaAboveLine
'
).
and
.
callThrough
();
spyOn
(
graphDrawData
,
'
areaBelowLine
'
).
and
.
callThrough
();
spyOn
(
graphDrawData
,
'
lineFunction
'
).
and
.
callThrough
();
});
describe
(
'
< alerts
'
,
()
=>
{
beforeEach
(()
=>
{
const
props
=
{
operator
:
'
<
'
,
threshold
:
0.6
,
graphDrawData
,
};
vm
=
mountComponent
(
Component
,
props
);
});
it
(
'
fills area
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
path
'
).
length
).
toEqual
(
2
);
expect
(
graphDrawData
.
areaBelowLine
).
toHaveBeenCalled
();
expect
(
graphDrawData
.
lineFunction
).
toHaveBeenCalled
();
});
});
describe
(
'
> alerts
'
,
()
=>
{
it
(
'
fills area
'
,
()
=>
{
const
props
=
{
operator
:
'
>
'
,
threshold
:
0.6
,
graphDrawData
,
};
vm
=
mountComponent
(
Component
,
props
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
path
'
).
length
).
toEqual
(
2
);
expect
(
graphDrawData
.
areaAboveLine
).
toHaveBeenCalled
();
expect
(
graphDrawData
.
lineFunction
).
toHaveBeenCalled
();
});
it
(
'
hides area if threshold out of range
'
,
()
=>
{
const
props
=
{
operator
:
'
>
'
,
threshold
:
1000
,
graphDrawData
,
};
vm
=
mountComponent
(
Component
,
props
);
expect
(
vm
.
$el
.
innerHTML
).
not
.
toBeDefined
();
expect
(
graphDrawData
.
areaAboveLine
).
not
.
toHaveBeenCalled
();
expect
(
graphDrawData
.
lineFunction
).
not
.
toHaveBeenCalled
();
});
});
describe
(
'
= alerts
'
,
()
=>
{
it
(
'
draws line only
'
,
()
=>
{
const
props
=
{
operator
:
'
=
'
,
threshold
:
0.6
,
graphDrawData
,
};
vm
=
mountComponent
(
Component
,
props
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
path
'
).
length
).
toEqual
(
1
);
expect
(
graphDrawData
.
lineFunction
).
toHaveBeenCalled
();
});
});
});
spec/javascripts/monitoring/alert_widget_spec.js
View file @
d774d714
...
...
@@ -13,6 +13,11 @@ describe('AlertWidget', () => {
currentAlerts
:
[
'
my/alert.json
'
],
};
const
mockSetAlerts
=
(
_
,
data
)
=>
{
/* eslint-disable-next-line no-underscore-dangle */
Vue
.
set
(
vm
.
_props
,
'
alertData
'
,
data
);
};
beforeAll
(()
=>
{
AlertWidgetComponent
=
Vue
.
extend
(
AlertWidget
);
});
...
...
@@ -69,7 +74,11 @@ describe('AlertWidget', () => {
spyOn
(
AlertsService
.
prototype
,
'
readAlert
'
).
and
.
returnValue
(
Promise
.
resolve
({
operator
:
'
>
'
,
threshold
:
42
}),
);
vm
=
mountComponent
(
AlertWidgetComponent
,
props
,
'
#alert-widget
'
);
const
propsWithAlertData
=
{
...
props
,
alertData
:
{
'
my/alert.json
'
:
{
operator
:
'
>
'
,
threshold
:
42
}
},
};
vm
=
mountComponent
(
AlertWidgetComponent
,
propsWithAlertData
,
'
#alert-widget
'
);
setTimeout
(()
=>
vm
.
$nextTick
(()
=>
{
...
...
@@ -140,6 +149,8 @@ describe('AlertWidget', () => {
);
vm
=
mountComponent
(
AlertWidgetComponent
,
{
...
props
,
currentAlerts
:
[]
});
vm
.
$on
(
'
setAlerts
'
,
mockSetAlerts
);
vm
.
$refs
.
widgetForm
.
$emit
(
'
create
'
,
alertParams
);
expect
(
AlertsService
.
prototype
.
createAlert
).
toHaveBeenCalledWith
(
alertParams
);
...
...
@@ -161,6 +172,8 @@ describe('AlertWidget', () => {
spyOn
(
AlertsService
.
prototype
,
'
updateAlert
'
).
and
.
returnValue
(
Promise
.
resolve
());
vm
=
mountComponent
(
AlertWidgetComponent
,
{
...
props
,
currentAlerts
:
[
alertPath
]
});
vm
.
$on
(
'
setAlerts
'
,
mockSetAlerts
);
vm
.
$refs
.
widgetForm
.
$emit
(
'
update
'
,
{
...
alertParams
,
alert
:
alertPath
,
...
...
@@ -191,6 +204,8 @@ describe('AlertWidget', () => {
spyOn
(
AlertsService
.
prototype
,
'
deleteAlert
'
).
and
.
returnValue
(
Promise
.
resolve
());
vm
=
mountComponent
(
AlertWidgetComponent
,
{
...
props
,
currentAlerts
:
[
alertPath
]
});
vm
.
$on
(
'
setAlerts
'
,
mockSetAlerts
);
vm
.
$refs
.
widgetForm
.
$emit
(
'
delete
'
,
{
alert
:
alertPath
});
expect
(
AlertsService
.
prototype
.
deleteAlert
).
toHaveBeenCalledWith
(
alertPath
);
...
...
spec/javascripts/monitoring/dashboard_spec.js
View file @
d774d714
...
...
@@ -4,30 +4,32 @@ import Dashboard from '~/monitoring/components/dashboard.vue';
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
{
metricsGroupsAPIResponse
,
mockApiEndpoint
,
environmentData
}
from
'
./mock_data
'
;
const
propsData
=
{
hasMetrics
:
false
,
documentationPath
:
'
/path/to/docs
'
,
settingsPath
:
'
/path/to/settings
'
,
clustersPath
:
'
/path/to/clusters
'
,
tagsPath
:
'
/path/to/tags
'
,
projectPath
:
'
/path/to/project
'
,
metricsEndpoint
:
mockApiEndpoint
,
deploymentEndpoint
:
null
,
emptyGettingStartedSvgPath
:
'
/path/to/getting-started.svg
'
,
emptyLoadingSvgPath
:
'
/path/to/loading.svg
'
,
emptyNoDataSvgPath
:
'
/path/to/no-data.svg
'
,
emptyUnableToConnectSvgPath
:
'
/path/to/unable-to-connect.svg
'
,
environmentsEndpoint
:
'
/root/hello-prometheus/environments/35
'
,
currentEnvironmentName
:
'
production
'
,
};
export
default
propsData
;
describe
(
'
Dashboard
'
,
()
=>
{
let
DashboardComponent
;
const
propsData
=
{
hasMetrics
:
false
,
documentationPath
:
'
/path/to/docs
'
,
settingsPath
:
'
/path/to/settings
'
,
clustersPath
:
'
/path/to/clusters
'
,
tagsPath
:
'
/path/to/tags
'
,
projectPath
:
'
/path/to/project
'
,
metricsEndpoint
:
mockApiEndpoint
,
deploymentEndpoint
:
null
,
emptyGettingStartedSvgPath
:
'
/path/to/getting-started.svg
'
,
emptyLoadingSvgPath
:
'
/path/to/loading.svg
'
,
emptyNoDataSvgPath
:
'
/path/to/no-data.svg
'
,
emptyUnableToConnectSvgPath
:
'
/path/to/unable-to-connect.svg
'
,
environmentsEndpoint
:
'
/root/hello-prometheus/environments/35
'
,
currentEnvironmentName
:
'
production
'
,
};
beforeEach
(()
=>
{
setFixtures
(
`
<div class="prometheus-graphs"></div>
<div class="nav-sidebar"></div>
<div class="nav-sidebar"></div>
`
);
DashboardComponent
=
Vue
.
extend
(
Dashboard
);
});
...
...
spec/javascripts/monitoring/graph/legend_spec.js
View file @
d774d714
...
...
@@ -8,7 +8,7 @@ const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeri
const
defaultValuesComponent
=
{};
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
500
,
300
,
120
);
const
{
timeSeries
}
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
500
,
300
,
120
);
defaultValuesComponent
.
timeSeries
=
timeSeries
;
...
...
spec/javascripts/monitoring/graph/track_info_spec.js
View file @
d774d714
...
...
@@ -5,7 +5,7 @@ import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import
{
singleRowMetricsMultipleSeries
,
convertDatesMultipleSeries
}
from
'
../mock_data
'
;
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
500
,
300
,
120
);
const
{
timeSeries
}
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
500
,
300
,
120
);
describe
(
'
TrackInfo component
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/monitoring/graph/track_line_spec.js
View file @
d774d714
...
...
@@ -5,7 +5,7 @@ import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import
{
singleRowMetricsMultipleSeries
,
convertDatesMultipleSeries
}
from
'
../mock_data
'
;
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
500
,
300
,
120
);
const
{
timeSeries
}
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
500
,
300
,
120
);
describe
(
'
TrackLine component
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/monitoring/graph_path_spec.js
View file @
d774d714
...
...
@@ -13,7 +13,7 @@ const createComponent = (propsData) => {
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
428
,
272
,
120
);
const
{
timeSeries
}
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
428
,
272
,
120
);
const
firstTimeSeries
=
timeSeries
[
0
];
describe
(
'
Monitoring Paths
'
,
()
=>
{
...
...
spec/javascripts/monitoring/mock_data.js
View file @
d774d714
...
...
@@ -8,6 +8,7 @@ export const metricsGroupsAPIResponse = {
priority
:
1
,
metrics
:
[
{
id
:
5
,
title
:
'
Memory usage
'
,
weight
:
1
,
queries
:
[
...
...
spec/javascripts/monitoring/utils/multiple_time_series_spec.js
View file @
d774d714
...
...
@@ -2,7 +2,7 @@ import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import
{
convertDatesMultipleSeries
,
singleRowMetricsMultipleSeries
}
from
'
../mock_data
'
;
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
428
,
272
,
120
);
const
{
timeSeries
}
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
,
428
,
272
,
120
);
const
firstTimeSeries
=
timeSeries
[
0
];
describe
(
'
Multiple time series
'
,
()
=>
{
...
...
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