Commit 085c4c56 by Torkel Ödegaard

elasticearch: added support for histogram aggregations, closes #3164

parent 319b8d8f
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* **InfluxDB**: Small fix for the "glow" when focus the field for LIMIT and SLIMIT [#7799](https://github.com/grafana/grafana/pull/7799) thx [@thuck](https://github.com/thuck) * **InfluxDB**: Small fix for the "glow" when focus the field for LIMIT and SLIMIT [#7799](https://github.com/grafana/grafana/pull/7799) thx [@thuck](https://github.com/thuck)
* **Panels**: Delay loading & Lazy load panels as they become visible (scrolled into view) [#5216](https://github.com/grafana/grafana/issues/5216) thx [@jifwin](https://github.com/jifwin) * **Panels**: Delay loading & Lazy load panels as they become visible (scrolled into view) [#5216](https://github.com/grafana/grafana/issues/5216) thx [@jifwin](https://github.com/jifwin)
* **Graph**: Support auto grid min/max when using log scale [#3090](https://github.com/grafana/grafana/issues/3090), thx [@bigbenhur](https://github.com/bigbenhur) * **Graph**: Support auto grid min/max when using log scale [#3090](https://github.com/grafana/grafana/issues/3090), thx [@bigbenhur](https://github.com/bigbenhur)
* **Elasticsearch**: Support histogram aggregations [#3164](https://github.com/grafana/grafana/issues/3164)
## Minor Enchancements ## Minor Enchancements
......
...@@ -50,6 +50,7 @@ function (angular, _, queryDef) { ...@@ -50,6 +50,7 @@ function (angular, _, queryDef) {
switch($scope.agg.type) { switch($scope.agg.type) {
case 'date_histogram': case 'date_histogram':
case 'histogram':
case 'terms': { case 'terms': {
delete $scope.agg.query; delete $scope.agg.query;
$scope.agg.field = 'select field'; $scope.agg.field = 'select field';
...@@ -132,6 +133,16 @@ function (angular, _, queryDef) { ...@@ -132,6 +133,16 @@ function (angular, _, queryDef) {
} }
break; break;
} }
case 'histogram': {
settings.interval = settings.interval || 1000;
settings.min_doc_count = _.defaultTo(settings.min_doc_count, 1);
settingsLinkText = 'Interval: ' + settings.interval;
if (settings.min_doc_count > 0) {
settingsLinkText += ', Min Doc Count: ' + settings.min_doc_count;
}
break;
}
case 'geohash_grid': { case 'geohash_grid': {
// limit precision to 7 // limit precision to 7
settings.precision = Math.max(Math.min(settings.precision, 7), 1); settings.precision = Math.max(Math.min(settings.precision, 7), 1);
......
...@@ -52,6 +52,17 @@ ...@@ -52,6 +52,17 @@
</div> </div>
</div> </div>
<div ng-if="agg.type === 'histogram'">
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Interval</label>
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.interval" ng-blur="onChangeInternal()">
</div>
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Min Doc Count</label>
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.min_doc_count" ng-blur="onChangeInternal()">
</div>
</div>
<div ng-if="agg.type === 'terms'"> <div ng-if="agg.type === 'terms'">
<div class="gf-form offset-width-7"> <div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Order</label> <label class="gf-form-label width-10">Order</label>
......
...@@ -79,6 +79,19 @@ function (queryDef) { ...@@ -79,6 +79,19 @@ function (queryDef) {
return esAgg; return esAgg;
}; };
ElasticQueryBuilder.prototype.getHistogramAgg = function(aggDef) {
var esAgg = {};
var settings = aggDef.settings || {};
esAgg.interval = settings.interval;
esAgg.field = aggDef.field;
esAgg.min_doc_count = settings.min_doc_count || 0;
if (settings.missing) {
esAgg.missing = settings.missing;
}
return esAgg;
};
ElasticQueryBuilder.prototype.getFiltersAgg = function(aggDef) { ElasticQueryBuilder.prototype.getFiltersAgg = function(aggDef) {
var filterObj = {}; var filterObj = {};
for (var i = 0; i < aggDef.settings.filters.length; i++) { for (var i = 0; i < aggDef.settings.filters.length; i++) {
...@@ -192,6 +205,10 @@ function (queryDef) { ...@@ -192,6 +205,10 @@ function (queryDef) {
esAgg["date_histogram"] = this.getDateHistogramAgg(aggDef); esAgg["date_histogram"] = this.getDateHistogramAgg(aggDef);
break; break;
} }
case 'histogram': {
esAgg["histogram"] = this.getHistogramAgg(aggDef);
break;
}
case 'filters': { case 'filters': {
esAgg["filters"] = {filters: this.getFiltersAgg(aggDef)}; esAgg["filters"] = {filters: this.getFiltersAgg(aggDef)};
break; break;
......
...@@ -24,6 +24,7 @@ function (_) { ...@@ -24,6 +24,7 @@ function (_) {
{text: "Filters", value: 'filters' }, {text: "Filters", value: 'filters' },
{text: "Geo Hash Grid", value: 'geohash_grid', requiresField: true}, {text: "Geo Hash Grid", value: 'geohash_grid', requiresField: true},
{text: "Date Histogram", value: 'date_histogram', requiresField: true}, {text: "Date Histogram", value: 'date_histogram', requiresField: true},
{text: "Histogram", value: 'histogram', requiresField: true},
], ],
orderByOptions: [ orderByOptions: [
......
...@@ -361,6 +361,39 @@ describe('ElasticResponse', function() { ...@@ -361,6 +361,39 @@ describe('ElasticResponse', function() {
}); });
}); });
describe('histogram response', function() {
var result;
beforeEach(function() {
targets = [{
refId: 'A',
metrics: [{type: 'count', id: '1'}],
bucketAggs: [{type: 'histogram', field: 'bytes', id: '3'}],
}];
response = {
responses: [{
aggregations: {
"3": {
buckets: [
{doc_count: 1, key: 1000},
{doc_count: 3, key: 2000},
{doc_count: 2, key: 1000},
]
}
}
}]
};
result = new ElasticResponse(targets, response).getTimeSeries();
});
it('should return docs with byte and count', function() {
expect(result.data[0].datapoints.length).to.be(3);
expect(result.data[0].datapoints[0].Count).to.be(1);
expect(result.data[0].datapoints[0].bytes).to.be(1000);
});
});
describe('with two filters agg', function() { describe('with two filters agg', function() {
var result; var result;
......
...@@ -249,6 +249,23 @@ describe('ElasticQueryBuilder', function() { ...@@ -249,6 +249,23 @@ describe('ElasticQueryBuilder', function() {
expect(firstLevel.aggs["2"].derivative.buckets_path).to.be("3"); expect(firstLevel.aggs["2"].derivative.buckets_path).to.be("3");
}); });
it('with histogram', function() {
var query = builder.build({
metrics: [
{id: '1', type: 'count' },
],
bucketAggs: [
{type: 'histogram', field: 'bytes', id: '3', settings: {interval: 10, min_doc_count: 2, missing: 5}}
],
});
var firstLevel = query.aggs["3"];
expect(firstLevel.histogram.field).to.be('bytes');
expect(firstLevel.histogram.interval).to.be(10);
expect(firstLevel.histogram.min_doc_count).to.be(2);
expect(firstLevel.histogram.missing).to.be(5);
});
it('with adhoc filters', function() { it('with adhoc filters', function() {
var query = builder.build({ var query = builder.build({
metrics: [{type: 'Count', id: '0'}], metrics: [{type: 'Count', id: '0'}],
......
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