mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(elasticsearch): terms aggregation options are working, things are starting to come together, #1034
This commit is contained in:
parent
2d832e10b0
commit
3e9aca3ed4
@ -1,23 +0,0 @@
|
|||||||
define([
|
|
||||||
'angular',
|
|
||||||
'lodash',
|
|
||||||
'jquery',
|
|
||||||
],
|
|
||||||
function (angular, _, $) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.directives')
|
|
||||||
.directive('tightFormAdvancedOption', function($compile, uiSegmentSrv, $q) {
|
|
||||||
return {
|
|
||||||
templateUrl: 'app/plugins/datasource/elasticsearch/partials/advancedOption.html',
|
|
||||||
restrict: 'E',
|
|
||||||
scope: {
|
|
||||||
model: "=",
|
|
||||||
option: "=",
|
|
||||||
},
|
|
||||||
link: function postLink($scope, elem) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,112 +1,95 @@
|
|||||||
define([
|
define([
|
||||||
'angular',
|
'angular',
|
||||||
'lodash',
|
'lodash',
|
||||||
'jquery',
|
'./queryDef',
|
||||||
],
|
],
|
||||||
function (angular, _, $) {
|
function (angular, _, queryDef) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var module = angular.module('grafana.directives');
|
var module = angular.module('grafana.directives');
|
||||||
|
|
||||||
module.controller('ElasticBucketAggCtrl', function($scope, uiSegmentSrv, $q) {
|
module.controller('ElasticBucketAggCtrl', function($scope, uiSegmentSrv, $q, $rootScope) {
|
||||||
var bucketAggs = $scope.target.bucketAggs;
|
var bucketAggs = $scope.target.bucketAggs;
|
||||||
|
|
||||||
$scope.bucketAggTypes = [
|
$scope.orderByOptions = [];
|
||||||
{text: "Terms", value: 'terms' },
|
$scope.bucketAggTypes = queryDef.bucketAggTypes;
|
||||||
{text: "Date Histogram", value: 'date_histogram' },
|
$scope.orderOptions = queryDef.orderOptions;
|
||||||
];
|
$scope.sizeOptions = queryDef.sizeOptions;
|
||||||
|
|
||||||
$scope.orderOptions = [
|
$rootScope.onAppEvent('elastic-query-updated', function() {
|
||||||
{text: "Top", value: 'desc' },
|
$scope.validateModel();
|
||||||
{text: "Bottom", value: 'asc' },
|
$scope.updateOrderByOptions();
|
||||||
];
|
});
|
||||||
|
|
||||||
$scope.sizeOptions = [
|
$scope.init = function() {
|
||||||
{text: "No limit", value: '0' },
|
$scope.agg = bucketAggs[$scope.index];
|
||||||
{text: "1", value: '1' },
|
$scope.validateModel();
|
||||||
{text: "2", value: '2' },
|
};
|
||||||
{text: "3", value: '4' },
|
|
||||||
{text: "5", value: '5' },
|
|
||||||
{text: "10", value: '10' },
|
|
||||||
{text: "15", value: '15' },
|
|
||||||
{text: "20", value: '20' },
|
|
||||||
];
|
|
||||||
|
|
||||||
$scope.$watch("index", function() {
|
$scope.onChangeInternal = function() {
|
||||||
$scope.isFirst = $scope.index === 0;
|
if ($scope.validateModel()) {
|
||||||
$scope.isLast = $scope.index === bucketAggs.length - 1;
|
$scope.onChange();
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$scope.init = function() {
|
$scope.validateModel = function() {
|
||||||
$scope.agg = bucketAggs[$scope.index];
|
$scope.isFirst = $scope.index === 0;
|
||||||
$scope.modelIsValid();
|
$scope.isLast = $scope.index === bucketAggs.length - 1;
|
||||||
};
|
$scope.aggOptionsString = "";
|
||||||
|
|
||||||
$scope.onChangeInternal = function() {
|
if ($scope.agg.type === "terms") {
|
||||||
if ($scope.modelIsValid()) {
|
$scope.agg.order = $scope.agg.order || "desc";
|
||||||
$scope.onChange();
|
$scope.agg.size = $scope.agg.size || "0";
|
||||||
|
$scope.agg.orderBy = $scope.agg.orderBy || "_count";
|
||||||
|
|
||||||
|
if ($scope.agg.size === '0') {
|
||||||
|
$scope.aggOptionsString = "";
|
||||||
|
} else {
|
||||||
|
$scope.aggOptionsString = queryDef.describeOrder($scope.agg.order) + ' ' + $scope.agg.size + ', '
|
||||||
}
|
}
|
||||||
};
|
$scope.aggOptionsString += 'Order by: ' + queryDef.describeOrderBy($scope.agg.orderBy, $scope.target);
|
||||||
|
|
||||||
$scope.modelIsValid = function() {
|
if ($scope.agg.size === '0') {
|
||||||
if ($scope.agg.type === "terms") {
|
$scope.aggOptionsString += ' (' + $scope.agg.order + ')';
|
||||||
$scope.aggOptionsString = "Top 5, Order by: sum @value";
|
|
||||||
|
|
||||||
$scope.agg.order = $scope.agg.order || "desc";
|
|
||||||
$scope.agg.size = $scope.agg.size || "0";
|
|
||||||
$scope.agg.orderBy = $scope.agg.orderBy || "_count";
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.toggleOptions = function() {
|
|
||||||
$scope.showOptions = !$scope.showOptions;
|
|
||||||
|
|
||||||
$scope.orderByOptions = [
|
|
||||||
{text: "Doc Count", value: '_count' },
|
|
||||||
{text: "Term name", value: '_term' },
|
|
||||||
{text: "Average of @value", value: '1' },
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.addBucketAgg = function() {
|
return true;
|
||||||
// if last is date histogram add it before
|
};
|
||||||
var lastBucket = bucketAggs[bucketAggs.length - 1];
|
|
||||||
var addIndex = bucketAggs.length - 1;
|
|
||||||
|
|
||||||
if (lastBucket && lastBucket.type === 'date_histogram') {
|
$scope.toggleOptions = function() {
|
||||||
addIndex - 1;
|
$scope.showOptions = !$scope.showOptions;
|
||||||
}
|
$scope.updateOrderByOptions();
|
||||||
|
};
|
||||||
|
|
||||||
var id = _.reduce($scope.target.bucketAggs.concat($scope.target.metrics), function(max, val) {
|
$scope.updateOrderByOptions = function() {
|
||||||
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
$scope.orderByOptions = queryDef.getOrderByOptions($scope.target);
|
||||||
}, 0);
|
};
|
||||||
|
|
||||||
bucketAggs.splice(addIndex, 0, {type: "terms", field: "select field", id: (id+1).toString()});
|
$scope.addBucketAgg = function() {
|
||||||
};
|
// if last is date histogram add it before
|
||||||
|
var lastBucket = bucketAggs[bucketAggs.length - 1];
|
||||||
|
var addIndex = bucketAggs.length - 1;
|
||||||
|
|
||||||
$scope.removeBucketAgg = function() {
|
if (lastBucket && lastBucket.type === 'date_histogram') {
|
||||||
bucketAggs.splice($scope.index, 1);
|
addIndex - 1;
|
||||||
$scope.onChange();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
$scope.init();
|
var id = _.reduce($scope.target.bucketAggs.concat($scope.target.metrics), function(max, val) {
|
||||||
|
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
});
|
bucketAggs.splice(addIndex, 0, {type: "terms", field: "select field", id: (id+1).toString()});
|
||||||
|
$scope.onChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.removeBucketAgg = function() {
|
||||||
|
bucketAggs.splice($scope.index, 1);
|
||||||
|
$scope.onChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.init();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
module.directive('elasticBucketAgg', function() {
|
|
||||||
return {
|
|
||||||
templateUrl: 'app/plugins/datasource/elasticsearch/partials/bucketAgg.html',
|
|
||||||
controller: 'ElasticBucketAggCtrl',
|
|
||||||
restrict: 'E',
|
|
||||||
scope: {
|
|
||||||
target: "=",
|
|
||||||
index: "=",
|
|
||||||
onChange: "&",
|
|
||||||
getFields: "&",
|
|
||||||
},
|
|
||||||
link: function postLink($scope, elem) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -20,4 +20,32 @@ function (angular) {
|
|||||||
return {templateUrl: 'app/plugins/datasource/elasticsearch/partials/annotations.editor.html'};
|
return {templateUrl: 'app/plugins/datasource/elasticsearch/partials/annotations.editor.html'};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.directive('elasticMetricAgg', function() {
|
||||||
|
return {
|
||||||
|
templateUrl: 'app/plugins/datasource/elasticsearch/partials/metricAgg.html',
|
||||||
|
controller: 'ElasticMetricAggCtrl',
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
target: "=",
|
||||||
|
index: "=",
|
||||||
|
onChange: "&",
|
||||||
|
getFields: "&",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
module.directive('elasticBucketAgg', function() {
|
||||||
|
return {
|
||||||
|
templateUrl: 'app/plugins/datasource/elasticsearch/partials/bucketAgg.html',
|
||||||
|
controller: 'ElasticBucketAggCtrl',
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
target: "=",
|
||||||
|
index: "=",
|
||||||
|
onChange: "&",
|
||||||
|
getFields: "&",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,74 +1,52 @@
|
|||||||
define([
|
define([
|
||||||
'angular',
|
'angular',
|
||||||
'lodash',
|
'lodash',
|
||||||
'jquery',
|
'./queryDef'
|
||||||
],
|
],
|
||||||
function (angular, _, $) {
|
function (angular, _, queryDef) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var module = angular.module('grafana.directives');
|
var module = angular.module('grafana.directives');
|
||||||
|
|
||||||
module.controller('ElasticMetricAggCtrl', function($scope, uiSegmentSrv, $q) {
|
module.controller('ElasticMetricAggCtrl', function($scope, uiSegmentSrv, $q) {
|
||||||
var metricAggs = $scope.target.metrics;
|
var metricAggs = $scope.target.metrics;
|
||||||
|
|
||||||
$scope.metricAggTypes = [
|
$scope.metricAggTypes = queryDef.metricAggTypes;
|
||||||
{text: "Count", value: 'count' },
|
|
||||||
{text: "Average of", value: 'avg' },
|
|
||||||
{text: "Sum of", value: 'sum' },
|
|
||||||
{text: "Max of", value: 'max' },
|
|
||||||
{text: "Min of", value: 'min' },
|
|
||||||
{text: "Standard Deviations", value: 'std_dev' },
|
|
||||||
];
|
|
||||||
|
|
||||||
$scope.init = function() {
|
$scope.init = function() {
|
||||||
$scope.agg = metricAggs[$scope.index];
|
$scope.agg = metricAggs[$scope.index];
|
||||||
if (!$scope.agg.field) {
|
if (!$scope.agg.field) {
|
||||||
$scope.agg.field = 'select field';
|
$scope.agg.field = 'select field';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$scope.$watchCollection("target.metrics", function() {
|
$scope.$watchCollection("target.metrics", function() {
|
||||||
$scope.isFirst = $scope.index === 0;
|
$scope.isFirst = $scope.index === 0;
|
||||||
$scope.isLast = $scope.index === metricAggs.length - 1;
|
$scope.isLast = $scope.index === metricAggs.length - 1;
|
||||||
$scope.isSingle = metricAggs.length === 1;
|
$scope.isSingle = metricAggs.length === 1;
|
||||||
});
|
|
||||||
|
|
||||||
$scope.toggleOptions = function() {
|
|
||||||
$scope.showOptions = !$scope.showOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.addMetricAgg = function() {
|
|
||||||
var addIndex = metricAggs.length;
|
|
||||||
|
|
||||||
var id = _.reduce($scope.target.bucketAggs.concat($scope.target.metrics), function(max, val) {
|
|
||||||
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
metricAggs.splice(addIndex, 0, {type: "count", field: "select field", id: (id+1).toString()});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.removeMetricAgg = function() {
|
|
||||||
metricAggs.splice($scope.index, 1);
|
|
||||||
$scope.onChange();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.init();
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.directive('elasticMetricAgg', function() {
|
$scope.toggleOptions = function() {
|
||||||
return {
|
$scope.showOptions = !$scope.showOptions;
|
||||||
templateUrl: 'app/plugins/datasource/elasticsearch/partials/metricAgg.html',
|
}
|
||||||
controller: 'ElasticMetricAggCtrl',
|
|
||||||
restrict: 'E',
|
$scope.addMetricAgg = function() {
|
||||||
scope: {
|
var addIndex = metricAggs.length;
|
||||||
target: "=",
|
|
||||||
index: "=",
|
var id = _.reduce($scope.target.bucketAggs.concat($scope.target.metrics), function(max, val) {
|
||||||
onChange: "&",
|
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
||||||
getFields: "&",
|
}, 0);
|
||||||
},
|
|
||||||
link: function postLink($scope, elem) {
|
metricAggs.splice(addIndex, 0, {type: "count", field: "select field", id: (id+1).toString()});
|
||||||
}
|
};
|
||||||
};
|
|
||||||
});
|
$scope.removeMetricAgg = function() {
|
||||||
|
metricAggs.splice($scope.index, 1);
|
||||||
|
$scope.onChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.init();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
<div class="tight-form last">
|
<div class="tight-form last">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item" style="width: 60px">
|
<li class="tight-form-item" style="width: 60px">
|
||||||
By
|
Order By
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<metric-segment-model property="agg.orderBy" options="orderByOptions" on-change="onChangeInternal()" css-class="last"></metric-segment-model>
|
<metric-segment-model property="agg.orderBy" options="orderByOptions" on-change="onChangeInternal()" css-class="last"></metric-segment-model>
|
||||||
|
@ -16,24 +16,7 @@ function (angular, _, ElasticQueryBuilder) {
|
|||||||
|
|
||||||
target.timeField = target.timeField || '@timestamp';
|
target.timeField = target.timeField || '@timestamp';
|
||||||
target.metrics = target.metrics || [{ type: 'count', id: '1' }];
|
target.metrics = target.metrics || [{ type: 'count', id: '1' }];
|
||||||
target.bucketAggs = target.bucketAggs || [];
|
target.bucketAggs = target.bucketAggs || [{ type: 'date_histogram', field: '@timestmap', id: '2'}];
|
||||||
target.bucketAggs = [
|
|
||||||
{
|
|
||||||
type: 'terms',
|
|
||||||
field: '@hostname',
|
|
||||||
id: '2'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'date_histogram',
|
|
||||||
field: '@timestamp',
|
|
||||||
id: '3'
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
$scope.timeSegment = uiSegmentSrv.newSegment(target.timeField);
|
|
||||||
|
|
||||||
$scope.removeSelectSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove select --'});
|
|
||||||
$scope.resetSelectSegment = uiSegmentSrv.newSegment({fake: true, value: '-- reset --'});
|
|
||||||
|
|
||||||
$scope.queryBuilder = new ElasticQueryBuilder(target);
|
$scope.queryBuilder = new ElasticQueryBuilder(target);
|
||||||
$scope.rawQueryOld = angular.toJson($scope.queryBuilder.build($scope.target), true);
|
$scope.rawQueryOld = angular.toJson($scope.queryBuilder.build($scope.target), true);
|
||||||
@ -46,12 +29,13 @@ function (angular, _, ElasticQueryBuilder) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.queryUpdated = function() {
|
$scope.queryUpdated = function() {
|
||||||
console.log('qery updated');
|
|
||||||
var newJson = angular.toJson($scope.queryBuilder.build($scope.target), true);
|
var newJson = angular.toJson($scope.queryBuilder.build($scope.target), true);
|
||||||
if (newJson !== $scope.oldQueryRaw) {
|
if (newJson !== $scope.oldQueryRaw) {
|
||||||
$scope.rawQueryOld = newJson;
|
$scope.rawQueryOld = newJson;
|
||||||
$scope.get_data();
|
$scope.get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.appEvent('elastic-query-updated');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.transformToSegments = function(addTemplateVars) {
|
$scope.transformToSegments = function(addTemplateVars) {
|
||||||
@ -65,7 +49,6 @@ function (angular, _, ElasticQueryBuilder) {
|
|||||||
segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true }));
|
segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true }));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return segments;
|
return segments;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
79
public/app/plugins/datasource/elasticsearch/queryDef.js
Normal file
79
public/app/plugins/datasource/elasticsearch/queryDef.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
define([
|
||||||
|
'lodash'
|
||||||
|
],
|
||||||
|
function (_) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
return {
|
||||||
|
metricAggTypes: [
|
||||||
|
{text: "Count", value: 'count' },
|
||||||
|
{text: "Average of", value: 'avg' },
|
||||||
|
{text: "Sum of", value: 'sum' },
|
||||||
|
{text: "Max of", value: 'max' },
|
||||||
|
{text: "Min of", value: 'min' },
|
||||||
|
{text: "Standard Deviations", value: 'std_dev' },
|
||||||
|
],
|
||||||
|
|
||||||
|
bucketAggTypes: [
|
||||||
|
{text: "Terms", value: 'terms' },
|
||||||
|
{text: "Date Histogram", value: 'date_histogram' },
|
||||||
|
],
|
||||||
|
|
||||||
|
orderByOptions: [
|
||||||
|
{text: "Doc Count", value: '_count' },
|
||||||
|
{text: "Term value", value: '_term' },
|
||||||
|
],
|
||||||
|
|
||||||
|
orderOptions: [
|
||||||
|
{text: "Top", value: 'desc' },
|
||||||
|
{text: "Bottom", value: 'asc' },
|
||||||
|
],
|
||||||
|
|
||||||
|
sizeOptions: [
|
||||||
|
{text: "No limit", value: '0' },
|
||||||
|
{text: "1", value: '1' },
|
||||||
|
{text: "2", value: '2' },
|
||||||
|
{text: "3", value: '4' },
|
||||||
|
{text: "5", value: '5' },
|
||||||
|
{text: "10", value: '10' },
|
||||||
|
{text: "15", value: '15' },
|
||||||
|
{text: "20", value: '20' },
|
||||||
|
],
|
||||||
|
|
||||||
|
getOrderByOptions: function(target) {
|
||||||
|
var self = this;
|
||||||
|
var metricRefs = [];
|
||||||
|
_.each(target.metrics, function(metric) {
|
||||||
|
if (metric.type !== 'count') {
|
||||||
|
metricRefs.push({text: self.describeMetric(metric), value: metric.id});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.orderByOptions.concat(metricRefs);
|
||||||
|
},
|
||||||
|
|
||||||
|
describeOrder: function(order) {
|
||||||
|
var def = _.findWhere(this.orderOptions, {value: order});
|
||||||
|
return def.text;
|
||||||
|
},
|
||||||
|
|
||||||
|
describeMetric: function(metric) {
|
||||||
|
var def = _.findWhere(this.metricAggTypes, {value: metric.type});
|
||||||
|
return def.text + ' ' + metric.field;
|
||||||
|
},
|
||||||
|
|
||||||
|
describeOrderBy: function(orderBy, target) {
|
||||||
|
var def = _.findWhere(this.orderByOptions, {value: orderBy});
|
||||||
|
if (def) {
|
||||||
|
return def.text;
|
||||||
|
}
|
||||||
|
var metric = _.findWhere(target.metrics, {id: orderBy});
|
||||||
|
if (metric) {
|
||||||
|
return this.describeMetric(metric);
|
||||||
|
} else {
|
||||||
|
return "metric not found";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user