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

Merge branch 'influxdb_dashstore'

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

+ 2 - 5
src/app/controllers/search.js

@@ -41,7 +41,7 @@ function (angular, _, config, $) {
 
         var selectedDash = $scope.results.dashboards[$scope.selectedIndex];
         if (selectedDash) {
-          $location.path("/dashboard/elasticsearch/" + encodeURIComponent(selectedDash._id));
+          $location.path("/dashboard/elasticsearch/" + selectedDash.id);
           setTimeout(function() {
             $('body').click(); // hack to force dropdown to close;
           });
@@ -90,10 +90,7 @@ function (angular, _, config, $) {
       $scope.showImport = false;
       $scope.selectedIndex = -1;
 
-      var queryStr = $scope.query.query.toLowerCase();
-      queryStr = queryStr.replace(' and ', ' AND ');
-
-      $scope.searchDashboards(queryStr);
+      $scope.searchDashboards($scope.query.query);
     };
 
     $scope.openSearch = function (evt) {

+ 6 - 6
src/app/partials/search.html

@@ -66,11 +66,11 @@
               ng-class="{'selected': $index === selectedIndex }">
             <td><span class="label label-info">metric</span></td>
             <td class="grafana-search-metric-name">
-              {{row._id}}
+              {{row.id}}
             </td>
             <td style="width:100%;">
               <div class="grafana-search-metric-actions">
-                <a ng-click="addMetricToCurrentDashboard(row._id)"><i class="icon-plus-sign"></i> Add to dashboard</a>
+                <a ng-click="addMetricToCurrentDashboard(row.id)"><i class="icon-plus-sign"></i> Add to dashboard</a>
               </div>
             </td>
           </tr>
@@ -78,16 +78,16 @@
           <tr bindonce
               ng-repeat="row in results.dashboards"
               ng-class="{'selected': $index === selectedIndex }">
-            <td><a ng-click="deleteDashboard(row._id)"><i class="icon-remove"></i></a></td>
+            <td><a ng-click="deleteDashboard(row.id)"><i class="icon-remove"></i></a></td>
             <td style="width:100%">
-              <a href="#/dashboard/elasticsearch/{{row._id}}" bo-text="row._id"></a>
+              <a href="#/dashboard/elasticsearch/{{row.id}}" bo-text="row.id"></a>
             </td>
             <td style="white-space: nowrap; text-align: right;">
-              <a ng-click="filterByTag(tag, $event)" ng-repeat="tag in row._source.tags" style="margin-right: 5px;" class="label label-tag">
+              <a ng-click="filterByTag(tag, $event)" ng-repeat="tag in row.tags" style="margin-right: 5px;" class="label label-tag">
                 {{tag}}
               </a>
             </td>
-            <td><a><i class="icon-share" ng-click="shareDashboard(row._id, row._id)" config-modal="app/partials/dashLoaderShare.html"></i></a></td>
+            <td><a><i class="icon-share" ng-click="shareDashboard(row.id, row.id)" config-modal="app/partials/dashLoaderShare.html"></i></a></td>
           </tr>
 					</tbody>
         </table>

+ 2 - 0
src/app/services/elasticsearch/es-datasource.js

@@ -181,6 +181,8 @@ function (angular, _, $, config, kbn, moment) {
     };
 
     ElasticDatasource.prototype.searchDashboards = function(queryString) {
+      queryString = queryString.toLowerCase().replace(' and ', ' AND ');
+
       var tagsOnly = queryString.indexOf('tags!:') === 0;
       if (tagsOnly) {
         var tagsQuery = queryString.substring(6, queryString.length);

+ 94 - 11
src/app/services/influxdb/influxdbDatasource.js

@@ -22,6 +22,7 @@ function (angular, _, kbn, InfluxSeries) {
         interpolate : /\[\[([\s\S]+?)\]\]/g,
       };
 
+      this.grafanaDB = datasource.grafanaDB;
       this.supportAnnotations = true;
       this.supportMetrics = true;
       this.annotationEditorSrc = 'app/partials/influxdb/annotation_editor.html';
@@ -110,7 +111,7 @@ function (angular, _, kbn, InfluxSeries) {
         }
 
         var handleResponse = _.partial(handleInfluxQueryResponse, alias, groupByField);
-        return this.doInfluxRequest(query, alias).then(handleResponse);
+        return this._seriesQuery(query).then(handleResponse);
 
       }, this);
 
@@ -124,13 +125,13 @@ function (angular, _, kbn, InfluxSeries) {
       var timeFilter = getTimeFilter({ range: rangeUnparsed });
       var query = _.template(annotation.query, { timeFilter: timeFilter }, this.templateSettings);
 
-      return this.doInfluxRequest(query).then(function(results) {
+      return this._seriesQuery(query).then(function(results) {
         return new InfluxSeries({ seriesList: results, annotation: annotation }).getAnnotations();
       });
     };
 
     InfluxDatasource.prototype.listColumns = function(seriesName) {
-      return this.doInfluxRequest('select * from /' + seriesName + '/ limit 1').then(function(data) {
+      return this._seriesQuery('select * from /' + seriesName + '/ limit 1').then(function(data) {
         if (!data) {
           return [];
         }
@@ -139,12 +140,12 @@ function (angular, _, kbn, InfluxSeries) {
     };
 
     InfluxDatasource.prototype.listSeries = function() {
-      return this.doInfluxRequest('list series').then(function(data) {
+      return this._seriesQuery('list series').then(function(data) {
         if (!data || data.length === 0) {
           return [];
         }
         // influxdb >= 1.8
-        if (data[0].columns) {
+        if (data[0].points.length > 0) {
           return _.map(data[0].points, function(point) {
             return point[1];
           });
@@ -166,7 +167,7 @@ function (angular, _, kbn, InfluxSeries) {
         return $q.reject(err);
       }
 
-      return this.doInfluxRequest(interpolated)
+      return this._seriesQuery(interpolated)
         .then(function (results) {
           return _.map(results[0].points, function (metric) {
             return {
@@ -190,7 +191,14 @@ function (angular, _, kbn, InfluxSeries) {
       });
     }
 
-    InfluxDatasource.prototype.doInfluxRequest = function(query) {
+    InfluxDatasource.prototype._seriesQuery = function(query) {
+      return this._influxRequest('GET', '/series', {
+        q: query,
+        time_precision: 's',
+      });
+    };
+
+    InfluxDatasource.prototype._influxRequest = function(method, url, data) {
       var _this = this;
       var deferred = $q.defer();
 
@@ -201,14 +209,18 @@ function (angular, _, kbn, InfluxSeries) {
         var params = {
           u: _this.username,
           p: _this.password,
-          time_precision: 's',
-          q: query
         };
 
+        if (method === 'GET') {
+          _.extend(params, data);
+          data = null;
+        }
+
         var options = {
-          method: 'GET',
-          url:    currentUrl + '/series',
+          method: method,
+          url:    currentUrl + url,
           params: params,
+          data:   data
         };
 
         return $http(options).success(function (data) {
@@ -219,6 +231,77 @@ function (angular, _, kbn, InfluxSeries) {
       return deferred.promise;
     };
 
+    InfluxDatasource.prototype.saveDashboard = function(dashboard, title) {
+      var dashboardClone = angular.copy(dashboard);
+      var tags = dashboardClone.tags.join(',');
+      title = dashboardClone.title = title ? title : dashboard.title;
+
+      var data = [{
+        name: 'grafana.dashboard_' + btoa(title),
+        columns: ['time', 'sequence_number', 'title', 'tags', 'dashboard'],
+        points: [[1, 1, title, tags, angular.toJson(dashboardClone)]]
+      }];
+
+      return this._influxRequest('POST', '/series', data).then(function() {
+        return { title: title, url: '/dashboard/elasticsearch/' + title };
+      }, function(err) {
+        throw 'Failed to save dashboard to InfluxDB: ' + err.data;
+      });
+    };
+
+    InfluxDatasource.prototype.getDashboard = function(id) {
+      return this._seriesQuery('select dashboard from "grafana.dashboard_' + btoa(id) + '"').then(function(results) {
+        if (!results || !results.length) {
+          throw "Dashboard not found";
+        }
+        var dashCol = _.indexOf(results[0].columns, 'dashboard');
+        var dashJson = results[0].points[0][dashCol];
+        return angular.fromJson(dashJson);
+      }, function(err) {
+        return "Could not load dashboard, " + err.data;
+      });
+    };
+
+    InfluxDatasource.prototype.searchDashboards = function(queryString) {
+      var influxQuery = 'select title, tags from /grafana.dashboard_.*/ where ';
+
+      var tagsOnly = queryString.indexOf('tags!:') === 0;
+      if (tagsOnly) {
+        var tagsQuery = queryString.substring(6, queryString.length);
+        influxQuery = influxQuery + 'tags =~ /.*' + tagsQuery + '.*/i';
+      }
+      else {
+        var titleOnly = queryString.indexOf('title:') === 0;
+        if (titleOnly) {
+          var titleQuery = queryString.substring(6, queryString.length);
+          influxQuery = influxQuery + ' title =~ /.*' + titleQuery + '.*/i';
+        }
+        else {
+          influxQuery = influxQuery + '(tags =~ /.*' + queryString + '.*/i or title =~ /.*' + queryString + '.*/i)';
+        }
+      }
+
+      return this._seriesQuery(influxQuery).then(function(results) {
+        if (!results || !results.length) {
+          return { dashboards: [], tags: [] };
+        }
+
+        var dashList = [];
+        var dashCol = _.indexOf(results[0].columns, 'title');
+        var tagsCol = _.indexOf(results[0].columns, 'tags');
+
+        for (var i = 0; i < results.length; i++) {
+          var hit =  {
+            id: results[i].points[0][dashCol],
+            tags: results[i].points[0][tagsCol].split(",")
+          };
+          hit.tags = hit.tags[0] ? hit.tags : [];
+          dashList.push(hit);
+        }
+        return { dashboards: dashList, tags: [] };
+      });
+    };
+
     function handleInfluxQueryResponse(alias, groupByField, seriesList) {
       var influxSeries = new InfluxSeries({
         seriesList: seriesList,