[Status] Fixed some bugs, moved some things around generally improved code, Also fixed watch task for status plugin css
This commit is contained in:
parent
8d33e9f039
commit
0936b0340c
8
src/server/plugins/status/public/chartTemplate.html
Normal file
8
src/server/plugins/status/public/chartTemplate.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="status_chart_wrapper col-md-4">
|
||||||
|
<h3 class="title">{{chart.niceName}}</h3>
|
||||||
|
<h4 class="average">
|
||||||
|
<span ng-repeat="average in chart.average track by $index"><span ng-if="$index">, </span>{{average}}</span>
|
||||||
|
</h4>
|
||||||
|
<nvd3 options="chart.options" data="chart.data"></nvd3>
|
||||||
|
</h4>
|
||||||
|
</div>
|
|
@ -5,8 +5,8 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/styles/theme/elk.ico">
|
<link rel="shortcut icon" href="/styles/theme/elk.ico">
|
||||||
|
<link rel="stylesheet" href="/status/styles/main.css?_b=@@buildNum">
|
||||||
<link rel="stylesheet" href="/styles/main.css?_b=@@buildNum">
|
<link rel="stylesheet" href="/styles/main.css?_b=@@buildNum">
|
||||||
<link rel="stylesheet" href="styles/main.css?_b=@@buildNum">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container" ng-controller="StatusPage">
|
<div class="container" ng-controller="StatusPage">
|
||||||
|
@ -27,13 +27,13 @@
|
||||||
</h3>
|
</h3>
|
||||||
<div id="plugin_table">
|
<div id="plugin_table">
|
||||||
<div class="plugin_table_header plugin_row">
|
<div class="plugin_table_header plugin_row">
|
||||||
<div class="col-md-1 plugin_key">Plugin</div>
|
<div class="col-md-1 col-sm-2 col-xs-4 plugin_key">Plugin</div>
|
||||||
<div class="col-md-11 plugin_state">Status</div>
|
<div class="col-md-11 col-sm-10 col-xs-8 plugin_state">Status</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-repeat="(key, plugin) in ui.plugins" class="plugin_table_plugin plugin_row plugin_status_{{plugin.uiStatus}}">
|
<div ng-repeat="(key, plugin) in ui.plugins" class="plugin_table_plugin plugin_row plugin_status_{{plugin.uiStatus}}">
|
||||||
<div class="col-md-1 plugin_key">{{key}}</div>
|
<div class="col-md-1 col-sm-2 col-xs-4 plugin_key">{{key}}</div>
|
||||||
<div class="col-md-11 plugin_state">{{plugin.message}}</div>
|
<div class="col-md-11 col-sm-10 col-xs-8 plugin_state">{{plugin.message}}</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,14 +41,9 @@
|
||||||
<h2>Server Metrics</h2>
|
<h2>Server Metrics</h2>
|
||||||
<p>Interval of 5 seconds, with a max history of 5 minutes.</p>
|
<p>Interval of 5 seconds, with a max history of 5 minutes.</p>
|
||||||
<div id="chart_cont" class="row">
|
<div id="chart_cont" class="row">
|
||||||
<div ng-repeat="(key, chart) in ui.charts" class="status_chart_wrapper col-md-4">
|
<div ng-repeat="(key, chart) in ui.charts">
|
||||||
<h3 class="title">{{chart.niceName}}</h2>
|
<kb-sparkline chart-data="ui.charts[key].data" chart-key="key"></kb-sparkline>
|
||||||
<h4 class="average">
|
|
||||||
<span ng-repeat="average in chart.average track by $index"><span ng-if="$index">, </span>{{average}}</span>
|
|
||||||
</h4>
|
|
||||||
<nvd3 options="chart.options" data="chart.data"></nvd3>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer></footer>
|
<footer></footer>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directives'],
|
window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'text!status/chartTemplate.html', 'nvd3_directives'],
|
||||||
function (angular, $, _, moment, numeral) {
|
function (angular, $, _, moment, numeral, chartTemplate) {
|
||||||
|
|
||||||
// Make sure we don't have to deal with statuses by hand
|
// Make sure we don't have to deal with statuses by hand
|
||||||
function getStatus(plugin) {
|
function getStatus(plugin) {
|
||||||
|
@ -32,68 +32,6 @@ window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directi
|
||||||
}
|
}
|
||||||
function getLabel(plugin) { return getStatus(plugin).label; }
|
function getLabel(plugin) { return getStatus(plugin).label; }
|
||||||
|
|
||||||
// Turns thisIsASentence to
|
|
||||||
// This Is A Sentence
|
|
||||||
function niceName(name) {
|
|
||||||
return name
|
|
||||||
.split(/(?=[A-Z])/)
|
|
||||||
.map(function (word) { return word[0].toUpperCase() + _.rest(word).join(''); })
|
|
||||||
.join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatNumber(num, which) {
|
|
||||||
var format = '0.00';
|
|
||||||
var postfix = '';
|
|
||||||
switch (which) {
|
|
||||||
case 'time':
|
|
||||||
return moment(num).format('HH:mm:ss');
|
|
||||||
case 'byte':
|
|
||||||
format += 'b';
|
|
||||||
break;
|
|
||||||
case 'ms':
|
|
||||||
postfix = 'ms';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return numeral(num).format(format) + postfix;
|
|
||||||
}
|
|
||||||
function numberType(key) {
|
|
||||||
var byteMetrics = ['heapTotal', 'heapUsed', 'rss'];
|
|
||||||
var msMetrics = ['delay', 'responseTimeAvg', 'responseTimeMax'];
|
|
||||||
var preciseMetric = ['requests', 'load'];
|
|
||||||
if ( byteMetrics.indexOf(key) > -1 ) {
|
|
||||||
return 'byte';
|
|
||||||
} else if (msMetrics.indexOf(key) > -1 ) {
|
|
||||||
return 'ms';
|
|
||||||
} else {
|
|
||||||
return 'precise';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var makeChartOptions = _.memoize(function (type) {
|
|
||||||
return {
|
|
||||||
chart: {
|
|
||||||
type: 'lineChart',
|
|
||||||
height: 200,
|
|
||||||
showLegend: false,
|
|
||||||
showXAxis: false,
|
|
||||||
showYAxis: false,
|
|
||||||
useInteractiveGuideline: true,
|
|
||||||
tooltips: true,
|
|
||||||
pointSize: 0,
|
|
||||||
color: ['#444', '#777', '#aaa'],
|
|
||||||
margin: {
|
|
||||||
top: 10,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 20
|
|
||||||
},
|
|
||||||
xAxis: { tickFormat: function (d) { return formatNumber(d, 'time'); } },
|
|
||||||
yAxis: { tickFormat: function (d) { return formatNumber(d, type); }, },
|
|
||||||
y: function (d) { return d.y; },
|
|
||||||
x: function (d) { return d.x; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// The Kibana App
|
// The Kibana App
|
||||||
angular.module('KibanaStatusApp', ['nvd3'])
|
angular.module('KibanaStatusApp', ['nvd3'])
|
||||||
.controller('StatusPage', ['$scope', '$http', '$window', '$timeout', function ($scope, $http, $window, $timeout) {
|
.controller('StatusPage', ['$scope', '$http', '$window', '$timeout', function ($scope, $http, $window, $timeout) {
|
||||||
|
@ -137,6 +75,9 @@ window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directi
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// To make sure that the alert box doesn't keep showing up
|
||||||
|
var hasHttpError = false;
|
||||||
|
|
||||||
function getAppStatus() {
|
function getAppStatus() {
|
||||||
// go ahead and get the info you want
|
// go ahead and get the info you want
|
||||||
$http
|
$http
|
||||||
|
@ -146,47 +87,14 @@ window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directi
|
||||||
|
|
||||||
// setup The charts
|
// setup The charts
|
||||||
// wrap the metrics data and append the average
|
// wrap the metrics data and append the average
|
||||||
$scope.ui.charts = _.mapValues(data.metrics, function (metric, name) {
|
_.mapValues(data.metrics, function (metric, name) {
|
||||||
|
var currentMetricObj = $scope.ui.charts[name];
|
||||||
// Metric Values format
|
var newMetricObj = {data: metric, key: name};
|
||||||
// metric: [[xValue, yValue], ...]
|
if (currentMetricObj) {
|
||||||
// LoadMetric:
|
currentMetricObj.data = metric;
|
||||||
// metric: [[xValue, [yValue, yValue2, yValue3]], ...]
|
} else {
|
||||||
// return [
|
$scope.ui.charts[name] = newMetricObj;
|
||||||
// {type: 'line', key: name, yAxis: 1, values: [{x: xValue, y: yValue}, ...]},
|
}
|
||||||
// {type: 'line', key: name, yAxis: 1, values: [{x: xValue, y: yValue1}, ...]},
|
|
||||||
// {type: 'line', key: name, yAxis: 1, values: [{x: xValue, y: yValue2}, ...]}]
|
|
||||||
//
|
|
||||||
// Go through all of the metric values and split the values out.
|
|
||||||
// returns an array of all of the averages
|
|
||||||
var metricList = [];
|
|
||||||
var metricNumberType = numberType(name);
|
|
||||||
|
|
||||||
// convert the [x,y] into {x: x, y: y}
|
|
||||||
metric.forEach(function (vector) {
|
|
||||||
vector = _.flatten(vector);
|
|
||||||
var x = vector.shift();
|
|
||||||
vector.forEach(function (yValue, idx) {
|
|
||||||
if (!metricList[idx]) {
|
|
||||||
metricList[idx] = {
|
|
||||||
key: name + idx,
|
|
||||||
values: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// unshift to make sure they're in the correct order
|
|
||||||
metricList[idx].values.unshift({x: x, y: yValue});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var average = metricList.map(function (data) {
|
|
||||||
var uglySum = data.values.reduce(function (sumSoFar, vector) {
|
|
||||||
return sumSoFar + vector.y;
|
|
||||||
}, 0);
|
|
||||||
return formatNumber(uglySum / data.values.length, metricNumberType);
|
|
||||||
});
|
|
||||||
var options = makeChartOptions(metricNumberType);
|
|
||||||
|
|
||||||
return { data: metricList, average: average, niceName: niceName(name), options: options };
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// give the plugins their proper name so CSS classes can be properply applied
|
// give the plugins their proper name so CSS classes can be properply applied
|
||||||
|
@ -195,19 +103,152 @@ window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directi
|
||||||
return plugin;
|
return plugin;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Finally notify that there has been a succesful request
|
||||||
|
hasHttpError = false;
|
||||||
|
|
||||||
if (windowHasFocus) {
|
if (windowHasFocus) {
|
||||||
// go ahead and get another status in 5 seconds
|
// go ahead and get another status in 5 seconds
|
||||||
$timeout(getAppStatus, 5000);
|
$timeout(getAppStatus, 5000);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.error(function () {
|
.error(function () {
|
||||||
window.alert('Something went terribly wrong while making the request!!! Perhaps your server is down?');
|
if (!hasHttpError) {
|
||||||
|
window.alert('Something went terribly wrong while making the request!!! Perhaps your server is down?');
|
||||||
|
hasHttpError = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start it all up
|
// Start it all up
|
||||||
getAppStatus();
|
getAppStatus();
|
||||||
}]);
|
}])
|
||||||
|
.directive('kbSparkline', function () {
|
||||||
|
var directiveDef = {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
data: '=chartData',
|
||||||
|
key: '=chartKey'
|
||||||
|
},
|
||||||
|
template: chartTemplate,
|
||||||
|
link: function ($scope, $el, attrs) {
|
||||||
|
|
||||||
|
var metricNumberType = numberType($scope.key);
|
||||||
|
|
||||||
|
var options = makeChartOptions(metricNumberType);
|
||||||
|
$scope.chart = { niceName: niceName($scope.key), options: options };
|
||||||
|
$scope.$watch('data', function (newData) {
|
||||||
|
var metricList = convertData(newData);
|
||||||
|
var average = calcAvg(metricList);
|
||||||
|
$scope.chart.data = metricList;
|
||||||
|
$scope.chart.average = average;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function convertData(data) {
|
||||||
|
// Metric Values format
|
||||||
|
// metric: [[xValue, yValue], ...]
|
||||||
|
// LoadMetric:
|
||||||
|
// metric: [[xValue, [yValue, yValue2, yValue3]], ...]
|
||||||
|
// return [
|
||||||
|
// {type: 'line', key: name, yAxis: 1, values: [{x: xValue, y: yValue}, ...]},
|
||||||
|
// {type: 'line', key: name, yAxis: 1, values: [{x: xValue, y: yValue1}, ...]},
|
||||||
|
// {type: 'line', key: name, yAxis: 1, values: [{x: xValue, y: yValue2}, ...]}]
|
||||||
|
//
|
||||||
|
// Go through all of the metric values and split the values out.
|
||||||
|
// returns an array of all of the averages
|
||||||
|
|
||||||
|
var metricList = [];
|
||||||
|
data.forEach(function (vector) {
|
||||||
|
vector = _.flatten(vector);
|
||||||
|
var x = vector.shift();
|
||||||
|
vector.forEach(function (yValue, idx) {
|
||||||
|
if (!metricList[idx]) {
|
||||||
|
metricList[idx] = {
|
||||||
|
key: idx,
|
||||||
|
values: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// unshift to make sure they're in the correct order
|
||||||
|
metricList[idx].values.unshift({x: x, y: yValue});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return metricList;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcAvg(metricList) {
|
||||||
|
return metricList.map(function (data) {
|
||||||
|
var uglySum = data.values.reduce(function (sumSoFar, vector) {
|
||||||
|
return sumSoFar + vector.y;
|
||||||
|
}, 0);
|
||||||
|
return formatNumber(uglySum / data.values.length, metricNumberType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Turns thisIsASentence to
|
||||||
|
// This Is A Sentence
|
||||||
|
function niceName(name) {
|
||||||
|
return name
|
||||||
|
.split(/(?=[A-Z])/)
|
||||||
|
.map(function (word) { return word[0].toUpperCase() + _.rest(word).join(''); })
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatNumber(num, which) {
|
||||||
|
var format = '0.00';
|
||||||
|
var postfix = '';
|
||||||
|
switch (which) {
|
||||||
|
case 'time':
|
||||||
|
return moment(num).format('HH:mm:ss');
|
||||||
|
case 'byte':
|
||||||
|
format += 'b';
|
||||||
|
break;
|
||||||
|
case 'ms':
|
||||||
|
postfix = 'ms';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return numeral(num).format(format) + postfix;
|
||||||
|
}
|
||||||
|
function numberType(key) {
|
||||||
|
var byteMetrics = ['heapTotal', 'heapUsed', 'rss'];
|
||||||
|
var msMetrics = ['delay', 'responseTimeAvg', 'responseTimeMax'];
|
||||||
|
var preciseMetric = ['requests', 'load'];
|
||||||
|
if ( byteMetrics.indexOf(key) > -1 ) {
|
||||||
|
return 'byte';
|
||||||
|
} else if (msMetrics.indexOf(key) > -1 ) {
|
||||||
|
return 'ms';
|
||||||
|
} else {
|
||||||
|
return 'precise';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var makeChartOptions = _.memoize(function (type) {
|
||||||
|
return {
|
||||||
|
chart: {
|
||||||
|
type: 'lineChart',
|
||||||
|
height: 200,
|
||||||
|
showLegend: false,
|
||||||
|
showXAxis: false,
|
||||||
|
showYAxis: false,
|
||||||
|
useInteractiveGuideline: true,
|
||||||
|
tooltips: true,
|
||||||
|
pointSize: 0,
|
||||||
|
color: ['#444', '#777', '#aaa'],
|
||||||
|
margin: {
|
||||||
|
top: 10,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 20
|
||||||
|
},
|
||||||
|
xAxis: { tickFormat: function (d) { return formatNumber(d, 'time'); } },
|
||||||
|
yAxis: { tickFormat: function (d) { return formatNumber(d, type); }, },
|
||||||
|
y: function (d) { return d.y; },
|
||||||
|
x: function (d) { return d.x; }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return directiveDef;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function () {
|
init: function () {
|
||||||
|
|
|
@ -10,7 +10,8 @@ require.config({
|
||||||
moment: '/bower_components/moment/moment',
|
moment: '/bower_components/moment/moment',
|
||||||
nvd3: '/bower_components/nvd3/build/nv.d3',
|
nvd3: '/bower_components/nvd3/build/nv.d3',
|
||||||
nvd3_directives: '/bower_components/angular-nvd3/dist/angular-nvd3',
|
nvd3_directives: '/bower_components/angular-nvd3/dist/angular-nvd3',
|
||||||
numeral: '/bower_components/numeral/numeral'
|
numeral: '/bower_components/numeral/numeral',
|
||||||
|
text: '/bower_components/requirejs-text/text'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
angular: {
|
angular: {
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
#plugin_table {
|
#plugin_table {
|
||||||
margin:0 15px 15px 15px;
|
margin:0 15px 15px 15px;
|
||||||
.plugin_row {
|
.plugin_row {
|
||||||
height:30px;
|
|
||||||
line-height:30px;
|
line-height:30px;
|
||||||
+ .plugin_row {
|
+ .plugin_row {
|
||||||
border-top:1px solid #ebebeb;
|
border-top:1px solid #ebebeb;
|
||||||
|
|
|
@ -7,7 +7,7 @@ module.exports = function (grunt) {
|
||||||
'<%= plugins %>/*/*.less',
|
'<%= plugins %>/*/*.less',
|
||||||
'<%= app %>/**/components/**/*.less',
|
'<%= app %>/**/components/**/*.less',
|
||||||
'<%= app %>/**/components/vislib/components/styles/**/*.less',
|
'<%= app %>/**/components/vislib/components/styles/**/*.less',
|
||||||
'<%= src %>/*/server/plugins/status/public/styles/*.less'
|
'<%= src %>/server/plugins/status/public/styles/main.less'
|
||||||
],
|
],
|
||||||
tasks: ['less:dev']
|
tasks: ['less:dev']
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue