Rewrote the derivative calculations for the stats table. Ported the index dashboard to a scripted one.

This commit is contained in:
Boaz Leskes 2013-11-15 14:09:20 +01:00
parent 4c25bd87db
commit 7c20322960
6 changed files with 349 additions and 3076 deletions

View file

@ -1,900 +0,0 @@
{
"title": "Indices",
"services": {
"query": {
"idQueue": [],
"list": {
"0": {
"id": 0,
"type": "topN",
"query": "*",
"alias": "",
"color": "#7EB26D",
"pin": false,
"enable": true,
"field": "index",
"size": 6,
"union": "none"
}
},
"ids": [
0
]
},
"filter": {
"idQueue": [],
"list": {
"0": {
"type": "time",
"field": "@timestamp",
"from": "now-1h",
"to": "now",
"mandate": "must",
"active": true,
"alias": "",
"id": 0
},
"1": {
"type": "querystring",
"query": "_type:index_stats",
"mandate": "must",
"active": true,
"alias": "",
"id": 1
}
},
"ids": [
0,
1
]
}
},
"rows": [
{
"title": "Data",
"height": "150px",
"editable": true,
"collapse": true,
"collapsable": true,
"panels": [
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "primaries.docs.count",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Documents",
"extra_filter": "primary:true",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": false,
"scale": 1,
"grid": {
"max": null,
"min": 0
},
"annotate": {
"enable": false,
"query": "*",
"size": 20,
"field": "_type",
"sort": [
"_score",
"desc"
]
}
},
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.store.size_in_bytes",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Index size",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": false,
"scale": 1,
"grid": {
"max": null,
"min": 0
},
"annotate": {
"enable": false,
"query": "*",
"size": 20,
"field": "_type",
"sort": [
"_score",
"desc"
]
}
},
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "primaries.docs.deleted",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Deleted docs",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": false,
"scale": 1,
"grid": {
"max": null,
"min": 0
},
"annotate": {
"enable": false,
"query": "*",
"size": 20,
"field": "_type",
"sort": [
"_score",
"desc"
]
}
}
],
"notice": false
},
{
"title": "Indexing",
"height": "150px",
"editable": true,
"collapse": true,
"collapsable": true,
"panels": [
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "primaries.indexing.index_total",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Indexing requests",
"show_query": true,
"legend_counts": true,
"zerofill": true,
"derivative": true,
"scale": 1,
"grid": {
"max": null,
"min": 0
}
},
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.indexing.index_time_in_millis",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Indexing time",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": true,
"scale": 1,
"grid": {
"max": null,
"min": 0
}
}
],
"notice": false
},
{
"title": "Indexing 2",
"height": "150px",
"editable": true,
"collapse": true,
"collapsable": true,
"panels": [
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.refresh.total_time_in_millis",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Avg Refresh time",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": true,
"scale": 1,
"grid": {
"max": null,
"min": 0
}
}
],
"notice": false
},
{
"title": "Search requests",
"height": "150px",
"editable": true,
"collapse": true,
"collapsable": true,
"panels": [
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.search.query_total",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Search requests",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": true,
"scale": 1,
"grid": {
"max": null,
"min": 0
}
},
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.search.query_time_in_millis",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"show_query": true,
"legend_counts": false,
"x-axis": true,
"y-axis": true,
"percentage": false,
"zerofill": true,
"interactive": true,
"options": true,
"derivative": true,
"scale": 1,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"grid": {
"max": null,
"min": 0
},
"title": "Avg Search time"
},
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "total",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.search.open_contexts",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"title": "Open search context",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": true,
"scale": 1,
"grid": {
"max": null,
"min": 0
}
}
],
"notice": false
},
{
"title": "Get requests",
"height": "150px",
"editable": true,
"collapse": true,
"collapsable": true,
"panels": [
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "total",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.get.total",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1M",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"x-axis": true,
"y-axis": true,
"percentage": false,
"interactive": true,
"options": true,
"tooltip": {
"value_type": "individual",
"query_as_alias": true
},
"title": "GET REQUESTS",
"show_query": true,
"legend_counts": false,
"zerofill": true,
"derivative": true,
"scale": 1,
"grid": {
"max": null,
"min": 0
}
},
{
"span": 4,
"editable": true,
"type": "histogram",
"loadingEditor": false,
"mode": "max",
"time_field": "@timestamp",
"queries": {
"mode": "all",
"ids": [
0
]
},
"value_field": "total.get.time_in_millis",
"auto_int": true,
"resolution": 30,
"interval": "1m",
"intervals": [
"auto",
"1s",
"1m",
"5m",
"10m",
"30m",
"1h",
"3h",
"12h",
"1d",
"1w",
"1y"
],
"fill": 0,
"linewidth": 3,
"timezone": "browser",
"spyable": true,
"zoomlinks": true,
"bars": false,
"stack": false,
"points": false,
"lines": true,
"legend": true,
"show_query": true,
"legend_counts": false,
"x-axis": true,
"y-axis": true,
"percentage": false,
"zerofill": true,
"interactive": true,
"options": true,
"derivative": true,
"scale": 1,
"tooltip": {
"value_type": "cumulative",
"query_as_alias": true
},
"grid": {
"max": null,
"min": 0
},
"title": "Avg Get time"
}
],
"notice": false
}
],
"editable": true,
"failover": false,
"index": {
"interval": "day",
"pattern": "[es_monitor-]YYYY.MM.DD",
"default": "_all"
},
"style": "dark",
"panel_hints": true,
"pulldowns": [
{
"type": "query",
"collapse": false,
"notice": false,
"enable": true,
"query": "*",
"pinned": true,
"history": [
"_type:index_stats",
"*",
"index:\"index2\" AND (_type:shard_stats)",
"index:\"es_monitor-2013.10.16\" AND (_type:shard_stats)",
"index:\"kibana-int\" AND (_type:shard_stats)",
"index:\"index\" AND (_type:shard_stats)",
"index:\"es_monitor-2013.10.15\" AND (_type:shard_stats)"
],
"remember": 10
},
{
"type": "filtering",
"collapse": true,
"notice": false,
"enable": true
}
],
"nav": [
{
"type": "timepicker",
"collapse": false,
"notice": false,
"enable": true,
"status": "Stable",
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
],
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"timefield": "@timestamp",
"now": true,
"filter_id": 0
}
],
"loader": {
"save_gist": true,
"save_elasticsearch": true,
"save_local": true,
"save_default": true,
"save_temp": true,
"save_temp_ttl_enable": true,
"save_temp_ttl": "30d",
"load_gist": true,
"load_elasticsearch": true,
"load_elasticsearch_size": 20,
"load_local": true,
"hide": false
},
"refresh": false
}

