Commit b3bda020 by Torkel Ödegaard

feat(elasticsearch): lots of work on elasticsearch metrics processing, handling…

feat(elasticsearch): lots of work on elasticsearch metrics processing, handling grouped responses, etc, #1034
parent df1d56e7
...@@ -172,6 +172,8 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) { ...@@ -172,6 +172,8 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) {
return date.getTime(); return date.getTime();
}; };
// this is quite complex
// neeed to recurise down the nested buckets to build series
ElasticDatasource.prototype._processBuckets = function(buckets, groupByFields, series, level, parentName, parentTime) { ElasticDatasource.prototype._processBuckets = function(buckets, groupByFields, series, level, parentName, parentTime) {
var points = []; var points = [];
var groupBy = groupByFields[level]; var groupBy = groupByFields[level];
...@@ -180,13 +182,14 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) { ...@@ -180,13 +182,14 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) {
var bucket = buckets[i]; var bucket = buckets[i];
if (groupBy) { if (groupBy) {
var seriesName = ""; var seriesName = level > 0 ? bucket.key : '';
var time = parentTime || bucket.key; var time = parentTime || bucket.key;
this._processBuckets(bucket[groupBy.field].buckets, groupByFields, series, level+1, seriesName, time) this._processBuckets(bucket[groupBy.field].buckets, groupByFields, series, level+1, seriesName, time)
} else { } else {
var seriesName = parentName; var seriesName = parentName;
if (level > 0) { if (level > 0) {
if (seriesName) { seriesName += " "; }
seriesName += bucket.key; seriesName += bucket.key;
} else { } else {
parentTime = bucket.key; parentTime = bucket.key;
...@@ -202,12 +205,17 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) { ...@@ -202,12 +205,17 @@ function (angular, _, config, kbn, moment, ElasticQueryBuilder) {
var series = []; var series = [];
for (var i = 0; i < results.responses.length; i++) { for (var i = 0; i < results.responses.length; i++) {
var buckets = results.responses[i].aggregations.histogram.buckets; var response = results.responses[i];
if (response.error) {
throw { message: response.error };
}
var buckets = response.aggregations.histogram.buckets;
var target = targets[i]; var target = targets[i];
var points = []; var points = [];
var querySeries = {} var querySeries = {}
this._processBuckets(buckets, target.groupByFields, querySeries, 0, target.refId); this._processBuckets(buckets, target.groupByFields, querySeries, 0);
_.each(querySeries, function(value) { _.each(querySeries, function(value) {
series.push(value); series.push(value);
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<div class="tight-form" ng-hide="target.rawQuery"> <div class="tight-form" ng-hide="target.rawQuery">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;"> <li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
Group By Group by
</li> </li>
<li ng-repeat="segment in groupBySegments"> <li ng-repeat="segment in groupBySegments">
<metric-segment segment="segment" get-alt-segments="getGroupByFields(segment, $index)" on-value-changed="groupByChanged(segment, $index)"></metric-segment> <metric-segment segment="segment" get-alt-segments="getGroupByFields(segment, $index)" on-value-changed="groupByChanged(segment, $index)"></metric-segment>
......
...@@ -52,23 +52,23 @@ function () { ...@@ -52,23 +52,23 @@ function () {
"max": timeTo "max": timeTo
} }
} }
} },
}; };
var nestedAggs = {}; var nestedAggs = query.aggs.histogram;
if (target.groupByFields && target.groupByFields.length > 0) { for (var i = 0; i < target.groupByFields.length; i++) {
var field = target.groupByFields[0].field; var field = target.groupByFields[i].field;
nestedAggs[field] = { var aggs = {terms: {field: field}};
terms: {
field: field, nestedAggs.aggs = {};
} nestedAggs.aggs[field] = aggs;
} nestedAggs = aggs;
} }
query.aggs.histogram.aggs = nestedAggs; console.log(angular.toJson(query, true));
query = JSON.stringify(query); query = angular.toJson(query);
return query; return query;
}; };
......
...@@ -57,14 +57,7 @@ define([ ...@@ -57,14 +57,7 @@ define([
var result; var result;
beforeEach(function() { beforeEach(function() {
result = ctx.ds._processTimeSeries([ result = ctx.ds._processTimeSeries([{refId: 'A', groupByFields: [{field: 'host' }]}], {
{
refId: 'A',
groupByFields: [
{field: 'host' }
]
}
], {
responses: [{ responses: [{
aggregations: { aggregations: {
histogram: { histogram: {
...@@ -103,6 +96,87 @@ define([ ...@@ -103,6 +96,87 @@ define([
expect(result.data[1].target).to.be('server2'); expect(result.data[1].target).to.be('server2');
}); });
}); });
describe('two group by query', function() {
var result;
beforeEach(function() {
result = ctx.ds._processTimeSeries([{refId: 'A', groupByFields: [{field: 'host'}, {field: 'site'}]}], {
responses: [{
aggregations: {
histogram: {
buckets: [
{
host: {
buckets: [
{
site: {
buckets: [
{doc_count: 3, key: 'backend'},
{doc_count: 1, key: 'frontend'},
],
},
doc_count: 4, key: 'server1'
},
{
site: {
buckets: [
{doc_count: 3, key: 'backend'},
{doc_count: 1, key: 'frontend'},
],
},
doc_count: 6, key: 'server2'
},
]
},
doc_count: 10,
key: 1000
},
{
host: {
buckets: [
{
site: {
buckets: [
{doc_count: 3, key: 'backend'},
{doc_count: 1, key: 'frontend'},
],
},
doc_count: 4,
key: 'server1'
},
{
site: {
buckets: [
{doc_count: 3, key: 'backend'},
{doc_count: 1, key: 'frontend'},
],
},
doc_count: 6,
key: 'server2'
},
]
},
doc_count: 15,
key: 2000
}
]
}
}
}]
})
});
it('should return 2 series', function() {
expect(result.data.length).to.be(4);
expect(result.data[0].datapoints.length).to.be(2);
expect(result.data[0].target).to.be('server1 backend');
expect(result.data[1].target).to.be('server1 frontend');
expect(result.data[2].target).to.be('server2 backend');
expect(result.data[3].target).to.be('server2 frontend');
});
});
}); });
}); });
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment