Fixed linting, added compare function, added node_stats.js scripted dashboard

This commit is contained in:
Rashid Khan 2013-11-05 21:35:28 -07:00
parent 3217a7aa35
commit 5a464fcaf9
2 changed files with 136 additions and 104 deletions

View file

@ -1,76 +1,93 @@
<div ng-controller='marvel.nodes_health' ng-init="init()">
<style>
.marvel-table {
vertical-align: middle;
}
.marvel-mean {
font-size: 20pt;
font-weight: 200;
display: inline-block;
vertical-align: middle;
}
.marvel-extended {
display: inline-block;
font-size:9pt;
margin-left: 5px;
vertical-align: middle;
}
.marvel-header .nodes{
font-size: 20pt;
font-weight: bold;
margin-left: 10px;
}
.marvel-nodes-health-chart {
margin-top: 5px;
display: inline-block;
height: 10px;
width: 50px;
}
</style>
<style>
.marvel-table {
vertical-align: middle;
}
.marvel-mean {
font-size: 20pt;
font-weight: 200;
display: inline-block;
vertical-align: middle;
}
.marvel-extended {
display: inline-block;
font-size:9pt;
margin-left: 5px;
vertical-align: middle;
}
.marvel-header {
margin-bottom: 10px;
}
.marvel-header .nodes{
font-size: 20pt;
font-weight: bold;
margin-left: 10px;
}
.marvel-nodes-health-chart {
margin-top: 5px;
display: inline-block;
height: 10px;
width: 50px;
}
</style>
<div class="pull-left marvel-header marvel-table" ng-show="nodes.length > 0">
<span class="nodes">{{nodes.length}} nodes</span> / Last 10m</span>
</div>
<div class="pull-right">
<a href="" ng-class="{strong:!panel.compact}" ng-click="panel.compact=false">Full</a> / <a href="" ng-class="{strong:panel.compact}"
ng-click="panel.compact=true">Compact</a>
</div>
<div class="pull-left marvel-header marvel-table" ng-show="nodes.length > 0">
<span class="nodes">{{nodes.length}} nodes</span> / Last 10m </span>
</div>
<div class="pull-right">
<a href="" ng-class="{strong:!panel.compact}" ng-click="panel.compact=false">Full</a> /
<a href="" ng-class="{strong:panel.compact}" ng-click="panel.compact=true">Compact</a>
</div>
<table class="table table-bordered" ng-if="!panel.compact">
<thead>
<th>node</th>
<th ng-repeat="metric in metrics" ng-class="alertClass(warnLevels['_global_'][metric.name])">{{metric.name}}</th>
</thead>
<tr ng-repeat="node in nodes">
<td>{{node}}</td>
<td ng-repeat="metric in metrics" ng-class="alertClass(warnLevels[node][metric.name])">
<div class="marvel-mean">
{{data[node+"_"+metric.name].mean / metric.scale | number:metric.decimals}}<br>
<table class="table table-bordered" ng-if="!panel.compact">
<thead>
<th>node <a ng-href="{{compareLink()}}" target="_blank" class="btn btn-mini btn-info" ng-disabled="!hasSelected(nodes)" bs-tooltip="compareTip()" data-placement="right">Compare</a></th>
<th ng-repeat="metric in metrics" ng-class="alertClass(warnLevels['_global_'][metric.name])">{{metric.name}}</th>
</thead>
<tr ng-repeat="node in nodes">
<td>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="nodes[$index].selected" ng-checked="nodes[$index].selected">
{{node.name}}
</label>
</div>
</td>
<td ng-repeat="metric in metrics" ng-class="alertClass(warnLevels[node][metric.name])">
<div class="marvel-mean">
{{data[node.name+"_"+metric.name].mean / metric.scale | number:metric.decimals}}<br>
<div class="marvel-nodes-health-chart" series="data[node+'_'+metric.name+'_history']"></div>
</div>
<div class="marvel-extended">
<span>min: {{data[node+"_"+metric.name].min / metric.scale | number:metric.decimals}}</span><br>
<span>max: {{data[node+"_"+metric.name].max / metric.scale | number:metric.decimals}}</span>
<div class="marvel-nodes-health-chart" series="data[node.name+'_'+metric.name+'_history']"></div>
</div>
<div class="marvel-extended">
<span>min: {{data[node.name+"_"+metric.name].min / metric.scale | number:metric.decimals}}</span><br>
<span>max: {{data[node.name+"_"+metric.name].max / metric.scale | number:metric.decimals}}</span>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="table table-bordered table-condensed marvel-table" ng-if="panel.compact">
<thead>
<th>node</th>
<th ng-repeat="metric in metrics" ng-class="alertClass(warnLevels['_global_'][metric.name])">{{metric.name}}</th>
</thead>
<tr ng-repeat="node in nodes">
<td>{{node}}</td>
<td ng-repeat="metric in metrics" ng-class="alertClass(warnLevels[node][metric.name])">
<div>{{data[node+"_"+metric.name].mean / metric.scale | number:metric.decimals}}
<div class="marvel-nodes-health-chart" series="data[node+'_'+metric.name+'_history']"></div>
</div>
</td>
</tr>
</table>
<table class="table table-bordered table-condensed marvel-table" ng-if="panel.compact">
<thead>
<th>node <a ng-href="{{compareLink()}}" class="btn btn-mini btn-info" ng-disabled="!hasSelected(nodes)" bs-tooltip="compareTip()" data-placement="right">Compare</a></th>
<th ng-repeat="metric in metrics" ng-class="alertClass(warnLevels['_global_'][metric.name])">{{metric.name}}</th>
</thead>
<tr ng-repeat="node in nodes">
<td>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="nodes[$index].selected" ng-checked="nodes[$index].selected">
{{node.name}}
</label>
</div>
</td>
<td ng-repeat="metric in metrics" ng-class="alertClass(warnLevels[node.name][metric.name])">
<div>{{data[node.name+"_"+metric.name].mean / metric.scale | number:metric.decimals}}
<div class="marvel-nodes-health-chart" series="data[node.name+'_'+metric.name+'_history']"></div>
</div>
</td>
</tr>
</table>
</div>