View file

@ -1 +1,236 @@
// STUB
/* global _ */
/*
* Node statistics scripted dashboard
* This script generates a dashboard object that Kibana can load.
*
* Parameters (all optional)
* nodes :: By default, a comma seperated list of queries to run. Default: *
* show :: The names of the rows to expand
* from :: Search this amount of time back, eg 15m, 1h, 2d. Default: 1d
*
*/
'use strict';
// Setup some variables
var dashboard, queries, _d_timespan;
// All url parameters are available via the ARGS object
var ARGS;
// Set a default timespan if one isn't specified
_d_timespan = '1d';
// Intialize a skeleton with nothing but a rows array and service object
dashboard = {
rows: [],
services: {}
};
// Set a title
dashboard.title = 'Marvel - Index Statistics';
// And the index options
dashboard.failover = false;
dashboard.index = {
'default': 'ADD_A_TIME_FILTER',
'pattern': '[marvel-]YYYY.MM.DD',
'interval': 'day'
};
// In this dashboard we let users pass nodes as comma seperated list to the query parameter.
// If nodes are defined, split into a list of query objects, otherwise, show all
// NOTE: ids must be integers, hence the parseInt()s
if (!_.isUndefined(ARGS.queries)) {
queries = _.object(_.map(JSON.parse(ARGS.queries), function (v, k) {
return [k, {
query: v.q,
alias: v.a || v.q,
pin: true,
id: parseInt(k, 10)
}];
}));
} else {
// No queries passed? Initialize a single query to match everything
queries = {
0: {
query: '*',
id: 0
}
};
}
var show = (ARGS.show || "").split(',');
// Now populate the query service with our objects
dashboard.services.query = {
list: queries,
ids: _.map(_.keys(queries), function (v) {
return parseInt(v, 10);
})
};
// Lets also add a default time filter, the value of which can be specified by the user
dashboard.services.filter = {
list: {
0: {
from: ARGS.from || "now-" + _d_timespan,
to: ARGS.to || "now",
field: "@timestamp",
type: "time",
active: true,
id: 0
},
1: {
type: "querystring",
mandate: "must",
active: true,
alias: "index stats",
query: "_type:index_stats",
id: 1
}
},
ids: [0, 1]
};
var row_defaults = {
height: "150px",
collapse: true,
collapsable: true
};
var panel_defaults_by_type = {};
panel_defaults_by_type["histogram"] = {
span: 4,
time_field: '@timestamp',
bars: false,
lines: true,
stack: false,
linewidth: 2,
mode: 'max',
zoomlinks: false,
options: false,
legend: true,
resolution: 20
};
var rows = [
{
"title": "Data",
"panels": [
{
"value_field": "primaries.docs.count",
"title": "Documents",
},
{
"value_field": "total.store.size_in_bytes",
"title": "Index size",
},
{
"value_field": "primaries.docs.deleted",
"title": "Deleted docs",
}
],
"notice": false
},
{
"title": "Indexing",
"panels": [
{
"value_field": "primaries.indexing.index_total",
"derivative": true,
"mode": "min",
"scaleSeconds": true
},
{
"value_field": "total.indexing.index_time_in_millis",
"title": "Indexing time",
"derivative": true,
"mode": "min",
"scaleSeconds": true
}
]
},
{
"title": "Indexing 2",
"panels": [
{
"value_field": "total.refresh.total_time_in_millis",
"title": "Avg Refresh time",
"derivative": true,
"mode": "min",
"scaleSeconds": true
}
]
},
{
"title": "Search requests",
"panels": [
{
"value_field": "total.search.query_total",
"title": "Search requests",
"derivative": true,
"mode": "min",
"scaleSeconds": true
},
{
"value_field": "total.search.open_contexts",
"title": "Open search contexts",
}
]
},
{
"title": "Get requests",
"panels": [
{
"value_field": "total.get.total",
"title": "Get requests",
"derivative": true,
"mode": "min",
"scaleSeconds": true
}
],
}
];
var showedSomething;
dashboard.rows = _.map(rows, function (r) {
_.defaults(r, row_defaults);
_.each(r.panels, function (panel) {
if (!panel.type) {
panel.type = "histogram";
}
_.defaults(panel, panel_defaults_by_type[panel.type]);
if (_.contains(show, panel.value_field)) {
showedSomething = true;
r.collapse = false;
}
});
return r;
});
if (!showedSomething && dashboard.rows.length > 0) {
dashboard.rows[0].collapse = false;
}
dashboard.pulldowns = [
{
"type": "query",
"collapse": false,
"notice": false,
"enable": true
},
{
"type": "filtering",
"collapse": true
}
];
// Now return the object and we're good!
return dashboard;

