Просмотр исходного кода

Merge branch 'influxdb-updates' of github.com:influxdb/grafana into influxdb-influxdb-updates

Torkel Ödegaard 11 лет назад
Родитель
Сommit
c592db4024

+ 6 - 0
src/app/components/settings.js

@@ -49,6 +49,11 @@ function (_, crypto) {
       return datasource;
     };
 
+    var parseMultipleHosts = function(datasource) {
+      datasource.urls = _.map(datasource.url.split(","), function (url) { return url.trim(); });
+      return datasource;
+    };
+
     if (options.graphiteUrl) {
       settings.datasources = {
         graphite: {
@@ -62,6 +67,7 @@ function (_, crypto) {
     _.each(settings.datasources, function(datasource, key) {
       datasource.name = key;
       parseBasicAuth(datasource);
+      if (datasource.type === 'influxdb') { parseMultipleHosts(datasource); }
     });
 
     var elasticParsed = parseBasicAuth({ url: settings.elasticsearch });

+ 11 - 1
src/app/controllers/influxTargetCtrl.js

@@ -15,6 +15,8 @@ function (angular) {
         $scope.target.function = 'mean';
       }
 
+      $scope.rawQuery = false;
+
       $scope.functions = ['count', 'mean', 'sum', 'min', 'max', 'mode', 'distinct', 'median', 'derivative', 'stddev', 'first', 'last'];
       $scope.oldSeries = $scope.target.series;
       $scope.$on('typeahead-updated', function(){
@@ -22,6 +24,14 @@ function (angular) {
       });
     };
 
+    $scope.showQuery = function () {
+      $scope.target.rawQuery = true;
+    };
+
+    $scope.hideQuery = function () {
+      $scope.target.rawQuery = false;
+    };
+
     // Cannot use typeahead and ng-change on blur at the same time
     $scope.seriesBlur = function() {
       if ($scope.oldSeries !== $scope.target.series) {
@@ -65,4 +75,4 @@ function (angular) {
 
   });
 
-});
+});

+ 35 - 21
src/app/partials/influxdb/editor.html

@@ -11,17 +11,16 @@
       <div class="grafana-target-inner">
         <ul class="grafana-target-controls">
           <li class="dropdown">
-            <a  class="pointer dropdown-toggle"
-                data-toggle="dropdown"
-                tabindex="1">
+            <a class="pointer dropdown-toggle"
+               data-toggle="dropdown"
+               tabindex="1">
               <i class="icon-cog"></i>
             </a>
             <ul class="dropdown-menu pull-right" role="menu">
               <li role="menuitem">
-                <a  tabindex="1"
-                    ng-click="duplicate()">
-                  Duplicate
-                </a>
+                <a tabindex="1" ng-click="duplicate()">Duplicate</a>
+                <a tabindex="2" ng-click="showQuery()" ng-hide="target.rawQuery">Show Query</a>
+                <a tabindex="2" ng-click="hideQuery()" ng-show="target.rawQuery">Hide Query</a>
               </li>
             </ul>
           </li>
@@ -34,19 +33,30 @@
 
         <ul class="grafana-target-controls-left">
           <li>
-            <a  class="grafana-target-segment"
-                ng-click="target.hide = !target.hide; get_data();"
-                role="menuitem">
+            <a class="grafana-target-segment"
+               ng-click="target.hide = !target.hide; get_data();"
+               role="menuitem">
               <i class="icon-eye-open"></i>
             </a>
           </li>
         </ul>
 
+
         <ul class="grafana-segment-list" role="menu">
-          <li class="grafana-target-segment">
+          <li ng-show="target.rawQuery">
+            <input type="text"
+                   class="input-large grafana-target-segment-input"
+                   style="width:843px;"
+                   ng-model="target.query"
+                   placeholder="select ..."
+                   data-min-length=0 data-items=100
+                   ng-blur="get_data()">
+          </li>
+          <li class="grafana-target-segment" ng-hide="target.rawQuery">
             from series
           </li>
-          <li>
+
+          <li ng-hide="target.rawQuery">
             <input type="text"
                    class="input-medium grafana-target-segment-input"
                    ng-model="target.series"
@@ -54,13 +64,14 @@
                    bs-typeahead="listSeries"
                    placeholder="series name"
                    data-min-length=0 data-items=100
-                   ng-blur="seriesBlur()"
-                   >
+                   ng-blur="seriesBlur()">
           </li>
-          <li class="grafana-target-segment">
+
+          <li class="grafana-target-segment" ng-hide="target.rawQuery">
             select
           </li>
-          <li>
+
+          <li ng-hide="target.rawQuery">
             <input type="text"
                    class="input-medium grafana-target-segment-input"
                    ng-model="target.column"
@@ -70,20 +81,23 @@
                    data-min-length=0
                    ng-blur="get_data()">
           </li>
-          <li class="grafana-target-segment">
+
+          <li class="grafana-target-segment" ng-hide="target.rawQuery">
             function
           </li>
-          <li>
+
+          <li ng-hide="target.rawQuery">
             <select class="input-medium grafana-target-segment-input"
                     ng-change="get_data()"
                     ng-model="target.function"
                     ng-options="f for f in functions" ></select>
           </li>
-          </li>
-          <li class="grafana-target-segment">
+
+          <li class="grafana-target-segment" ng-hide="target.rawQuery">
             group by time
           </li>
-          <li>
+
+          <li ng-hide="target.rawQuery">
             <input type="text"
                    class="input-mini grafana-target-segment-input"
                    ng-model="target.interval"

+ 88 - 37
src/app/services/influxdb/influxdbDatasource.js

@@ -13,7 +13,7 @@ function (angular, _, kbn) {
     function InfluxDatasource(datasource) {
       this.type = 'influxDB';
       this.editorSrc = 'app/partials/influxdb/editor.html';
-      this.url = datasource.url;
+      this.urls = datasource.urls;
       this.username = datasource.username;
       this.password = datasource.password;
       this.name = datasource.name;
@@ -26,78 +26,129 @@ function (angular, _, kbn) {
     InfluxDatasource.prototype.query = function(options) {
 
       var promises = _.map(options.targets, function(target) {
-        if (!target.series || !target.column || target.hide) {
+        var query;
+
+        if (target.hide || !((target.series && target.column) || target.query)) {
           return [];
         }
 
-        var template = "select [[func]]([[column]]) as [[column]]_[[func]] from [[series]] where [[timeFilter]]" + 
-          " group by time([[interval]]) order asc";
+        var timeFilter = getTimeFilter(options);
 
-        var templateData = {
-          series: target.series,
-          column: target.column,
-          func: target.function,
-          timeFilter: getTimeFilter(options),
-          interval: target.interval || options.interval
-        };
+        if (target.rawQuery) {
+          query = target.query;
+          query = query.replace(";", "");
+          var queryElements = query.split(" ");
+          var lowerCaseQueryElements = query.toLowerCase().split(" ");
+          var whereIndex = lowerCaseQueryElements.indexOf("where");
+          var groupByIndex = lowerCaseQueryElements.indexOf("group");
+          var orderIndex = lowerCaseQueryElements.indexOf("order");
+
+          if (whereIndex !== -1) {
+            queryElements.splice(whereIndex+1, 0, timeFilter, "and");
+          }
+          else {
+            if (groupByIndex !== -1) {
+              queryElements.splice(groupByIndex, 0, "where", timeFilter);
+            }
+            else if (orderIndex !== -1) {
+              queryElements.splice(orderIndex, 0, "where", timeFilter);
+            }
+            else {
+              queryElements.push("where");
+              queryElements.push(timeFilter);
+            }
+          }
+
+          query = queryElements.join(" ");
 
-        var query = _.template(template, templateData, this.templateSettings);
+        }
+        else {
+          var template = "select [[func]]([[column]]) as [[column]]_[[func]] from [[series]] where [[timeFilter]]" +
+                         " group by time([[interval]]) order asc";
+
+          var templateData = {
+            series: target.series,
+            column: target.column,
+            func: target.function,
+            timeFilter: timeFilter,
+            interval: target.interval || options.interval
+          };
+
+          query = _.template(template, templateData, this.templateSettings);
+          target.query = query;
+        }
 
         return this.doInfluxRequest(query).then(handleInfluxQueryResponse);
 
       }, this);
 
       return $q.all(promises).then(function(results) {
-
         return { data: _.flatten(results) };
       });
 
     };
 
     InfluxDatasource.prototype.listColumns = function(seriesName) {
-      return this.doInfluxRequest('select * from ' + seriesName + ' limit 1').then(function(results) {
-        console.log('response!');
-        if (!results.data) {
+      return this.doInfluxRequest('select * from ' + seriesName + ' limit 1').then(function(data) {
+        if (!data) {
           return [];
         }
 
-        return results.data[0].columns;
+        return data[0].columns;
       });
     };
 
     InfluxDatasource.prototype.listSeries = function() {
-      return this.doInfluxRequest('list series').then(function(results) {
-        if (!results.data) {
-          return [];
-        }
-
-        return _.map(results.data, function(series) {
+      return this.doInfluxRequest('list series').then(function(data) {
+        return _.map(data, function(series) {
           return series.name;
         });
       });
     };
 
+    function retry(deferred, callback, delay) {
+      return callback().then(undefined, function(reason) {
+        if (reason.status !== 0) {
+          deferred.reject(reason);
+        }
+        setTimeout(function() {
+          return retry(deferred, callback, Math.min(delay * 2, 30000));
+        }, delay);
+      });
+    }
+
     InfluxDatasource.prototype.doInfluxRequest = function(query) {
-      var params = {
-        u: this.username,
-        p: this.password,
-        q: query
-      };
+      var _this = this;
+      var deferred = $q.defer();
 
-      var options = {
-        method: 'GET',
-        url:    this.url + '/series',
-        params: params,
-      };
+      retry(deferred, function() {
+        var currentUrl = _this.urls.shift();
+        _this.urls.push(currentUrl);
+
+        var params = {
+          u: _this.username,
+          p: _this.password,
+          q: query
+        };
+
+        var options = {
+          method: 'GET',
+          url:    currentUrl + '/series',
+          params: params,
+        };
+
+        return $http(options).success(function (data) {
+          deferred.resolve(data);
+        });
+      }, 10);
 
-      console.log(query);
-      return $http(options);
+      return deferred.promise;
     };
 
-    function handleInfluxQueryResponse(results) {
+    function handleInfluxQueryResponse(data) {
       var output = [];
 
-      _.each(results.data, function(series) {
+      _.each(data, function(series) {
         var timeCol = series.columns.indexOf('time');
 
         _.each(series.columns, function(column, index) {