Browse Source

Refactoring and rewrite parts of influxdb group by feature from PR #441

Torkel Ödegaard 11 years ago
parent
commit
da451d013a
3 changed files with 83 additions and 28 deletions
  1. 1 0
      CHANGELOG.md
  2. 22 6
      src/app/partials/influxdb/editor.html
  3. 60 22
      src/app/services/influxdb/influxdbDatasource.js

+ 1 - 0
CHANGELOG.md

@@ -16,6 +16,7 @@
 - Row editing and adding new panel is now a lot quicker and easier with the new row menu (Issue #475)
 - New datasource! Initial support for OpenTSDB (PR #211) - thx @mpage
 - Improvement and polish to the OpenTSDB query editor (Issue #492)
+- Influxdb group by support (Issue #441) thx @piis3
 
 
 #### Changes

+ 22 - 6
src/app/partials/influxdb/editor.html

@@ -75,16 +75,13 @@
 
           <li>
             <a class="grafana-target-segment"
-               ng-click="target.condiction_filter = !target.condiction_filter; get_data();"
+               ng-click="target.condition_filter = !target.condition_filter; get_data();"
+               bs-tooltip="'Add a where clause'"
                role="menuitem">
               <i class="icon-filter"></i>
             </a>
           </li>
-          <li ng-show="target.condiction_filter">
-            <select class="input-small grafana-target-segment-input"
-                    ng-change="get_data()"
-                    ng-model="target.condition_add"
-                    ng-options="f for f in ['and', 'or']" ></select>
+          <li ng-show="target.condition_filter">
             <input type="text"
                    class="input-small grafana-target-segment-input"
                    ng-model="target.condition_key"
@@ -118,6 +115,25 @@
                    spellcheck='false'
                    ng-model-onblur ng-change="get_data()" >
           </li>
+          <li>
+            <a class="grafana-target-segment"
+               ng-click="target.groupby_field_add = !target.groupby_field_add; get_data();"
+               bs-tooltip="'Add a group by column'"
+               role="menuitem">
+              <i class="icon-plus"></i>
+            </a>
+          </li>
+
+          <li ng-show="target.groupby_field_add">
+            <input type="text"
+                   class="input-small grafana-target-segment-input"
+                   ng-model="target.groupby_field"
+                   placeholder="column"
+                   spellcheck="false"
+                   bs-typeahead="listColumns"
+                   data-min-length=0
+                   ng-blur="get_data()">
+          </li>
 
           <li class="grafana-target-segment">
             as

+ 60 - 22
src/app/services/influxdb/influxdbDatasource.js

@@ -17,7 +17,6 @@ function (angular, _, kbn) {
       this.username = datasource.username;
       this.password = datasource.password;
       this.name = datasource.name;
-
       this.templateSettings = {
         interpolate : /\[\[([\s\S]+?)\]\]/g,
       };
@@ -33,6 +32,7 @@ function (angular, _, kbn) {
         }
 
         var timeFilter = getTimeFilter(options);
+        var groupByField;
 
         if (target.rawQuery) {
           query = target.query;
@@ -43,6 +43,10 @@ function (angular, _, kbn) {
           var groupByIndex = lowerCaseQueryElements.indexOf("group");
           var orderIndex = lowerCaseQueryElements.indexOf("order");
 
+          if (lowerCaseQueryElements[1].indexOf(',')) {
+            groupByField = lowerCaseQueryElements[1].replace(',', '');
+          }
+
           if (whereIndex !== -1) {
             queryElements.splice(whereIndex + 1, 0, timeFilter, "and");
           }
@@ -63,9 +67,10 @@ function (angular, _, kbn) {
           query = filterSrv.applyTemplateToTarget(query);
         }
         else {
-          var template = "select [[func]](\"[[column]]\") as \"[[column]]_[[func]]\" from \"[[series]]\" " +
+
+          var template = "select [[group]][[group_comma]] [[func]](\"[[column]]\") as \"[[column]]_[[func]]\" from \"[[series]]\" " +
                          "where  [[timeFilter]] [[condition_add]] [[condition_key]] [[condition_op]] [[condition_value]] " +
-                         "group by time([[interval]]) order asc";
+                         "group by time([[interval]])[[group_comma]] [[group]] order asc";
 
           var templateData = {
             series: target.series,
@@ -73,10 +78,12 @@ function (angular, _, kbn) {
             func: target.function,
             timeFilter: timeFilter,
             interval: target.interval || options.interval,
-            condition_add: target.condiction_filter ? target.condition_add : '',
-            condition_key: target.condiction_filter ? target.condition_key : '',
-            condition_op: target.condiction_filter ? target.condition_op : '',
-            condition_value: target.condiction_filter ? target.condition_value: ''
+            condition_add: target.condition_filter ? 'and' : '',
+            condition_key: target.condition_filter ? target.condition_key : '',
+            condition_op: target.condition_filter ? target.condition_op : '',
+            condition_value: target.condition_filter ? target.condition_value : '',
+            group_comma: target.groupby_field_add && target.groupby_field ? ',' : '',
+            group: target.groupby_field_add ? target.groupby_field : '',
           };
 
           query = _.template(template, templateData, this.templateSettings);
@@ -86,11 +93,14 @@ function (angular, _, kbn) {
             alias = filterSrv.applyTemplateToTarget(target.alias);
           }
 
+          if (target.groupby_field_add) {
+            groupByField = target.groupby_field;
+          }
+
           target.query = query;
         }
 
-        var handleResponse = _.partial(handleInfluxQueryResponse, alias);
-
+        var handleResponse = _.partial(handleInfluxQueryResponse, alias, groupByField);
         return this.doInfluxRequest(query, alias).then(handleResponse);
 
       }, this);
@@ -141,12 +151,14 @@ function (angular, _, kbn) {
 
     function retry(deferred, callback, delay) {
       return callback().then(undefined, function(reason) {
-        if (reason.status !== 0) {
+        if (reason.status !== 0 || reason.status >= 300) {
           deferred.reject(reason);
         }
-        setTimeout(function() {
-          return retry(deferred, callback, Math.min(delay * 2, 30000));
-        }, delay);
+        else {
+          setTimeout(function() {
+            return retry(deferred, callback, Math.min(delay * 2, 30000));
+          }, delay);
+        }
       });
     }
 
@@ -179,28 +191,54 @@ function (angular, _, kbn) {
       return deferred.promise;
     };
 
-    function handleInfluxQueryResponse(alias, data) {
+    function handleInfluxQueryResponse(alias, groupByField, data) {
       var output = [];
 
       _.each(data, function(series) {
+        var seriesName;
         var timeCol = series.columns.indexOf('time');
+        var valueCol = 1;
+        var groupByCol = -1;
+
+        if (groupByField) {
+          groupByCol = series.columns.indexOf(groupByField);
+        }
 
+        // find value column
         _.each(series.columns, function(column, index) {
-          if (column === "time" || column === "sequence_number") {
-            return;
+          if (column !== 'time' && column !== 'sequence_number' && column !== groupByField) {
+            valueCol = index;
           }
+        });
+
+        var groups = {};
+
+        if (groupByField) {
+          groups = _.groupBy(series.points, function (point) {
+            return point[groupByCol];
+          });
+        }
+        else {
+          groups[series.columns[valueCol]] = series.points;
+        }
 
-          var target = alias || series.name + "." + column;
+        _.each(groups, function(groupPoints, key) {
           var datapoints = [];
-          var value;
+          for (var i = 0; i < groupPoints.length; i++) {
+            var metricValue = isNaN(groupPoints[i][valueCol]) ? null : groupPoints[i][valueCol];
+            datapoints[i] = [metricValue, groupPoints[i][timeCol]];
+          }
 
-          for (var i = 0; i < series.points.length; i++) {
-            value = isNaN(series.points[i][index]) ? null : series.points[i][index];
-            datapoints[i] = [value, series.points[i][timeCol]];
+          seriesName = alias ? alias : key;
+
+          // if mulitple groups append key to alias
+          if (alias && groupByField) {
+            seriesName += key;
           }
 
-          output.push({ target: target, datapoints: datapoints });
+          output.push({ target: seriesName, datapoints: datapoints });
         });
+
       });
 
       return output;