File diff suppressed because it is too large Load diff

View file

@ -66,7 +66,7 @@
<i class="pointer icon-check" ng-click="metricEditor.index=-1"></i>
</td>
<td ng-show="metricEditor.index == $index">
<i ng-click="deleteMetric($index)" class="pointer icon-remove"></i>
<i ng-click="deleteMetric($index); metricEditor.index = -1;" class="pointer icon-remove"></i>
<td ng-show="metricEditor.index == $index">
<i class="icon"></i></td>
</tr>

View file

@ -1,4 +1,4 @@
<div ng-controller='marvel.nodes_health' ng-init="init()">
<div ng-controller='marvel.stats_table' ng-init="init()">
<style>
.marvel-table {
vertical-align: middle;
@ -62,16 +62,15 @@
</td>
<td ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels[row.id][metric.field])">
<div class="marvel-mean pointer" ng-click="metricClick(row,metric)">
<span ng-hide="metric.rate">{{data[row.id+"_"+metric.field].mean / metric.scale | number:metric.decimals}}</span>
<span ng-show="metric.rate">{{(data[row.id+"_"+metric.field].max-data[row.id+"_"+metric.field].min) / 600 / metric.scale | number:metric.decimals}}</span>
<span>{{data[row.id+"_"+metric.field].mean | number:metric.decimals}}</span>
<br>
<div class="marvel-nodes-health-chart" panel='panel' field="metric.field" series="data[row.id+'_'+metric.field+'_history']"></div>
<div class="marvel-nodes-health-chart" panel='panel' field="metric.field" series="data[row.id+'_'+metric.field+'_history'].series"></div>
</div>
<div class="marvel-extended pointer" ng-click="metricClick(row,metric)" ng-hide="metric.rate">
<span>min: {{data[row.id+"_"+metric.field].min / metric.scale | number:metric.decimals}}</span><br>
<span>max: {{data[row.id+"_"+metric.field].max / metric.scale | number:metric.decimals}}</span>
<div class="marvel-extended pointer" ng-click="metricClick(row,metric)">
<span>min: {{data[row.id+"_"+metric.field].min | number:metric.decimals}}</span><br>
<span>max: {{data[row.id+"_"+metric.field].max | number:metric.decimals}}</span>
</div>
</td>
</tr>
@ -93,10 +92,9 @@
</td>
<td ng-repeat="metric in panel.metrics" ng-class="alertClass(warnLevels[row.id][metric.field])">
<div class="pointer" ng-click="metricClick(row,metric)">
<span ng-hide="metric.rate">{{data[row.id+"_"+metric.field].mean / metric.scale | number:metric.decimals}}</span>
<span ng-show="metric.rate">{{(data[row.id+"_"+metric.field].max-data[row.id+"_"+metric.field].min) / 600 / metric.scale | number:metric.decimals}}</span>
<span>{{data[row.id+"_"+metric.field].mean | number:metric.decimals}}</span>
<div class="marvel-nodes-health-chart pointer" ng-click="metricClick(row,metric)" panel='panel' field="metric.field" series="data[row.id+'_'+metric.field+'_history']"></div>
<div class="marvel-nodes-health-chart pointer" ng-click="metricClick(row,metric)" panel='panel' field="metric.field" series="data[row.id+'_'+metric.field+'_history'].series"></div>
</div>
</td>
</tr>

View file

@ -10,10 +10,10 @@ define([
function (angular, app, kbn, _, $) {
'use strict';
var module = angular.module('kibana.panels.marvel.nodes_health', []);
var module = angular.module('kibana.panels.marvel.stats_table', []);
app.useModule(module);
module.controller('marvel.nodes_health', function ($scope, dashboard, filterSrv) {
module.controller('marvel.stats_table', function ($scope, dashboard, filterSrv) {
$scope.panelMeta = {
modals: [],
editorTabs: [],
@ -75,12 +75,12 @@ define([
scale: 1024 * 1024 * 1024
},
/* Dropping this until we have error handling for fields that don't exist
{
// allow people to add a new, not-predefined metric.
name: 'Custom',
field: ''
}
*/
{
// allow people to add a new, not-predefined metric.
name: 'Custom',
field: ''
}
*/
]
},
indices: {
@ -97,30 +97,30 @@ define([
{
name: 'Index Rate',
field: 'primaries.indexing.index_total',
rate: true
derivative: true
},
{
name: 'Search Rate',
field: 'total.search.query_total',
rate: true,
derivative: true,
},
{
name: 'Merges',
field: 'total.merges.current',
},
/* Dropping this until we have error handling for fields that don't exist
{
// allow people to add a new, not-predefined metric.
name: 'Custom',
field: ''
}
*/
{
// allow people to add a new, not-predefined metric.
name: 'Custom',
field: ''
}
*/
]
}
};
var metricDefaults = function (m) {
if(_.isUndefined($scope.modeInfo[$scope.panel.mode])) {
if (_.isUndefined($scope.modeInfo[$scope.panel.mode])) {
return [];
}
if (_.isString(m)) {
@ -145,8 +145,8 @@ define([
return metricDefaults(m);
});
$scope.$watch('panel.mode',function(m) {
if(_.isUndefined(m)) {
$scope.$watch('panel.mode', function (m) {
if (_.isUndefined(m)) {
return;
}
$scope.panel.display_field = $scope.modeInfo[m].defaults.display_field;
@ -154,7 +154,7 @@ define([
$scope.panel.metrics = _.map($scope.modeInfo[m].defaults.metrics, function (m) {
return metricDefaults(m);
});
_.throttle($scope.get_rows(),500);
_.throttle($scope.get_rows(), 500);
});
$scope.init = function () {
@ -165,7 +165,7 @@ define([
});
};
$scope.get_mode_filter = function () {
$scope.get_mode_filter = function () {
return $scope.ejs.TermFilter("_type", $scope.panel.mode === "nodes" ? "node_stats" : "index_stats");
};
@ -267,14 +267,15 @@ define([
request = $scope.ejs.Request().indices(dashboard.indices);
var to = filterSrv.timeRange('last').to;
var from = new Date(to);
from.setMinutes(from.getMinutes()-10,0,0);
to = kbn.parseDate(to).valueOf();
from = kbn.parseDate(from).valueOf();
var to = filterSrv.timeRange(false).to;
if (to !== "now") {
to = kbn.parseDate(to).valueOf() + "||";
}
//to = kbn.parseDate(to).valueOf();
_.each(_.pluck(newRows, 'id'), function (id) {
var filter = $scope.ejs.BoolFilter()
.must($scope.ejs.RangeFilter('@timestamp').from(from).to(to))
.must($scope.ejs.RangeFilter('@timestamp').from(to + "-10m/m").to(to + "/m"))
.must($scope.ejs.TermsFilter($scope.panel.persistent_field, id))
.must($scope.get_mode_filter());
@ -294,12 +295,73 @@ define([
// Populate scope when we have results
results.then(function (results) {
$scope.rows = newRows;
$scope.data = results.facets;
$scope.data = normalizeFacetResults(results.facets, newRows, $scope.panel.metrics);
$scope.panelMeta.loading = false;
$scope.calculateWarnings();
});
};
var normalizeFacetResults = function (facets, rows, metrics) {
_.each(metrics, function (m) {
_.each(_.pluck(rows, 'id'), function (id) {
var summary_key = id + "_" + m.field;
var history_key = id + "_" + m.field + "_history";
var summary = facets[summary_key];
var series_data = _.pluck(facets[history_key].entries, m.derivative ? 'min' : 'mean');
var series_time = _.pluck(facets[history_key].entries, 'time');
if (m.scale !== 1) {
series_data = _.map(series_data, function (v) {
return v / m.scale;
});
summary.mean /= m.scale;
summary.max /= m.scale;
summary.max /= m.scale;
}
if (m.derivative) {
var _l = series_data.length - 1;
if (_l <= 0) {
summary.mean = null;
}
else {
var avg_time = (series_time[_l] - series_time[0]) / 1000;
summary.mean = (series_data[_l] - series_data[0]) / avg_time;
}
series_data = _.map(series_data, function (p, i) {
var _v;
if (i === 0) {
_v = null;
} else {
var _t = ((series_time[i] - series_time[i - 1]) / 1000); // milliseconds -> seconds.
_v = (p - series_data[i - 1]) / _t;
}
return _v;
});
summary.max = _.reduce(series_data, function (m, v) {
return m < v && v != null ? v : m;
}, Number.NEGATIVE_INFINITY);
summary.min = _.reduce(series_data, function (m, v) {
return m > v && v != null ? v : m;
}, Number.POSITIVE_INFINITY);
}
var series = _.zip(series_time, series_data);
facets[summary_key] = summary;
facets[history_key].series = series;
});
});
return facets;
};
$scope.hasSelected = function (nodes) {
return _.some(nodes, function (n) {
return n.selected;
@ -321,6 +383,7 @@ define([
};
$scope.detailViewLink = function (rows, fields) {
if (_.isUndefined(rows)) {
rows = _.where($scope.rows, {selected: true});
@ -340,10 +403,19 @@ define([
} else {
show = "";
}
return "#/dashboard/script/marvel."+$scope.panel.mode+"_stats.js?queries=" + encodeURI(rows) + "&from=" +
return "#/dashboard/script/marvel." + $scope.panel.mode + "_stats.js?queries=" + encodeUriSegment(rows) + "&from=" +
time.from + "&to=" + time.to + show;
};
// stolen from anuglar to have exactly the same url structure and thus no reloads.
function encodeUriSegment(val) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',');
}
$scope.detailViewTip = function () {
return $scope.hasSelected($scope.rows) ? 'Open nodes dashboard for selected nodes' :
'Select nodes and click top open the nodes dashboard';
@ -355,11 +427,7 @@ define([
$scope.warnLevels._global_[metric.field] = 0;
_.each(_.pluck($scope.rows, 'id'), function (id) {
var num, level;
if(metric.rate) {
num = ($scope.data[id + '_' + metric.field].max - $scope.data[id + '_' + metric.field].max)/600;
} else {
num = $scope.data[id + '_' + metric.field].mean;
}
num = $scope.data[id + '_' + metric.field].mean;
level = $scope.alertLevel(metric, num);
$scope.warnLevels[id] = $scope.warnLevels[id] || {};
$scope.warnLevels[id][metric.field] = level;
@ -441,7 +509,7 @@ define([
// This is expensive, it would be better to populate a scope object
$scope.addMetricOptions = function (m) {
if(_.isUndefined($scope.modeInfo[m])) {
if (_.isUndefined($scope.modeInfo[m])) {
return [];
}
var fields = _.pluck($scope.panel.metrics, 'field');
@ -524,15 +592,8 @@ define([
};
if (!_.isUndefined(scope.series)) {
var metric = _.findWhere(scope.panel.metrics, { "field": scope.field });
var _d = {
data: _.map(scope.series.entries, function (p) {
if(metric.rate) {
return [p.time, (p.max-p.min)];
} else {
return [p.time, p.mean];
}
}),
data: scope.series,
color: elem.css('color')
};