diff --git a/public/app/panels/table/controller.ts b/public/app/panels/table/controller.ts
index e2166f82577..4547a9d7896 100644
--- a/public/app/panels/table/controller.ts
+++ b/public/app/panels/table/controller.ts
@@ -27,7 +27,7 @@ export class TablePanelCtrl {
var panelDefaults = {
targets: [{}],
transform: 'timeseries_to_rows',
- pageSize: 50,
+ pageSize: null,
showHeader: true,
styles: [
{
diff --git a/public/app/panels/table/editor.html b/public/app/panels/table/editor.html
index a862a2b7776..27bf9002d56 100644
--- a/public/app/panels/table/editor.html
+++ b/public/app/panels/table/editor.html
@@ -44,7 +44,7 @@
Pagination (Page size)
-
diff --git a/public/app/panels/table/editor.ts b/public/app/panels/table/editor.ts
index 228b41ccd57..2908023d330 100644
--- a/public/app/panels/table/editor.ts
+++ b/public/app/panels/table/editor.ts
@@ -38,7 +38,7 @@ export function tablePanelEditor() {
scope.updateColumnsMenu = function(data) {
scope.columnsMenu = transformers[scope.panel.transform].getColumns(data);
- scope.showColumnOptions = scope.columnsMenu.length > 0;
+ scope.showColumnOptions = true;
};
scope.$on('render', function(event, table, rawData) {
@@ -51,6 +51,7 @@ export function tablePanelEditor() {
};
scope.transformChanged = function() {
+ scope.panel.columns = [];
scope.updateColumnsMenu();
scope.render();
};
diff --git a/public/app/panels/table/module.ts b/public/app/panels/table/module.ts
index f09a7389a59..dbdc4d0ba25 100644
--- a/public/app/panels/table/module.ts
+++ b/public/app/panels/table/module.ts
@@ -45,7 +45,8 @@ export function tablePanel() {
function appendPaginationControls(footerElem) {
footerElem.empty();
- var pageCount = Math.ceil(data.rows.length / panel.pageSize);
+ var pageSize = panel.pageSize || 100;
+ var pageCount = Math.ceil(data.rows.length / pageSize);
if (pageCount === 1) {
return;
}
@@ -55,18 +56,12 @@ export function tablePanel() {
var paginationList = $('');
- // var prevLink = $(' « ');
- // paginationList.append(prevLink);
-
for (var i = startPage; i < endPage; i++) {
var activeClass = i === scope.pageIndex ? 'active' : '';
var pageLinkElem = $('' + (i+1) + ' ');
paginationList.append(pageLinkElem);
}
- // var nextLink = $('» ');
- // paginationList.append(nextLink);
-
footerElem.append(paginationList);
}
diff --git a/public/app/panels/table/renderer.ts b/public/app/panels/table/renderer.ts
index 3ecb6d68643..a55a8bf2fac 100644
--- a/public/app/panels/table/renderer.ts
+++ b/public/app/panels/table/renderer.ts
@@ -119,8 +119,9 @@ export class TableRenderer {
}
render(page) {
- let startPos = page * this.panel.pageSize;
- let endPos = Math.min(startPos + this.panel.pageSize, this.table.rows.length);
+ let pageSize = this.panel.pageSize || 100;
+ let startPos = page * pageSize;
+ let endPos = Math.min(startPos + pageSize, this.table.rows.length);
var html = "";
for (var y = startPos; y < endPos; y++) {
diff --git a/public/app/panels/table/transformers.ts b/public/app/panels/table/transformers.ts
index 48559f943bd..1a5482693e7 100644
--- a/public/app/panels/table/transformers.ts
+++ b/public/app/panels/table/transformers.ts
@@ -145,7 +145,7 @@ transformers['json'] = {
var names: any = {};
for (var i = 0; i < data.length; i++) {
var series = data[i];
- if (series.type === 'docs') {
+ if (series.type !== 'docs') {
continue;
}
diff --git a/public/app/plugins/datasource/elasticsearch/elastic_response.js b/public/app/plugins/datasource/elasticsearch/elastic_response.js
index 7eb4378831d..73050ce7f2b 100644
--- a/public/app/plugins/datasource/elasticsearch/elastic_response.js
+++ b/public/app/plugins/datasource/elasticsearch/elastic_response.js
@@ -86,20 +86,71 @@ function (_, queryDef) {
}
};
+ ElasticResponse.prototype.processAggregationDocs = function(esAgg, aggDef, target, docs, props) {
+ var metric, y, i, bucket, metricName, doc;
+
+ for (i = 0; i < esAgg.buckets.length; i++) {
+ bucket = esAgg.buckets[i];
+ doc = _.defaults({}, props);
+ doc[aggDef.field] = bucket.key;
+
+ for (y = 0; y < target.metrics.length; y++) {
+ metric = target.metrics[y];
+
+ switch(metric.type) {
+ case "count": {
+ metricName = this._getMetricName(metric.type);
+ doc[metricName] = bucket.doc_count;
+ break;
+ }
+ case 'extended_stats': {
+ for (var statName in metric.meta) {
+ if (!metric.meta[statName]) {
+ continue;
+ }
+
+ var stats = bucket[metric.id];
+ // add stats that are in nested obj to top level obj
+ 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];
+ }
+ break;
+ }
+ default: {
+ metricName = this._getMetricName(metric.type);
+ doc[metricName] =bucket[metric.id].value;
+ break;
+ }
+ }
+ }
+
+ docs.push(doc);
+ }
+ };
+
// This is quite complex
// neeed to recurise down the nested buckets to build series
- ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, props) {
+ ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, docs, props, depth) {
var bucket, aggDef, esAgg, aggId;
+ var maxDepth = target.bucketAggs.length-1;
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);
+ if (depth === maxDepth) {
+ if (aggDef.type === 'date_histogram') {
+ this.processMetrics(esAgg, target, seriesList, props);
+ } else {
+ this.processAggregationDocs(esAgg, aggDef, target, docs, props);
+ }
} else {
for (var nameIndex in esAgg.buckets) {
bucket = esAgg.buckets[nameIndex];
@@ -109,7 +160,7 @@ function (_, queryDef) {
} else {
props["filter"] = nameIndex;
}
- this.processBuckets(bucket, target, seriesList, props);
+ this.processBuckets(bucket, target, seriesList, docs, props, depth+1);
}
}
}
@@ -217,13 +268,18 @@ function (_, queryDef) {
var aggregations = response.aggregations;
var target = this.targets[i];
var tmpSeriesList = [];
+ var docs = [];
- this.processBuckets(aggregations, target, tmpSeriesList, {});
+ this.processBuckets(aggregations, target, tmpSeriesList, docs, {}, 0);
this.nameSeries(tmpSeriesList, target);
for (var y = 0; y < tmpSeriesList.length; y++) {
seriesList.push(tmpSeriesList[y]);
}
+
+ if (seriesList.length === 0 && docs.length > 0) {
+ seriesList.push({target: 'docs', type: 'docs', datapoints: docs});
+ }
}
}
diff --git a/public/app/plugins/datasource/elasticsearch/specs/elastic_response_specs.ts b/public/app/plugins/datasource/elasticsearch/specs/elastic_response_specs.ts
index 5ae67f92d78..4e80833c55b 100644
--- a/public/app/plugins/datasource/elasticsearch/specs/elastic_response_specs.ts
+++ b/public/app/plugins/datasource/elasticsearch/specs/elastic_response_specs.ts
@@ -411,6 +411,51 @@ describe('ElasticResponse', function() {
});
});
+ describe('No group by time', function() {
+ beforeEach(function() {
+ targets = [{
+ refId: 'A',
+ metrics: [{type: 'avg', id: '1'}, {type: 'count' }],
+ bucketAggs: [{id: '2', type: 'terms', field: 'host'}],
+ }];
+
+ response = {
+ responses: [{
+ aggregations: {
+ "2": {
+ buckets: [
+ {
+ "1": { value: 1000},
+ key: "server-1",
+ doc_count: 369,
+ },
+ {
+ "1": { value: 2000},
+ key: "server-2",
+ doc_count: 200,
+ },
+ ]
+ }
+ }
+ }]
+ };
+
+ result = new ElasticResponse(targets, response).getTimeSeries();
+ });
+
+ it.only('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);
+ });
+ });
+
describe('Raw documents query', function() {
beforeEach(function() {
targets = [{ refId: 'A', metrics: [{type: 'raw_document', id: '1'}], bucketAggs: [] }];