mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
Metrics are now consistently use the field as an id. Added the option to edit field names. Added the option to add a custom metric.
Also the node_stats panel now opens in the same page.
This commit is contained in:
parent
687a8020cb
commit
dcf4fe7413
4 changed files with 91 additions and 56 deletions
|
@ -30,7 +30,9 @@
|
|||
<input ng-show="metricEditor.index == $index" type="text" class="input-medium" ng-model="metric.name" ng-required/></td>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{metric.field}}</span>
|
||||
<span ng-show="metricEditor.index != $index">{{metric.field}}</span>
|
||||
<input ng-show="metricEditor.index == $index" placeholder="field name"
|
||||
type="text" bs-typeahead="fields.list" class="input-medium" ng-model="metric.field" ng-required/></td>
|
||||
</td>
|
||||
<td>
|
||||
<span ng-show="metricEditor.index != $index">{{formatAlert(metric.warning)}}</span>
|
||||
|
@ -66,12 +68,12 @@
|
|||
</table>
|
||||
<form class="form-inline">
|
||||
<select ng-model="metricEditor.add">
|
||||
<option ng-repeat="(field,metric) in availableMetrics"
|
||||
value="{{field}}">
|
||||
{{availableMetrics[field]['name']}}
|
||||
<option ng-repeat="metric in addMetricOptions()"
|
||||
value="{{metric.field}}">
|
||||
{{metric.name}}
|
||||
</option>
|
||||
</select>
|
||||
<button class="btn btn-success" ng-click="addMetric(metricEditor.add);metricEditor.add=undefined" ng-disabled="!metricEditor.add">
|
||||
<button class="btn btn-success" ng-click="addMetric(metricEditor.add);metricEditor.add=undefined" ng-disabled="metricEditor.add === undefined">
|
||||
Add Metric</button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -45,10 +45,10 @@
|
|||
<table class="table table-bordered" ng-if="!panel.compact">
|
||||
<thead>
|
||||
|
||||
<th ng-if="hasSelected(nodes)">node <a id="detail_view_link" ng-href="{{detailViewLink()}}" target="_blank" class="btn btn-mini btn-info" bs-tooltip="detailViewTip()" data-placement="right">nodes dashboard</a></th>
|
||||
<th ng-if="hasSelected(nodes)">node <a id="detail_view_link" ng-href="{{detailViewLink()}}" class="btn btn-mini btn-info" bs-tooltip="detailViewTip()" data-placement="right">nodes dashboard</a></th>
|
||||
<th ng-if="!hasSelected(nodes)">node <a id="detail_view_link" disabled class="btn btn-mini btn-info" bs-tooltip="detailViewTip()" data-placement="right">nodes dashboard</a></th>
|
||||
|
||||
<th ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels['_global_'][metric.name])">{{metric.name}}</th>
|
||||
<th ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels['_global_'][metric.field])">{{metric.name}}</th>
|
||||
</thead>
|
||||
<tr ng-repeat="node in nodes">
|
||||
<td>
|
||||
|
@ -60,15 +60,15 @@
|
|||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels[node.id][metric.name])">
|
||||
<td ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels[node.id][metric.field])">
|
||||
<div class="marvel-mean pointer" ng-click="metricClick(node,metric)">
|
||||
{{data[node.id+"_"+metric.name].mean / metric.scale | number:metric.decimals}}<br>
|
||||
{{data[node.id+"_"+metric.field].mean / metric.scale | number:metric.decimals}}<br>
|
||||
|
||||
<div class="marvel-nodes-health-chart" series="data[node.id+'_'+metric.name+'_history']"></div>
|
||||
<div class="marvel-nodes-health-chart" series="data[node.id+'_'+metric.field+'_history']"></div>
|
||||
</div>
|
||||
<div class="marvel-extended pointer" ng-click="metricClick(node,metric)">
|
||||
<span>min: {{data[node.id+"_"+metric.name].min / metric.scale | number:metric.decimals}}</span><br>
|
||||
<span>max: {{data[node.id+"_"+metric.name].max / metric.scale | number:metric.decimals}}</span>
|
||||
<span>min: {{data[node.id+"_"+metric.field].min / metric.scale | number:metric.decimals}}</span><br>
|
||||
<span>max: {{data[node.id+"_"+metric.field].max / metric.scale | number:metric.decimals}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -77,7 +77,7 @@
|
|||
<table class="table table-bordered table-condensed marvel-table" ng-if="panel.compact">
|
||||
<thead>
|
||||
<th>node <a ng-href="{{detailViewLink()}}" class="btn btn-mini btn-info" ng-disabled="!hasSelected(nodes)" bs-tooltip="detailViewTip()" data-placement="right">nodes dashboard</a></th>
|
||||
<th ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels['_global_'][metric.name])">{{metric.name}}</th>
|
||||
<th ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels['_global_'][metric.field])">{{metric.name}}</th>
|
||||
</thead>
|
||||
<tr ng-repeat="node in nodes">
|
||||
<td>
|
||||
|
@ -88,9 +88,9 @@
|
|||
{{ node.display_name }}
|
||||
</div>
|
||||
</td>
|
||||
<td ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels[node.id][metric.name])">
|
||||
<div class="pointer" ng-click="metricClick(node,metric)">{{data[node.id+"_"+metric.name].mean / metric.scale | number:metric.decimals}}
|
||||
<div class="marvel-nodes-health-chart pointer" ng-click="metricClick(node,metric)" series="data[node.id+'_'+metric.name+'_history']"></div>
|
||||
<td ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels[node.id][metric.field])">
|
||||
<div class="pointer" ng-click="metricClick(node,metric)">{{data[node.id+"_"+metric.field].mean / metric.scale | number:metric.decimals}}
|
||||
<div class="marvel-nodes-health-chart pointer" ng-click="metricClick(node,metric)" series="data[node.id+'_'+metric.field+'_history']"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -26,53 +26,70 @@ define([
|
|||
compact: false,
|
||||
node_display_field: "node.name", // used as primary display string for a node.
|
||||
node_persistent_field: "node.transport_address", // used as node identity - i.e., search queries, facets etc.
|
||||
metrics: [
|
||||
{field: 'process.cpu.percent'},
|
||||
{field: 'os.load_average.1m'},
|
||||
{field: 'os.mem.used_percent'},
|
||||
{field: 'fs.data.available_in_bytes'}
|
||||
]
|
||||
metrics: [ 'process.cpu.percent', 'os.load_average.1m', 'os.mem.used_percent', 'fs.data.available_in_bytes' ]
|
||||
};
|
||||
_.defaults($scope.panel, _d);
|
||||
|
||||
// editedMetricIndex was not working because the ng-repeat was creating a new scope.
|
||||
// By using metricEditor.index we pass the index property by reference.
|
||||
$scope.metricEditor = {
|
||||
index : -1,
|
||||
add : undefined
|
||||
index: -1,
|
||||
add: undefined
|
||||
};
|
||||
|
||||
// The allowed metrics and their defaults, from which we can create a select list
|
||||
$scope.availableMetrics = {
|
||||
'process.cpu.percent': {
|
||||
$scope.availableMetrics = [
|
||||
{
|
||||
name: 'CPU (%)',
|
||||
field: 'process.cpu.percent',
|
||||
warning: 60,
|
||||
error: 90,
|
||||
error: 90
|
||||
},
|
||||
'os.load_average.1m' : {
|
||||
{
|
||||
name: 'Load (1m)',
|
||||
field: 'os.load_average.1m',
|
||||
warning: 8,
|
||||
error: 10,
|
||||
error: 10
|
||||
},
|
||||
'os.mem.used_percent': {
|
||||
{
|
||||
name: 'Jvm Mem (%)',
|
||||
field: 'os.mem.used_percent',
|
||||
warning: 95,
|
||||
error: 98,
|
||||
},
|
||||
'fs.data.available_in_bytes' : {
|
||||
name: 'Free disk space (GB)',
|
||||
warning: { threshold: 5, type: "lower_bound" },
|
||||
error: { threshold: 2, type: "lower_bound" },
|
||||
scale: 1024 * 1024 * 1024,
|
||||
error: 98
|
||||
}
|
||||
};
|
||||
,
|
||||
{
|
||||
name: 'Free disk space (GB)',
|
||||
field: 'fs.data.available_in_bytes',
|
||||
warning: {
|
||||
threshold: 5,
|
||||
type: "lower_bound"
|
||||
},
|
||||
error: {
|
||||
threshold: 2,
|
||||
type: "lower_bound"
|
||||
},
|
||||
scale: 1024 * 1024 * 1024
|
||||
},
|
||||
{
|
||||
name: 'Field data size (MB)',
|
||||
field: 'indices.fielddata.memory_size_in_bytes',
|
||||
scale: 1024 * 1024
|
||||
},
|
||||
{
|
||||
// allow people to add a new, not-predefined metric.
|
||||
name: 'Custom',
|
||||
field: ''
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
$scope.init = function () {
|
||||
$scope.warnLevels = {};
|
||||
$scope.nodes = [];
|
||||
|
||||
_.each($scope.panel.metrics, function (m) {
|
||||
m = metricDefaults(m);
|
||||
$scope.panel.metrics = _.map($scope.panel.metrics, function (m) {
|
||||
return metricDefaults(m);
|
||||
});
|
||||
|
||||
$scope.$on('refresh', function () {
|
||||
|
@ -180,11 +197,11 @@ define([
|
|||
|
||||
_.each($scope.panel.metrics, function (m) {
|
||||
request = request
|
||||
.facet($scope.ejs.StatisticalFacet(id + "_" + m.name)
|
||||
.field(m.field || m.name)
|
||||
.facet($scope.ejs.StatisticalFacet(id + "_" + m.field)
|
||||
.field(m.field)
|
||||
.facetFilter(filter));
|
||||
request = request.facet($scope.ejs.DateHistogramFacet(id + "_" + m.name + "_history")
|
||||
.keyField('@timestamp').valueField(m.field || m.name).interval('1m')
|
||||
request = request.facet($scope.ejs.DateHistogramFacet(id + "_" + m.field + "_history")
|
||||
.keyField('@timestamp').valueField(m.field).interval('1m')
|
||||
.facetFilter(filter)).size(0);
|
||||
});
|
||||
});
|
||||
|
@ -253,13 +270,13 @@ define([
|
|||
$scope.calculateWarnings = function () {
|
||||
$scope.warnLevels = {_global_: {}};
|
||||
_.each($scope.panel.metrics, function (metric) {
|
||||
$scope.warnLevels._global_[metric.name] = 0;
|
||||
$scope.warnLevels._global_[metric.field] = 0;
|
||||
_.each(_.pluck($scope.nodes, 'id'), function (nodeID) {
|
||||
var level = $scope.alertLevel(metric, ($scope.data[nodeID + '_' + metric.name] || {}).mean);
|
||||
var level = $scope.alertLevel(metric, ($scope.data[nodeID + '_' + metric.field] || {}).mean);
|
||||
$scope.warnLevels[nodeID] = $scope.warnLevels[nodeID] || {};
|
||||
$scope.warnLevels[nodeID][metric.name] = level;
|
||||
if (level > $scope.warnLevels._global_[metric.name]) {
|
||||
$scope.warnLevels._global_[metric.name] = level;
|
||||
$scope.warnLevels[nodeID][metric.field] = level;
|
||||
if (level > $scope.warnLevels._global_[metric.field]) {
|
||||
$scope.warnLevels._global_[metric.field] = level;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -325,9 +342,13 @@ define([
|
|||
|
||||
};
|
||||
|
||||
var metricDefaults = function(m) {
|
||||
var _metric_defaults = {name: "", decimals: 2, scale: 1};
|
||||
m = _.defaults({field:m},$scope.availableMetrics[m]);
|
||||
var metricDefaults = function (m) {
|
||||
if (typeof m === "string") {
|
||||
m = { "field": m };
|
||||
}
|
||||
m = _.defaults(m, _.findWhere($scope.availableMetrics, { "field": m.field }));
|
||||
|
||||
var _metric_defaults = {field: "", decimals: 2, scale: 1};
|
||||
m = _.defaults(m, _metric_defaults);
|
||||
|
||||
if (_.isNumber(m.error)) {
|
||||
|
@ -343,11 +364,22 @@ define([
|
|||
$scope.addMetric = function (metric) {
|
||||
metric = metricDefaults(metric);
|
||||
$scope.panel.metrics.push(metric);
|
||||
if (!metric.field) {
|
||||
// no field defined, got into edit mode..
|
||||
$scope.metricEditor.index = $scope.panel.metrics.length - 1;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.close_edit = function() {
|
||||
$scope.addMetricOptions = function () {
|
||||
var fields = _.pluck($scope.panel.metrics, 'field');
|
||||
return _.filter($scope.availableMetrics, function (value) {
|
||||
return !_.contains(fields, value.field);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.close_edit = function () {
|
||||
$scope.metricEditor = {
|
||||
index : -1
|
||||
index: -1
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -445,4 +477,5 @@ define([
|
|||
});
|
||||
|
||||
|
||||
});
|
||||
})
|
||||
;
|
2
pom.xml
2
pom.xml
|
@ -25,7 +25,7 @@
|
|||
</parent>
|
||||
|
||||
<properties>
|
||||
<elasticsearch.version>0.90.6</elasticsearch.version>
|
||||
<elasticsearch.version>0.90.7-SNAPSHOT</elasticsearch.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue