Merge branch 'pr/4724'

This commit is contained in:
spalger 2015-08-26 14:59:20 -07:00
commit 556e79dc2f
10 changed files with 223 additions and 151 deletions

View file

@ -5,6 +5,7 @@ define(function (require) {
require('plugins/kibana/settings/sections/indices/index'),
require('plugins/kibana/settings/sections/advanced/index'),
require('plugins/kibana/settings/sections/objects/index'),
require('plugins/kibana/settings/sections/status/index'),
require('plugins/kibana/settings/sections/about/index')
];
});

View file

@ -0,0 +1,10 @@
define(function (require) {
var _ = require('lodash');
return {
order: 3,
name: 'status',
display: 'Status',
url: '/status'
};
});

View file

@ -9,10 +9,10 @@ module.exports = function formatNumber(num, which) {
case 'time':
return moment(num).format('HH:mm:ss');
case 'byte':
format += 'b';
format += ' b';
break;
case 'ms':
postfix = 'ms';
postfix = ' ms';
break;
}
return numeral(num).format(format) + postfix;

View file

@ -1,48 +1,39 @@
<div class="container">
<div class="container state_default state_{{ui.serverState}}">
<header>
<h1>
<strong>Kibana</strong>&nbsp;Status Page
Status: <span class="state_color">{{ ui.serverStateMessage }}</span>
<i class="fa state_color state_icon" />
</h1>
</header>
<section class="section">
<h4>What is this page?</h4>
<p>This page is your sanity check, and your savior. You can check for potential problems</p>
<p>Here is the status of your kibana instance and the plugins you have installed along with some, statistics to asses potential problems.</p>
</section>
<div class="system_status_wrapper state_default state_{{ui.serverState}}">
<h3 class="title">
<b>System Status</b> {{ ui.serverStateMessage }}
</h3>
<div class="row metrics_wrapper">
<div ng-repeat="(name, data) in ui.metrics">
<status-page-metric name="{{name}}" data="data"></status-page-metric>
</div>
</div>
<div class="row plugin_status_wrapper">
<h3>Installed Plugins</h3>
<div ng-if="!ui.statuses && ui.loading" class="loading_statuses">
<span class="spinner"></span>
</div>
<h4 ng-if="!ui.statuses && !ui.loading" class="missing_statuses">
No status information available
No plugin status information available
</h4>
<table class="status_breakdown" ng-if="ui.statuses">
<table class="plugin_status_breakdown row" ng-if="ui.statuses">
<tr>
<th class="col-xs-1">Name</th>
<th class="col-xs-11">Description</th>
<th class="col-xs-11">Status</th>
</tr>
<tr ng-repeat="status in ui.statuses" class="status_row state_default state_{{status.state}}">
<tr ng-repeat="status in ui.statuses" class="status_row plugin_state_default plugin_state_{{status.state}}">
<td class="col-xs-1 status_name">{{status.name}}</td>
<td class="col-xs-11 status_message">{{status.message}}</td>
<td class="col-xs-11 status_message">
<i class="fa plugin_state_color plugin_state_icon" />
{{status.message}}
</td>
</tr>
</table>
</div>
<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="(name, data) in ui.metrics">
<status-page-metric name="{{name}}" data="data"></status-page-metric>
</div>
</div>
</div>

View file

@ -9,7 +9,8 @@ require('ui/chrome')
.setTabs([
{
id: '',
title: 'Server Status'
title: 'Server Status',
activeIndicatorColor: '#EFF0F2'
}
])
.setRootTemplate(require('plugins/statusPage/statusPage.html'))
@ -24,6 +25,7 @@ require('ui/chrome')
return $http
.get('/api/status')
.then(function (resp) {
if (ui.fetchError) {
ui.fetchError.clear();
ui.fetchError = null;
@ -36,7 +38,7 @@ require('ui/chrome')
var overall = data.status.overall;
if (!ui.serverState || (ui.serverState !== overall.state)) {
ui.serverState = overall.state;
ui.serverStateMessage = overall.nickname || overall.title;
ui.serverStateMessage = overall.title;
}
})
.catch(function () {
@ -50,9 +52,4 @@ require('ui/chrome')
};
ui.refresh();
// let the browser decide when to slow down requests
setInterval(function () {
$scope.$eval(ui.refresh);
}, 5000);
});

View file

