mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[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
6 changed files with 166 additions and 122 deletions
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">
|
||||
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container" ng-controller="StatusPage">
|
||||
|
@ -27,13 +27,13 @@
|
|||
</h3>
|
||||
<div id="plugin_table">
|
||||
<div class="plugin_table_header plugin_row">
|
||||
<div class="col-md-1 plugin_key">Plugin</div>
|
||||
<div class="col-md-11 plugin_state">Status</div>
|
||||
<div class="col-md-1 col-sm-2 col-xs-4 plugin_key">Plugin</div>
|
||||
<div class="col-md-11 col-sm-10 col-xs-8 plugin_state">Status</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<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-11 plugin_state">{{plugin.message}}</div>
|
||||
<div class="col-md-1 col-sm-2 col-xs-4 plugin_key">{{key}}</div>
|
||||
<div class="col-md-11 col-sm-10 col-xs-8 plugin_state">{{plugin.message}}</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -41,14 +41,9 @@
|
|||
<h2>Server Metrics</h2>
|
||||
<p>Interval of 5 seconds, with a max history of 5 minutes.</p>
|
||||
<div id="chart_cont" class="row">
|
||||
<div ng-repeat="(key, chart) in ui.charts" class="status_chart_wrapper col-md-4">
|
||||
<h3 class="title">{{chart.niceName}}</h2>
|
||||
<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 ng-repeat="(key, chart) in ui.charts">
|
||||
<kb-sparkline chart-data="ui.charts[key].data" chart-key="key"></kb-sparkline>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
<footer></footer>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directives'],
|
||||
function (angular, $, _, moment, numeral) {
|
||||
window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'text!status/chartTemplate.html', 'nvd3_directives'],
|
||||
function (angular, $, _, moment, numeral, chartTemplate) {
|
||||
|
||||
// Make sure we don't have to deal with statuses by hand
|
||||
function getStatus(plugin) {
|
||||
|
@ -32,68 +32,6 @@ window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directi
|
|||
}
|
||||
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
|
||||
angular.module('KibanaStatusApp', ['nvd3'])
|
||||
.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() {
|
||||
// go ahead and get the info you want
|
||||
$http
|
||||
|
@ -146,47 +87,14 @@ window.define(['angular', 'jquery', 'lodash', 'moment', 'numeral', 'nvd3_directi
|
|||
|
||||
// setup The charts
|
||||
// wrap the metrics data and append the average
|
||||
$scope.ui.charts = _.mapValues(data.metrics, function (metric, name) {
|
||||
|
||||
// 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 = [];
|
||||
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 };
|
||||
_.mapValues(data.metrics, function (metric, name) {
|
||||
var currentMetricObj = $scope.ui.charts[name];
|
||||
var newMetricObj = {data: metric, key: name};
|
||||
if (currentMetricObj) {
|
||||
currentMetricObj.data = metric;
|
||||
} else {
|
||||
$scope.ui.charts[name] = newMetricObj;
|
||||
}
|
||||
});
|
||||
|
||||
// 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;
|
||||
});
|
||||
|
||||
// Finally notify that there has been a succesful request
|
||||
hasHttpError = false;
|
||||
|
||||
if (windowHasFocus) {
|
||||
// go ahead and get another status in 5 seconds
|
||||
$timeout(getAppStatus, 5000);
|
||||
}
|
||||
})
|
||||
.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
|
||||
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 {
|
||||
init: function () {
|
||||
|
|
|
@ -10,7 +10,8 @@ require.config({
|
|||
moment: '/bower_components/moment/moment',
|
||||
nvd3: '/bower_components/nvd3/build/nv.d3',
|
||||
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: {
|
||||
angular: {
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#plugin_table {
|
||||
margin:0 15px 15px 15px;
|
||||
.plugin_row {
|
||||
height:30px;
|
||||
line-height:30px;
|
||||
+ .plugin_row {
|
||||
border-top:1px solid #ebebeb;
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = function (grunt) {
|
|||
'<%= plugins %>/*/*.less',
|
||||
'<%= app %>/**/components/**/*.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']
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue