mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Merge branch 'master' of github.com:elastic/kibana into apps/home
This commit is contained in:
commit
e809f4b718
9 changed files with 391 additions and 54 deletions
|
@ -35,10 +35,6 @@ module.exports = function (grunt) {
|
|||
'<%= src %>/**/*.js',
|
||||
'<%= unitTestDir %>/**/*.js',
|
||||
'!<%= unitTestDir %>/specs/vislib/fixture/**/*'
|
||||
],
|
||||
lessFiles: [
|
||||
'<%= src %>/**/*.less',
|
||||
'!<%= src %>/**/_*.less'
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"angular-bootstrap": "0.10.0",
|
||||
"angular-elastic": "2.4.2",
|
||||
"angular-mocks": "1.2.28",
|
||||
"angular-nvd3": "https://github.com/krispo/angular-nvd3.git#1.0.0-beta",
|
||||
"angular-route": "1.2.28",
|
||||
"angular-ui-ace": "0.2.3",
|
||||
"bluebird": "~2.9.27",
|
||||
|
@ -34,7 +35,10 @@
|
|||
"ng-clip": "0.2.6",
|
||||
"marked": "0.3.3",
|
||||
"numeral": "1.5.3",
|
||||
"nvd3": "1.7.1",
|
||||
"leaflet-draw": "0.2.4"
|
||||
},
|
||||
"devDependencies": {}
|
||||
"resolutions": {
|
||||
"d3": "3.5.5"
|
||||
}
|
||||
}
|
||||
|
|
3
src/server/plugins/status/public/.jshintrc
Normal file
3
src/server/plugins/status/public/.jshintrc
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "../../../../../.jshintrc.browser"
|
||||
}
|
229
src/server/plugins/status/public/index.js
Normal file
229
src/server/plugins/status/public/index.js
Normal file
|
@ -0,0 +1,229 @@
|
|||
define(function (require) {
|
||||
var angular = require('angular');
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
var moment = require('moment');
|
||||
var numeral = require('numeral');
|
||||
require('nvd3_directives');
|
||||
|
||||
// Make sure we don't have to deal with statuses by hand
|
||||
function getStatus(plugin) {
|
||||
var statusMap = {
|
||||
green: {
|
||||
label: 'success',
|
||||
msg: 'Ready',
|
||||
idx: 1
|
||||
},
|
||||
yellow: {
|
||||
label: 'warning',
|
||||
msg: 'S.N.A.F.U.',
|
||||
idx: 2
|
||||
},
|
||||
red: {
|
||||
label: 'danger',
|
||||
msg: 'Danger Will Robinson! Danger!',
|
||||
idx: 3
|
||||
},
|
||||
loading: {
|
||||
label: 'info',
|
||||
msg: 'Loading...',
|
||||
idx: 0
|
||||
}
|
||||
};
|
||||
if (!_.isObject(plugin) || _.isUndefined(plugin)) {
|
||||
plugin = {state: plugin};
|
||||
}
|
||||
return statusMap[plugin.state];
|
||||
}
|
||||
|
||||
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
|
||||
require('modules')
|
||||
.get('KibanaStatusApp', ['nvd3'])
|
||||
.controller('StatusPage', function ($scope, $http, $window, $timeout) {
|
||||
// the object representing all of the elements the ui touches
|
||||
$scope.ui = {
|
||||
// show the system status by going through all of the plugins,
|
||||
// and making sure they're green.
|
||||
systemStatus: (function () {
|
||||
// for convenience
|
||||
function getIdx(plugin) { return getStatus(plugin).idx; }
|
||||
|
||||
return function () {
|
||||
var currentStatus = 'loading';
|
||||
var currentIdx = getIdx(currentStatus);
|
||||
|
||||
// FIXME eh, not too thrilled about this.
|
||||
var status = _.reduce($scope.ui.plugins, function (curr, plugin, key) {
|
||||
var pluginIdx = getIdx(plugin);
|
||||
if (pluginIdx > currentIdx) {
|
||||
// set the current status
|
||||
currentStatus = plugin.state;
|
||||
currentIdx = getIdx(plugin);
|
||||
}
|
||||
return currentStatus;
|
||||
}, 'loading');
|
||||
|
||||
// give the ui the label for colors and such
|
||||
return getStatus(status);
|
||||
};
|
||||
}()),
|
||||
charts: {},
|
||||
plugins: []
|
||||
};
|
||||
|
||||
var windowHasFocus = true;
|
||||
angular.element($window).bind({
|
||||
blur: function () { windowHasFocus = false; },
|
||||
focus: function () {
|
||||
windowHasFocus = true;
|
||||
getAppStatus();
|
||||
}
|
||||
});
|
||||
|
||||
function getAppStatus() {
|
||||
// go ahead and get the info you want
|
||||
$http
|
||||
.get('/status/health')
|
||||
.success(function (data) {
|
||||
// Assign the propper variables to the scope and change them as necessary
|
||||
|
||||
// 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 };
|
||||
});
|
||||
|
||||
// give the plugins their proper name so CSS classes can be properply applied
|
||||
$scope.ui.plugins = _.mapValues(data.status, function (plugin) {
|
||||
plugin.uiStatus = getLabel(plugin);
|
||||
return plugin;
|
||||
});
|
||||
|
||||
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?');
|
||||
});
|
||||
}
|
||||
|
||||
// Start it all up
|
||||
getAppStatus();
|
||||
});
|
||||
|
||||
return {
|
||||
init: function () {
|
||||
$(function () {
|
||||
angular.bootstrap(window.document, ['nvd3', 'KibanaStatusApp']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
});
|
23
src/server/plugins/status/public/require.config.js
Normal file
23
src/server/plugins/status/public/require.config.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
require.config({
|
||||
baseUrl: '/',
|
||||
paths: {
|
||||
angular: '/bower_components/angular/angular',
|
||||
css: '/bower_components/require-css/css',
|
||||
d3: '/bower_components/d3/d3',
|
||||
jquery: '/bower_components/jquery/dist/jquery',
|
||||
lodash: '/utils/lodash-mixins/index',
|
||||
lodash_src: '/bower_components/lodash/lodash',
|
||||
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'
|
||||
},
|
||||
shim: {
|
||||
angular: {
|
||||
deps: ['jquery'],
|
||||
exports: 'angular'
|
||||
},
|
||||
nvd3: ['css!bower_components/nvd3/build/nv.d3.css', 'd3'],
|
||||
nvd3_directives: ['angular', 'nvd3']
|
||||
}
|
||||
});
|
115
src/server/plugins/status/public/styles/main.less
Normal file
115
src/server/plugins/status/public/styles/main.less
Normal file
|
@ -0,0 +1,115 @@
|
|||
.section {
|
||||
margin-bottom:15px;
|
||||
}
|
||||
.system_status_wrapper {
|
||||
border:1px solid #0a8e03;
|
||||
border-radius:5px;
|
||||
overflow:hidden;
|
||||
.title {
|
||||
color:#ffffff;
|
||||
height:50px;
|
||||
line-height:50px;
|
||||
background-color:#0a8e03;
|
||||
margin:0 0 10px 0;
|
||||
padding:0 15px;
|
||||
background:-moz-linear-gradient(left,#0a8e03 0%,#96f501 100%);
|
||||
background:-webkit-gradient(linear,left top,right top,color-stop(0%,#0a8e03),color-stop(100%,#96f501));
|
||||
background:-webkit-linear-gradient(left,#0a8e03 0%,#96f501 100%);
|
||||
background:-o-linear-gradient(left,#0a8e03 0%,#96f501 100%);
|
||||
background:-ms-linear-gradient(left,#0a8e03 0%,#96f501 100%);
|
||||
background:linear-gradient(to right,#0a8e03 0%,#96f501 100%);
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0a8e03',endColorstr='#96f501',GradientType=1);
|
||||
}
|
||||
}
|
||||
.system_status_wrapper.system_status_danger {
|
||||
border-color:#da1e04;
|
||||
.title {
|
||||
border-color:#da1e04;
|
||||
background:#da1e04;
|
||||
background:-moz-linear-gradient(left,#da1e04 0%,#ff730f 100%);
|
||||
background:-webkit-gradient(linear,left top,right top,color-stop(0%,#da1e04),color-stop(100%,#ff730f));
|
||||
background:-webkit-linear-gradient(left,#da1e04 0%,#ff730f 100%);
|
||||
background:-o-linear-gradient(left,#da1e04 0%,#ff730f 100%);
|
||||
background:-ms-linear-gradient(left,#da1e04 0%,#ff730f 100%);
|
||||
background:linear-gradient(to right,#da1e04 0%,#ff730f 100%);
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#da1e04',endColorstr='#ff730f',GradientType=1);
|
||||
}
|
||||
}
|
||||
.system_status_wrapper.system_status_warning {
|
||||
border-color:#fdee00;
|
||||
.title {
|
||||
border-color:#fdee00;
|
||||
background:#fdee00;
|
||||
background:-moz-linear-gradient(left,#fdee00 0%,#c16f00 100%);
|
||||
background:-webkit-gradient(linear,left top,right top,color-stop(0%,#fdee00),color-stop(100%,#c16f00));
|
||||
background:-webkit-linear-gradient(left,#fdee00 0%,#c16f00 100%);
|
||||
background:-o-linear-gradient(left,#fdee00 0%,#c16f00 100%);
|
||||
background:-ms-linear-gradient(left,#fdee00 0%,#c16f00 100%);
|
||||
background:linear-gradient(to right,#fdee00 0%,#c16f00 100%);
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdee00',endColorstr='#c16f00',GradientType=1);
|
||||
}
|
||||
}
|
||||
#plugin_table {
|
||||
margin:0 15px 15px 15px;
|
||||
.plugin_row {
|
||||
height:30px;
|
||||
line-height:30px;
|
||||
+ .plugin_row {
|
||||
border-top:1px solid #ebebeb;
|
||||
}
|
||||
}
|
||||
.plugin_table_header {
|
||||
font-size:10px;
|
||||
color:#a9a9a9;
|
||||
height:25px;
|
||||
line-height:25px;
|
||||
}
|
||||
.plugin_state {
|
||||
border-left:1px solid #ebebeb;
|
||||
padding:0;
|
||||
padding-left:15px;
|
||||
}
|
||||
.plugin_table_plugin {
|
||||
color:#608b32;
|
||||
}
|
||||
.plugin_key {
|
||||
font-weight:bold;
|
||||
padding:0px 5px;
|
||||
}
|
||||
.plugin_status_danger {
|
||||
color:#da1e04;
|
||||
}
|
||||
}
|
||||
.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;
|
||||
}
|
||||
}
|
||||
#chart_cont {
|
||||
margin-top:35px;
|
||||
}
|
||||
.status_chart_wrapper:nth-child(2), .status_chart_wrapper:nth-child(3) {
|
||||
border-top:0 none transparent;
|
||||
}
|
||||
.status_chart_wrapper:first-child {
|
||||
border-top:0 none transparent;
|
||||
border-left:0 none transparent;
|
||||
}
|
||||
.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;
|
||||
}
|
|
@ -32,7 +32,11 @@ define(function (require) {
|
|||
* @returns {D3.Selection|D3.Transition.Transition} DOM element with chart titles
|
||||
*/
|
||||
ChartTitle.prototype.render = function () {
|
||||
return d3.select(this.el).selectAll('.chart-title').call(this.draw());
|
||||
var el = d3.select(this.el).select('.chart-title').node();
|
||||
var width = el ? el.clientWidth : 0;
|
||||
var height = el ? el.clientHeight : 0;
|
||||
|
||||
return d3.select(this.el).selectAll('.chart-title').call(this.draw(width, height));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -89,33 +93,21 @@ define(function (require) {
|
|||
* @method draw
|
||||
* @returns {Function} Appends chart titles to a D3 selection
|
||||
*/
|
||||
ChartTitle.prototype.draw = function () {
|
||||
ChartTitle.prototype.draw = function (width, height) {
|
||||
var self = this;
|
||||
|
||||
return function (selection) {
|
||||
selection.each(function () {
|
||||
var div = d3.select(this);
|
||||
var dataType = this.parentNode.__data__.rows ? 'rows' : 'columns';
|
||||
var width = $(this).width();
|
||||
var height = $(this).height();
|
||||
var size = dataType === 'rows' ? height : width;
|
||||
var txtHtOffset = 11;
|
||||
|
||||
self.validateWidthandHeight(width, height);
|
||||
|
||||
div.append('svg')
|
||||
.attr('width', function () {
|
||||
if (dataType === 'rows') {
|
||||
return height;
|
||||
}
|
||||
return width;
|
||||
})
|
||||
.attr('height', function () {
|
||||
if (dataType === 'rows') {
|
||||
return width;
|
||||
}
|
||||
return height;
|
||||
})
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.append('text')
|
||||
.attr('transform', function () {
|
||||
if (dataType === 'rows') {
|
||||
|
|
|
@ -4,6 +4,7 @@ module.exports = function (grunt) {
|
|||
licenses: [
|
||||
'MIT',
|
||||
'MIT*',
|
||||
'MIT License',
|
||||
'MIT/X11',
|
||||
'new BSD, and MIT',
|
||||
'BSD',
|
||||
|
@ -20,9 +21,11 @@ module.exports = function (grunt) {
|
|||
'Apache2',
|
||||
'Apache-2.0',
|
||||
'Apache, Version 2.0',
|
||||
'Apache License, v2.0',
|
||||
'ISC',
|
||||
'WTFPL',
|
||||
'Public-Domain'
|
||||
'Public-Domain',
|
||||
'UNLICENSE'
|
||||
],
|
||||
overrides: {
|
||||
'assert-plus@0.1.5': ['MIT'],
|
||||
|
@ -36,7 +39,10 @@ module.exports = function (grunt) {
|
|||
'cycle@1.0.3': ['Public-Domain'],
|
||||
'pkginfo@0.2.3': ['MIT'],
|
||||
'uglify-js@2.2.5': ['BSD'],
|
||||
'amdefine@0.1.1': ['BSD-3-Clause', 'MIT']
|
||||
'amdefine@0.1.1': ['BSD-3-Clause', 'MIT'],
|
||||
'flatten@0.0.1': ['MIT'],
|
||||
'color-name@1.0.0': ['UNLICENSE'],
|
||||
'css-color-names@0.0.1': ['MIT']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
module.exports = function (grunt) {
|
||||
var config = {
|
||||
less: {
|
||||
files: [
|
||||
'src/**/*.less'
|
||||
],
|
||||
tasks: ['less:dev']
|
||||
},
|
||||
|
||||
jade: {
|
||||
files: [
|
||||
'<%= unitTestDir %>/index.jade'
|
||||
],
|
||||
tasks: ['jade:test']
|
||||
},
|
||||
|
||||
clientside_jade: {
|
||||
files: [
|
||||
'<%= testUtilsDir %>/istanbul_reporter/report.clientside.jade'
|
||||
],
|
||||
tasks: ['jade:clientside']
|
||||
}
|
||||
};
|
||||
|
||||
if (grunt.option('no-test-watcher')) {
|
||||
// unset the test watcher
|
||||
delete config.test;
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue