Commit ede827f5 by Torkel Ödegaard

feat: Elasticsearch change to how queries without date histogram are transformed…

feat: Elasticsearch change to how queries without date histogram are transformed into Grafana data stucture, now it is processed into a table structure instead of json structure
parent 6224a25e
......@@ -3,9 +3,11 @@ export default class TableModel {
columns: any[];
rows: any[];
type: string;
columnMap: any;
constructor() {
this.columns = [];
this.columnMap = {};
this.rows = [];
this.type = 'table';
}
......@@ -36,4 +38,11 @@ export default class TableModel {
this.columns[options.col].desc = false;
}
}
addColumn(col) {
if (!this.columnMap[col.text]) {
this.columns.push(col);
this.columnMap[col.text] = col;
}
}
}
......@@ -2,6 +2,7 @@
import _ from 'lodash';
import queryDef from "./query_def";
import TableModel from 'app/core/table_model';
export function ElasticResponse(targets, response) {
this.targets = targets;
......@@ -95,21 +96,35 @@ ElasticResponse.prototype.processMetrics = function(esAgg, target, seriesList, p
}
};
ElasticResponse.prototype.processAggregationDocs = function(esAgg, aggDef, target, docs, props) {
var metric, y, i, bucket, metricName, doc;
ElasticResponse.prototype.processAggregationDocs = function(esAgg, aggDef, target, table, props) {
// add columns
if (table.columns.length === 0) {
for (let propKey of _.keys(props)) {
table.addColumn({text: propKey});
}
table.addColumn({text: aggDef.field});
}
// helper func to add values to value array
let addMetricValue = (values, metricName, value) => {
table.addColumn({text: metricName});
values.push(value);
};
for (i = 0; i < esAgg.buckets.length; i++) {
bucket = esAgg.buckets[i];
doc = _.defaults({}, props);
doc[aggDef.field] = bucket.key;
for (let bucket of esAgg.buckets) {
let values = [];
for (let propValues of _.values(props)) {
values.push(propValues);
}
for (y = 0; y < target.metrics.length; y++) {
metric = target.metrics[y];
// add bucket key (value)
values.push(bucket.key);
for (let metric of target.metrics) {
switch (metric.type) {
case "count": {
metricName = this._getMetricName(metric.type);
doc[metricName] = bucket.doc_count;
addMetricValue(values, this._getMetricName(metric.type), bucket.doc_count);
break;
}
case 'extended_stats': {
......@@ -123,33 +138,32 @@ ElasticResponse.prototype.processAggregationDocs = function(esAgg, aggDef, targe
stats.std_deviation_bounds_upper = stats.std_deviation_bounds.upper;
stats.std_deviation_bounds_lower = stats.std_deviation_bounds.lower;
metricName = this._getMetricName(statName);
doc[metricName] = stats[statName];
addMetricValue(values, this._getMetricName(statName), stats[statName]);
}
break;
}
default: {
metricName = this._getMetricName(metric.type);
var otherMetrics = _.filter(target.metrics, {type: metric.type});
let metricName = this._getMetricName(metric.type);
let otherMetrics = _.filter(target.metrics, {type: metric.type});
// if more of the same metric type include field field name in property
if (otherMetrics.length > 1) {
metricName += ' ' + metric.field;
}
doc[metricName] = bucket[metric.id].value;
addMetricValue(values, metricName, bucket[metric.id].value);
break;
}
}
}
docs.push(doc);
table.rows.push(values);
}
};
// This is quite complex
// neeed to recurise down the nested buckets to build series
ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, docs, props, depth) {
ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, table, props, depth) {
var bucket, aggDef, esAgg, aggId;
var maxDepth = target.bucketAggs.length-1;
......@@ -165,7 +179,7 @@ ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, do
if (aggDef.type === 'date_histogram') {
this.processMetrics(esAgg, target, seriesList, props);
} else {
this.processAggregationDocs(esAgg, aggDef, target, docs, props);
this.processAggregationDocs(esAgg, aggDef, target, table, props);
}
} else {
for (var nameIndex in esAgg.buckets) {
......@@ -179,7 +193,7 @@ ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, do
if (bucket.key_as_string) {
props[aggDef.field] = bucket.key_as_string;
}
this.processBuckets(bucket, target, seriesList, docs, props, depth+1);
this.processBuckets(bucket, target, seriesList, table, props, depth+1);
}
}
}
......@@ -325,9 +339,9 @@ ElasticResponse.prototype.getTimeSeries = function() {
var aggregations = response.aggregations;
var target = this.targets[i];
var tmpSeriesList = [];
var docs = [];
var table = new TableModel();
this.processBuckets(aggregations, target, tmpSeriesList, docs, {}, 0);
this.processBuckets(aggregations, target, tmpSeriesList, table, {}, 0);
this.trimDatapoints(tmpSeriesList, target);
this.nameSeries(tmpSeriesList, target);
......@@ -335,8 +349,8 @@ ElasticResponse.prototype.getTimeSeries = function() {
seriesList.push(tmpSeriesList[y]);
}
if (seriesList.length === 0 && docs.length > 0) {
seriesList.push({target: 'docs', type: 'docs', datapoints: docs});
if (table.rows.length > 0) {
seriesList.push(table);
}
}
}
......
......@@ -387,10 +387,9 @@ describe('ElasticResponse', function() {
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);
it('should return table with byte and count', function() {
expect(result.data[0].rows.length).to.be(3);
expect(result.data[0].columns).to.eql([{text: 'bytes'}, {text: 'Count'}]);
});
});
......@@ -530,14 +529,14 @@ describe('ElasticResponse', function() {
it('should return table', function() {
expect(result.data.length).to.be(1);
expect(result.data[0].type).to.be('docs');
expect(result.data[0].datapoints.length).to.be(2);
expect(result.data[0].datapoints[0].host).to.be("server-1");
expect(result.data[0].datapoints[0].Average).to.be(1000);
expect(result.data[0].datapoints[0].Count).to.be(369);
expect(result.data[0].datapoints[1].host).to.be("server-2");
expect(result.data[0].datapoints[1].Average).to.be(2000);
expect(result.data[0].type).to.be('table');
expect(result.data[0].rows.length).to.be(2);
expect(result.data[0].rows[0][0]).to.be("server-1");
expect(result.data[0].rows[0][1]).to.be(1000);
expect(result.data[0].rows[0][2]).to.be(369);
expect(result.data[0].rows[1][0]).to.be("server-2");
expect(result.data[0].rows[1][1]).to.be(2000);
});
});
......@@ -573,10 +572,9 @@ describe('ElasticResponse', function() {
});
it('should include field in metric name', function() {
expect(result.data[0].type).to.be('docs');
expect(result.data[0].datapoints[0].Average).to.be(undefined);
expect(result.data[0].datapoints[0]['Average test']).to.be(1000);
expect(result.data[0].datapoints[0]['Average test2']).to.be(3000);
expect(result.data[0].type).to.be('table');
expect(result.data[0].rows[0][1]).to.be(1000);
expect(result.data[0].rows[0][2]).to.be(3000);
});
});
......
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