mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(elasticsearch): work on supporting filters aggregate, #2785
This commit is contained in:
parent
9de016bfe3
commit
e694a74c9d
@ -35,6 +35,20 @@ function (angular, _, queryDef) {
|
|||||||
$scope.agg.settings = {};
|
$scope.agg.settings = {};
|
||||||
$scope.showOptions = false;
|
$scope.showOptions = false;
|
||||||
|
|
||||||
|
switch($scope.agg.type) {
|
||||||
|
case 'date_histogram':
|
||||||
|
case 'terms': {
|
||||||
|
delete $scope.agg.query;
|
||||||
|
$scope.agg.type = 'select field';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'filters': {
|
||||||
|
delete $scope.agg.field;
|
||||||
|
$scope.agg.query = '*';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$scope.validateModel();
|
$scope.validateModel();
|
||||||
$scope.onChange();
|
$scope.onChange();
|
||||||
};
|
};
|
||||||
@ -65,6 +79,9 @@ function (angular, _, queryDef) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'filters': {
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'date_histogram': {
|
case 'date_histogram': {
|
||||||
settings.interval = settings.interval || 'auto';
|
settings.interval = settings.interval || 'auto';
|
||||||
$scope.agg.field = $scope.target.timeField;
|
$scope.agg.field = $scope.target.timeField;
|
||||||
|
@ -10,23 +10,8 @@ function (_, queryDef) {
|
|||||||
this.response = response;
|
this.response = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is quite complex
|
ElasticResponse.prototype.processMetrics = function(esAgg, target, seriesList, props) {
|
||||||
// neeed to recurise down the nested buckets to build series
|
var metric, y, i, newSeries, bucket, value;
|
||||||
ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, level, props) {
|
|
||||||
var value, metric, i, y, bucket, aggDef, esAgg, newSeries;
|
|
||||||
|
|
||||||
aggDef = target.bucketAggs[level];
|
|
||||||
esAgg = aggs[aggDef.id];
|
|
||||||
|
|
||||||
if (level < target.bucketAggs.length - 1) {
|
|
||||||
for (i = 0; i < esAgg.buckets.length; i++) {
|
|
||||||
bucket = esAgg.buckets[i];
|
|
||||||
props = _.clone(props);
|
|
||||||
props[aggDef.field] = bucket.key;
|
|
||||||
this.processBuckets(bucket, target, seriesList, level+1, props);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (y = 0; y < target.metrics.length; y++) {
|
for (y = 0; y < target.metrics.length; y++) {
|
||||||
metric = target.metrics[y];
|
metric = target.metrics[y];
|
||||||
@ -101,6 +86,35 @@ function (_, queryDef) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This is quite complex
|
||||||
|
// neeed to recurise down the nested buckets to build series
|
||||||
|
ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, props) {
|
||||||
|
var bucket, aggDef, esAgg, aggId;
|
||||||
|
|
||||||
|
for (aggId in aggs) {
|
||||||
|
aggDef = _.findWhere(target.bucketAggs, {id: aggId});
|
||||||
|
esAgg = aggs[aggId];
|
||||||
|
if (!aggDef) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aggDef.type === 'date_histogram') {
|
||||||
|
this.processMetrics(esAgg, target, seriesList, props);
|
||||||
|
} else {
|
||||||
|
for (var nameIndex in esAgg.buckets) {
|
||||||
|
bucket = esAgg.buckets[nameIndex];
|
||||||
|
props = _.clone(props);
|
||||||
|
if (bucket.key) {
|
||||||
|
props[aggDef.field] = bucket.key;
|
||||||
|
} else {
|
||||||
|
props["filter"] = nameIndex;
|
||||||
|
}
|
||||||
|
this.processBuckets(bucket, target, seriesList, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ElasticResponse.prototype._getMetricName = function(metric) {
|
ElasticResponse.prototype._getMetricName = function(metric) {
|
||||||
var metricDef = _.findWhere(queryDef.metricAggTypes, {value: metric});
|
var metricDef = _.findWhere(queryDef.metricAggTypes, {value: metric});
|
||||||
if (!metricDef) {
|
if (!metricDef) {
|
||||||
@ -172,7 +186,7 @@ function (_, queryDef) {
|
|||||||
var target = this.targets[i];
|
var target = this.targets[i];
|
||||||
var tmpSeriesList = [];
|
var tmpSeriesList = [];
|
||||||
|
|
||||||
this.processBuckets(aggregations, target, tmpSeriesList, 0, {});
|
this.processBuckets(aggregations, target, tmpSeriesList, {});
|
||||||
this.nameSeries(tmpSeriesList, target);
|
this.nameSeries(tmpSeriesList, target);
|
||||||
|
|
||||||
for (var y = 0; y < tmpSeriesList.length; y++) {
|
for (var y = 0; y < tmpSeriesList.length; y++) {
|
||||||
|
@ -7,9 +7,12 @@
|
|||||||
<li>
|
<li>
|
||||||
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
|
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li ng-if="agg.type !== 'filters'">
|
||||||
<metric-segment-model property="agg.field" get-options="getFields()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
|
<metric-segment-model property="agg.field" get-options="getFields()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
|
||||||
</li>
|
</li>
|
||||||
|
<li ng-if="agg.type === 'filters'">
|
||||||
|
<input type="text" class="tight-form-input tight-form-item-xxlarge" ng-model="agg.query" spellcheck='false' placeholder="Lucence query" ng-blur="onChange()">
|
||||||
|
</li>
|
||||||
<li class="tight-form-item last" ng-if="settingsLinkText">
|
<li class="tight-form-item last" ng-if="settingsLinkText">
|
||||||
<a ng-click="toggleOptions()">{{settingsLinkText}}</a>
|
<a ng-click="toggleOptions()">{{settingsLinkText}}</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -54,12 +54,34 @@ function (angular) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ElasticQueryBuilder.prototype.getFiltersAgg = function(target) {
|
||||||
|
var filterObj = {};
|
||||||
|
|
||||||
|
for (var i = 0; i < target.bucketAggs.length; i++) {
|
||||||
|
var aggDef = target.bucketAggs[i];
|
||||||
|
if (aggDef.type !== 'filters') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterObj[aggDef.query] = {
|
||||||
|
query: {
|
||||||
|
query_string: {
|
||||||
|
query: aggDef.query,
|
||||||
|
analyze_wildcard: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterObj;
|
||||||
|
};
|
||||||
|
|
||||||
ElasticQueryBuilder.prototype.build = function(target) {
|
ElasticQueryBuilder.prototype.build = function(target) {
|
||||||
if (target.rawQuery) {
|
if (target.rawQuery) {
|
||||||
return angular.fromJson(target.rawQuery);
|
return angular.fromJson(target.rawQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
var i, nestedAggs, metric;
|
var i, nestedAggs, metric, filtersHandled;
|
||||||
var query = {
|
var query = {
|
||||||
"size": 0,
|
"size": 0,
|
||||||
"query": {
|
"query": {
|
||||||
@ -95,6 +117,15 @@ function (angular) {
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'filters': {
|
||||||
|
// skip filters if we already processed them
|
||||||
|
if (filtersHandled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
esAgg["filters"] = {filters: this.getFiltersAgg(target)};
|
||||||
|
filtersHandled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'terms': {
|
case 'terms': {
|
||||||
this.buildTermsAgg(aggDef, esAgg, target);
|
this.buildTermsAgg(aggDef, esAgg, target);
|
||||||
break;
|
break;
|
||||||
|
@ -18,6 +18,7 @@ function (_) {
|
|||||||
|
|
||||||
bucketAggTypes: [
|
bucketAggTypes: [
|
||||||
{text: "Terms", value: 'terms' },
|
{text: "Terms", value: 'terms' },
|
||||||
|
{text: "Filters", value: 'filters' },
|
||||||
{text: "Date Histogram", value: 'date_histogram' },
|
{text: "Date Histogram", value: 'date_histogram' },
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -214,6 +214,10 @@ select.tight-form-input {
|
|||||||
.tight-form-item-xlarge { width: 150px; }
|
.tight-form-item-xlarge { width: 150px; }
|
||||||
.tight-form-item-xxlarge { width: 200px; }
|
.tight-form-item-xxlarge { width: 200px; }
|
||||||
|
|
||||||
|
.tight-form-input.tight-form-item-xxlarge {
|
||||||
|
width: 215px;
|
||||||
|
}
|
||||||
|
|
||||||
.tight-form-inner-box {
|
.tight-form-inner-box {
|
||||||
margin: 20px 0 20px 148px;
|
margin: 20px 0 20px 148px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -95,6 +95,22 @@ define([
|
|||||||
expect(firstLevel.aggs["1"].percentiles.percents).to.eql([1,2,3,4]);
|
expect(firstLevel.aggs["1"].percentiles.percents).to.eql([1,2,3,4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('with filters aggs', function() {
|
||||||
|
var query = builder.build({
|
||||||
|
metrics: [{type: 'count', id: '1'}],
|
||||||
|
timeField: '@timestamp',
|
||||||
|
bucketAggs: [
|
||||||
|
{type: 'filters', query: '@metric:cpu', id: '2'},
|
||||||
|
{type: 'filters', query: '@metric:logins.count', id: '3' },
|
||||||
|
{type: 'date_histogram', field: '@timestamp', id: '4'}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(query.aggs["2"].filters.filters["@metric:cpu"].query.query_string.query).to.be("@metric:cpu");
|
||||||
|
expect(query.aggs["2"].filters.filters["@metric:logins.count"].query.query_string.query).to.be("@metric:logins.count");
|
||||||
|
expect(query.aggs["2"].aggs["4"].date_histogram.field).to.be("@timestamp");
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -351,5 +351,56 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('with two filters agg', function() {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
targets = [{
|
||||||
|
refId: 'A',
|
||||||
|
metrics: [{type: 'count', id: '1'}],
|
||||||
|
bucketAggs: [
|
||||||
|
{type: 'filters', query: '@metric:cpu', id: '2'},
|
||||||
|
{type: 'filters', query: '@metric:logins.count', id: '5'},
|
||||||
|
{type: 'date_histogram', field: '@timestamp', id: '3'}
|
||||||
|
],
|
||||||
|
}];
|
||||||
|
response = {
|
||||||
|
responses: [{
|
||||||
|
aggregations: {
|
||||||
|
"2": {
|
||||||
|
buckets: {
|
||||||
|
"@metric:cpu": {
|
||||||
|
"3": {
|
||||||
|
buckets: [
|
||||||
|
{doc_count: 1, key: 1000},
|
||||||
|
{doc_count: 3, key: 2000}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"@metric:logins.count": {
|
||||||
|
"3": {
|
||||||
|
buckets: [
|
||||||
|
{doc_count: 2, key: 1000},
|
||||||
|
{doc_count: 8, key: 2000}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
result = new ElasticResponse(targets, response).getTimeSeries();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return 2 series', function() {
|
||||||
|
expect(result.data.length).to.be(2);
|
||||||
|
expect(result.data[0].datapoints.length).to.be(2);
|
||||||
|
expect(result.data[0].target).to.be('@metric:cpu');
|
||||||
|
expect(result.data[1].target).to.be('@metric:logins.count');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user