@ -1,126 +1,178 @@
@import "~font-awesome/less/font-awesome";
@status-bg: #eff0f2;
@status-metric-bg: #fff;
@status-metric-border: #aaa;
@status-metric-title-color: #666;
@status-plugins-bg: #fff;
@status-plugins-border: #bbb;
@status-plugins-headings-color: #666;
@status-default: #7c7c7c;
@status-green: #94c63d;
@status-yellow: #edb800;
@status-red: #da1e04;
@icon-default: @fa-var-clock-o;
@icon-green: @fa-var-check;
@icon-yellow: @fa-var-exclamation-circle;
@icon-red: @fa-var-exclamation-triangle;
// background of main page
.content {
background-color: @status-bg;
}
.section {
margin-bottom:15px;
}
.status_breakdown {
margin:0 15px 15px 15px;
// metrics section
.metrics_wrapper {
margin-top: 25px;
.status_metric_wrapper {
padding: 10px;
border: 0;
.status_row {
height:30px;
line-height:30px;
+ .status_row {
border-top:1px solid #ebebeb;
.content {
text-align: right;
padding: 15px;
padding-right: 20px;
background-color: @status-metric-bg;
border-top: 2px solid;
border-top-color: @status-metric-border;
.title {
color: @status-metric-title-color;
margin: 0 0 5px 0;
}
.average {
font-size: 42px;
line-height:45px;
font-weight: normal;
margin:0;
}
}
}
th {
font-size:10px;
color:#a9a9a9;
height:25px;
line-height:25px;
}
.status_name {
font-weight:bold;
padding:0px 5px;
}
.status_message {
border-left:1px solid #ebebeb;
padding:0;
padding-left:15px;
}
}
.system_status_wrapper {
// plugin status table section
.plugin_status_wrapper {
margin-top: 25px;
margin-left: -5px;
margin-right: -5px;
border-top:2px solid;
background-color: @status-plugins-bg;
padding: 10px;
h3 {
margin-top: 3px;
margin-bottom: 3px;
}
.missing_statuses,
.loading_statuses {
padding: 20px;
text-align: center;
}
}
.status_chart_wrapper {
border-top:1px solid #ebebeb;
border-left:1px solid #ebebeb;
.average {
font-size: 42px;
line-height:45px;
margin-top:0;
font-weight:bold;
}
.title {
margin:0 0 5px 0;
text-transform:capitalize;
}
}
.plugin_status_breakdown {
margin-left: 0;
margin-right: 0;
#chart_cont {
margin-top:35px;
}
.status_row {
height:30px;
line-height:30px;
border-bottom:1px solid;
border-bottom-color: @status-plugins-border;
}
.status_chart_wrapper:nth-child(2), .status_chart_wrapper:nth-child(3) {
border-top:0 none transparent;
}
th {
color:@status-plugins-headings-color;
font-weight: normal;
height:25px;
line-height:25px;
border-bottom:1px solid;
border-bottom-color: @status-plugins-border;
}
.status_chart_wrapper:first-child {
border-top:0 none transparent;
border-left:0 none transparent;
}
.status_name {
padding:0px 5px;
border-left: 2px solid;
}
.status_chart_wrapper:nth-child(3n + 1) {
border-left:0 none transparent;
}
.status_chart_wrapper:nth-child(n + 4) {
padding-top:20px;
}
.nv-axis.nv-x .tick line {
display:none;
}
.state(@primary, @secondary) {
&.system_status_wrapper {
border:1px solid @primary;
border-radius:5px;
overflow: hidden;
.title {
color:#ffffff;
height:50px;
line-height:50px;
margin:0 0 10px 0;
padding:0 15px;
border-color:@primary;
background:@primary;
background:-moz-linear-gradient(left,@primary 0%,@secondary 100%);
background:-webkit-gradient(linear,left top,right top,color-stop(0%,@primary),color-stop(100%,@secondary));
background:-webkit-linear-gradient(left,@primary 0%,@secondary 100%);
background:-o-linear-gradient(left,@primary 0%,@secondary 100%);
background:-ms-linear-gradient(left,@primary 0%,@secondary 100%);
background:linear-gradient(to right,@primary 0%,@secondary 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=@primary,endColorstr=@secondary,GradientType=1);
.status_message {
padding:0;
padding-left:15px;
border-right: 2px solid;
}
}
}
&.status_row {
color: @primary;
//plugin state
.plugin_state(@color, @icon) {
.plugin_state_color {
color: @color;
}
.plugin_state_icon:before {
content: @icon;
}
.status_name {
border-left-color: @color !important;
}
.status_message {
border-right-color: @color !important;
}
}
.plugin_state_default {
.plugin_state(@status-default, @icon-default);
}
.plugin_state_green {
.plugin_state(@status-green, @icon-green);
}
.plugin_state_yellow {
.plugin_state(@status-yellow, @icon-yellow);
}
.plugin_state_red {
.plugin_state(@status-red, @icon-red);
}
//server state
.state(@color, @icon) {
.state_color {
color: @color;
}
.state_icon:before {
content: @icon;
}
.plugin_status_wrapper {
border-top-color: @color;
}
}
.state_default {
.state(#7C7C7C, #CFCFCF);
.state(@status-default, @icon-default);
}
.state_green {
.state(#0a8e03, #96f501);
.state(@status-green, @icon-green);
}
.state_yellow {
.state(#fdee00, #c16f00);
.state(@status-yellow, @icon-yellow);
}
.state_red {
.state(#da1e04, #ff730f);
.state(@status-red, @icon-red);
}

View file

@ -1,5 +1,6 @@
<div class="status_chart_wrapper col-md-4">
<h3 class="title">{{metric.title}}</h3>
<h4 class="average">{{ metric.averages.join(', ') }}</h4>
<nvd3 options="metric.chartOptions" data="metric.chartData"></nvd3>
<div class="status_metric_wrapper col-md-4">
<div class="content">
<h3 class="title">{{metric.extendedTitle}}</h3>
<h4 class="average">{{ metric.averages.join(', ') }}</h4>
</div>
</div>

View file

@ -5,7 +5,6 @@ require('angular-nvd3');
var toTitleCase = require('./lib/toTitleCase');
var formatNumber = require('./lib/formatNumber');
var getChartOptions = _.memoize(require('./lib/makeChartOptions'));
var readStatData = require('./lib/readStatData');
function calcAvg(metricList, metricNumberType) {
@ -33,17 +32,16 @@ require('ui/modules')
self.name = $scope.name;
self.title = toTitleCase(self.name);
self.extendedTitle = self.title;
self.numberType = 'precise';
self.seriesNames = [];
switch (self.name) {
case 'heapTotal':
case 'heapUsed':
case 'rss':
self.numberType = 'byte';
break;
case 'delay':
case 'responseTimeAvg':
case 'responseTimeMax':
self.numberType = 'ms';
@ -54,12 +52,22 @@ require('ui/modules')
break;
}
self.chartOptions = getChartOptions(self.numberType);
$scope.$watch('data', function (data) {
self.rawData = data;
self.chartData = readStatData(self.rawData, self.seriesNames);
self.averages = calcAvg(self.chartData, self.numberType);
var unit = '';
self.averages = self.averages.map(function (average) {
var parts = average.split(' ');
var value = parts.shift();
unit = parts.join(' ');
return value;
});
self.extendedTitle = self.title;
if (unit) {
self.extendedTitle = `${self.extendedTitle} (${unit})`;
}
});
}
};

View file

@ -1,27 +1,12 @@
module.exports = function (kbnServer, server, config) {
var _ = require('lodash');
var Samples = require('./Samples');
var ServerStatus = require('./ServerStatus');
var { join } = require('path');
kbnServer.status = new ServerStatus(kbnServer.server);
kbnServer.metrics = new Samples(60);
if (server.plugins.good) {
server.plugins.good.monitor.on('ops', function (event) {
var port = config.get('server.port');
kbnServer.metrics.add({
rss: event.psmem.rss,
heapTotal: event.psmem.heapTotal,
heapUsed: event.psmem.heapUsed,
load: event.osload,
delay: event.psdelay,
concurrency: _.get(event, ['concurrents', port]),
responseTimeAvg: _.get(event, ['responseTimes', port, 'avg']),
responseTimeMax: _.get(event, ['responseTimes', port, 'max']),
requests: _.get(event, ['requests', port, 'total'], 0)
});
});
kbnServer.mixin(require('./metrics'));
}
server.route({

View file

@ -0,0 +1,27 @@
module.exports = function (kbnServer, server, config) {
var _ = require('lodash');
var Samples = require('./Samples');
let lastReport = Date.now();
kbnServer.metrics = new Samples(12);
server.plugins.good.monitor.on('ops', function (event) {
let now = Date.now();
let secSinceLast = (now - lastReport) / 1000;
lastReport = now;
var port = config.get('server.port');
let requests = _.get(event, ['requests', port, 'total'], 0);
let requestsPerSecond = requests / secSinceLast;
kbnServer.metrics.add({
heapTotal: _.get(event, 'psmem.heapTotal'),
heapUsed: _.get(event, 'psmem.heapUsed'),
load: event.osload,
responseTimeAvg: _.get(event, ['responseTimes', port, 'avg']),
responseTimeMax: _.get(event, ['responseTimes', port, 'max']),
requestsPerSecond: requestsPerSecond
});
});
};