View file

@ -27,8 +27,6 @@ function (angular, app, kbn, _, $) {
};
_.defaults($scope.panel,_d);
$scope.init = function () {
$scope.warnLevels = [];
@ -56,14 +54,20 @@ function (angular, app, kbn, _, $) {
request = request
.facet($scope.ejs.TermsFacet('terms')
.field("node.transport_address")
.allTerms(true)
.size(9999999)
.order('term')
.facetFilter(filterSrv.getBoolFilter(filterSrv.ids))).size(0);
results = request.doSearch();
results.then(function(r) {
$scope.nodes = _.pluck(r.facets.terms.terms,'term');
var newNodes = _.difference(_.pluck(r.facets.terms.terms,'term'),_.pluck($scope.nodes,'name'));
$scope.nodes = _.map(newNodes, function(n) {
return {
name: n,
selected: false
};
});
$scope.get_data();
});
@ -93,32 +97,32 @@ function (angular, app, kbn, _, $) {
error: 10,
decimals: 2
},{
name: 'System Mem (%)',
field: 'os.mem.used_percent',
warning: 90,
error: 97,
decimals: 2
name: 'System Mem (%)',
field: 'os.mem.used_percent',
warning: 90,
error: 97,
decimals: 2
},{
name: 'Jvm Mem (%)',
field: 'os.mem.used_percent',
warning: 95,
error: 98,
decimals: 2
},{
name: 'Free disk space (GB)',
field: 'fs.data.available_in_bytes',
scale: 1024 * 1024 * 1024,
warning: { threshold: 5, type: "lower_bound" },
error: { threshold: 2, type: "lower_bound" },
decimals: 2
}];
name: 'Jvm Mem (%)',
field: 'os.mem.used_percent',
warning: 95,
error: 98,
decimals: 2
},{
name: 'Free disk space (GB)',
field: 'fs.data.available_in_bytes',
scale: 1024 * 1024 * 1024,
warning: { threshold: 5, type: "lower_bound" },
error: { threshold: 2, type: "lower_bound" },
decimals: 2
}];
_.each($scope.metrics, function (m) {
_.defaults(m, { scale : 1})
if (typeof m.error === 'number') {
_.defaults(m, {scale : 1});
if (_.isNumber(m.error)) {
m.error = { threshold: m.error, type: "upper_bound"};
}
if (typeof m.warning === 'number') {
if (_.isNumber(m.warning)) {
m.warning = { threshold: m.warning, type: "upper_bound"};
}
});
@ -128,7 +132,7 @@ function (angular, app, kbn, _, $) {
var time = filterSrv.timeRange('last').to;
time = kbn.parseDate(time).valueOf();
// Terms mode
_.each($scope.nodes,function(n) {
_.each(_.pluck($scope.nodes,'name'),function(n) {
var filter = $scope.ejs.BoolFilter()
.must($scope.ejs.RangeFilter('@timestamp').from(time + '||-10m/m'))
.must($scope.ejs.TermsFilter('node.transport_address',n));
@ -152,17 +156,31 @@ function (angular, app, kbn, _, $) {
$scope.panelMeta.loading = false;
$scope.warnLevels = {};
$scope.calculateWarnings();
});
};
$scope.hasSelected = function(nodes) {
return _.some(nodes, function(n){
return n.selected;
});
};
$scope.compareLink = function() {
var nodes = _.pluck(_.where($scope.nodes,{selected:true}),'name');
return "#/dashboard/script/node_stats.js?show=OS&nodes="+nodes.join(',');
};
$scope.compareTip = function() {
return $scope.hasSelected($scope.nodes) ? false : 'Select nodes to compare';
};
$scope.calculateWarnings = function () {
$scope.warnLevels = {_global_: {}};
_.each($scope.metrics, function (metric) {
$scope.warnLevels['_global_'][metric.name] = 0;
_.each($scope.nodes, function (node) {
_.each(_.pluck($scope.nodes,'name'), function (node) {
var level = $scope.alertLevel(metric, $scope.data[node + '_' + metric.name].mean);
if (!$scope.warnLevels[node]) $scope.warnLevels[node] = {};
$scope.warnLevels[node] = $scope.warnLevels[node] || {};
$scope.warnLevels[node][metric.name] = level;
if (level > $scope.warnLevels['_global_'][metric.name]) {
$scope.warnLevels['_global_'][metric.name] = level;
@ -171,11 +189,13 @@ function (angular, app, kbn, _, $) {
});
};
$scope.alertLevel = function(metric,num) {
$scope.alertLevel = function(metric,num) {
var level = 0;
function testAlert(alert,num) {
if (!alert) return false;
if (!alert) {
return false;
}
return alert.type === "upper_bound" ? num>alert.threshold : num<alert.threshold;
}
@ -233,7 +253,6 @@ function (angular, app, kbn, _, $) {
// Function for rendering panel
function render_panel() {
// Populate element
//try {
var options = {
legend: { show: false },
series: {
@ -266,13 +285,9 @@ function (angular, app, kbn, _, $) {
color : elem.css('color'),
};
$.plot(elem, [_d], options);
}
//} catch(e) {
// console.log(e);
//}
}
}
};