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

+ 2 - 1
src/app/components/settings.js

@@ -14,7 +14,8 @@ function (_) {
       panel_names       : [],
       panel_names       : [],
       kibana_index      : 'kibana-int',
       kibana_index      : 'kibana-int',
       graphiteUrl       : null,
       graphiteUrl       : null,
-      default_route     : '/dashboard/file/default.json'
+      default_route     : '/dashboard/file/default.json',
+      grafana_index     : 'grafana-int2'
     };
     };
 
 
     // This initializes a new hash on purpose, to avoid adding parameters to
     // This initializes a new hash on purpose, to avoid adding parameters to

+ 2 - 1
src/app/controllers/all.js

@@ -4,5 +4,6 @@ define([
   './row',
   './row',
   './pulldown',
   './pulldown',
   './zoom',
   './zoom',
-  './search'
+  './search',
+  './metricKeys'
 ], function () {});
 ], function () {});

+ 113 - 0
src/app/controllers/metricKeys.js

@@ -0,0 +1,113 @@
+define([
+  'angular',
+  'underscore',
+  'config'
+],
+function (angular, _, config) {
+  'use strict';
+
+  var module = angular.module('kibana.controllers');
+
+  module.controller('MetricKeysCtrl', function($scope, $http) {
+
+    $scope.init = function () {
+      $scope.metricPath = "prod.apps.api.boobarella.*";
+    };
+
+    $scope.loadMetricsFromPath = function () {
+      $scope.infoText = 'loading';
+      loadMetricsRecursive($scope.metricPath)
+
+      /*$http.put(config.elasticsearch + "/grafana-int/", {
+{
+  "settings": {
+    "analysis": {
+      "analyzer": {
+        "category_path": {
+          "type": "custom",
+          "tokenizer": "category_path"
+        },
+        "my_ngram_analyzer" : {
+      "tokenizer" : "my_ngram_tokenizer"
+    }
+      },
+      "tokenizer": {
+        "category_path": {
+          "type": "path_hierarchy",
+          "delimiter": "."
+        },
+        "my_ngram_tokenizer" : {
+          "type" : "nGram",
+          "min_gram" : "4",
+          "max_gram" : "8",
+          "token_chars": [ "letter", "digit" ]
+        }
+      }
+    }
+  },
+  "mappings": {
+    "metricKey": {
+      "properties": {
+        "metricPath": {
+          "type": "string",
+          "index": "analyzed",
+          "index_analyzer": "my_ngram_analyzer"
+    }
+      }
+    }
+  }
+}
+      });*/
+    };
+
+    function receiveMetric(data) {
+      if (!data || data.length == 0) {
+        console.log('no data');
+        return;
+      }
+
+      _.each(data, function(metric) {
+        if (metric.expandable) {
+          console.log('Loading children: ' + metric.id);
+          loadMetricsRecursive(metric.id + ".*");
+        }
+        if (metric.leaf) {
+          saveMetricKey(metric.id);
+        }
+      });
+    }
+
+    function saveMetricKey(metricId) {
+
+      // Create request with id as title. Rethink this.
+      var request = ejs.Document(config.grafana_index, 'metricKey', metricId).source({
+        metricPath: metricId
+      });
+
+      request.doIndex(
+        // Success
+        function(result) {
+          console.log('save metric success', result);
+        },
+        function(error) {
+          console.log('save metric error', error);
+        }
+      );
+    }
+
+    function metricLoadError(data, status, headers, config)
+    {
+      console.log('error: ' + status);
+      $scope.error = "failed to get metrics from graphite";
+    }
+
+    function loadMetricsRecursive(metricPath, data, callback)
+    {
+      $http({ method: 'GET', url: config.graphiteUrl + '/metrics/find/?query=' + metricPath} )
+        .success(receiveMetric)
+        .error(metricLoadError);
+    }
+
+  });
+
+});

+ 39 - 14
src/app/controllers/search.js

@@ -1,7 +1,10 @@
 define([
 define([
-  'angular'
+  'angular',
+  'underscore',
+  'config',
+  'jquery'
 ],
 ],
-function (angular) {
+function (angular, _, config, $) {
   'use strict';
   'use strict';
 
 
   var module = angular.module('kibana.controllers');
   var module = angular.module('kibana.controllers');
@@ -11,14 +14,33 @@ function (angular) {
     $scope.init = function() {
     $scope.init = function() {
       $scope.elasticsearch = $scope.elasticsearch || {};
       $scope.elasticsearch = $scope.elasticsearch || {};
       $scope.giveSearchFocus = 0;
       $scope.giveSearchFocus = 0;
+      $scope.search_results = {
+        dashboards: [],
+        metrics: [],
+        graphs: []
+      };
     };
     };
 
 
     $scope.elasticsearch_dblist = function(query) {
     $scope.elasticsearch_dblist = function(query) {
-      dashboard.elasticsearch_list(query,100).then(
-        function(result) {
-        if(!_.isUndefined(result.hits)) {
-          $scope.hits = result.hits.total;
-          $scope.elasticsearch.dashboards = result.hits.hits;
+      var words = query.split(" ");
+      var query = $scope.ejs.BoolQuery();
+      var terms = _.map(words, function(word) {
+        return $scope.ejs.MatchQuery("metricPath", word);
+      });
+
+      console.log("query: ", terms);
+      query.must(terms);
+
+      var request = $scope.ejs.Request().indices(config.grafana_index).types('metricKey');
+      var results = request.query(query).size(20).doSearch();
+
+      results.then(function(results) {
+        if (results && results.hits && results.hits.hits.length > 0) {
+          $scope.search_results.metrics = results.hits.hits;
+          console.log("hits", $scope.search_results.metrics);
+        }
+        else {
+          $scope.search_results.metrics = [];
         }
         }
       });
       });
     };
     };
@@ -31,13 +53,16 @@ function (angular) {
 
 
   module.directive('xngFocus', function() {
   module.directive('xngFocus', function() {
     return function(scope, element, attrs) {
     return function(scope, element, attrs) {
-       scope.$watch(attrs.xngFocus,
-         function (newValue) {
-            setTimeout(function() {
-              newValue && element.focus();
-            }, 200);
-         },true);
-      };
+      $(element).click(function(e) {
+        e.stopPropagation();
+      });
+
+      scope.$watch(attrs.xngFocus,function (newValue) {
+        setTimeout(function() {
+          newValue && element.focus();
+        }, 200);
+      },true);
+    };
   });
   });
 
 
 });
 });

+ 1 - 1
src/app/panels/graphite/graphiteSrv.js

@@ -84,7 +84,7 @@ function ($, RQ, config) {
       accepts: { text: 'application/json' },
       accepts: { text: 'application/json' },
       cache: false,
       cache: false,
       dataType: 'json',
       dataType: 'json',
-      url: config.graphiteUrl,
+      url: config.graphiteUrl + '/render/',
       type: "POST",
       type: "POST",
       data: parameters.join('&')
       data: parameters.join('&')
     });
     });

+ 0 - 92
src/app/partials/dashLoader.html

@@ -11,99 +11,7 @@
 <li ng-repeat="pulldown in dashboard.current.nav" ng-controller="PulldownCtrl" ng-show="pulldown.enable"><kibana-simple-panel type="pulldown.type" ng-cloak></kibana-simple-panel></li>
 <li ng-repeat="pulldown in dashboard.current.nav" ng-controller="PulldownCtrl" ng-show="pulldown.enable"><kibana-simple-panel type="pulldown.type" ng-cloak></kibana-simple-panel></li>
 
 
 <li><a bs-tooltip="'Goto saved default'" data-placement="bottom" href='#/dashboard'><i class='icon-home'></i></a></li>
 <li><a bs-tooltip="'Goto saved default'" data-placement="bottom" href='#/dashboard'><i class='icon-home'></i></a></li>
-<li class="dropdown" ng-show="showDropdown('load')" >
-  <a href="#" bs-tooltip="'Load'" data-placement="bottom" class="dropdown-toggle" data-toggle="dropdown" ng-click="elasticsearch_dblist('title:'+elasticsearch.query+'*')">
-    <i class='icon-folder-open'></i>
-  </a>
 
 
-  <ul class="dropdown-menu" style="padding:10px">
-    <li ng-if='dashboard.current.loader.load_elasticsearch'>
-      <form class="nomargin">
-        <input type="text" ng-model="elasticsearch.query" ng-change="elasticsearch_dblist('title:'+elasticsearch.query+'*')" placeholder="Type to filter"/>
-      </form>
-      <h6 ng-hide="elasticsearch.dashboards.length">No dashboards matching your query found</h6>
-      <table class="table table-condensed table-striped">
-        <tr bindonce ng-repeat="row in elasticsearch.dashboards | orderBy:['_id']">
-          <td><a ng-click="elasticsearch_delete(row._id)"><i class="icon-remove"></i></a></td>
-          <td><a href="#/dashboard/elasticsearch/{{row._id}}" bo-text="row._id"></a></td>
-          <td><a><i class="icon-share" ng-click="share = dashboard.share_link(row._id,'elasticsearch',row._id)" bs-modal="'app/panels/dashcontrol/share.html'"></i></a></td>
-        </tr>
-      </table>
-    </li>
-
-    <li class="dropdown-submenu noarrow" ng-show="dashboard.current.loader.load_gist || dashboard.current.loader.load_local">
-      <a tabindex="-1" class="small" style="padding:0"><i class="icon-caret-left"></i> Advanced</a>
-      <ul class="dropdown-menu" style="padding:10px">
-        <li ng-show='dashboard.current.loader.load_local'>
-          <h5>Local File <tip>Load dashboard JSON layout from file</tip></h5>
-          <form>
-            <input type="file" id="dashupload" dash-upload /><br>
-          </form>
-        </li>
-        <li ng-show='dashboard.current.loader.load_gist'>
-          <h5>Gist <tip>Enter a gist number or url</tip></h5>
-          <form>
-            <input type="text" ng-model="gist.url"/ placeholder="Gist number or URL"><br>
-            <button class="btn" ng-click="gist_dblist(dashboard.gist_id(gist.url))" ng-show="dashboard.is_gist(gist.url)"><i class="icon-github-alt"></i> Get gist:{{gist.url | gistid}}</button>
-            <h6 ng-show="gist.files.length">Dashboards in gist:{{gist.url | gistid}} <small>click to load</small></h6>
-            <h6 ng-hide="gist.files.length || !gist.url.length">No gist dashboards found</h6>
-            <table class="table table-condensed table-striped">
-              <tr ng-repeat="file in gist.files">
-                <td><a ng-click="dashboard.dash_load(file)">{{file.title}}</a></td>
-              </tr>
-            </table>
-          </form>
-        </li>
-      </ul>
-    </li>
-
-  </ul>
-
-
-</li>
-<li class="dropdown"ng-show="showDropdown('save')">
-  <a href="#"  bs-tooltip="'Save'" data-placement="bottom" class="dropdown-toggle" data-toggle="dropdown">
-    <i class='icon-save'></i>
-  </a>
-
-
-  <ul class="dropdown-menu" style="padding:10px">
-
-    <li ng-show="dashboard.current.loader.save_elasticsearch">
-      <form class="input-prepend nomargin">
-        <button style="margin-top:-1px" class="btn" ng-click="elasticsearch_save('dashboard')"><i class="icon-save"></i></button>
-        <input class='input-medium' ng-model="dashboard.current.title" type="text" ng-model="elasticsearch.title"/>
-      </form>
-    </li>
-
-    <li class="dropdown-submenu noarrow" ng-show="dashboard.current.loader.save_local || dashboard.current.loader.save_gist || dashboard.current.loader.save_default">
-      <a tabindex="-1" class="small" style="padding:0"><i class="icon-caret-left"></i> Advanced</a>
-      <ul class="dropdown-menu">
-
-        <li ng-show="dashboard.current.loader.save_default">
-          <a class="link" ng-click="set_default()">Save as Home</a>
-        </li>
-        <li ng-show="dashboard.current.loader.save_default">
-          <a class="link" ng-click="purge_default()">Reset Home</a>
-        </li>
-        <li ng-show="dashboard.current.loader.save_local">
-          <a class="link" ng-click="dashboard.to_file()">Export schema</a>
-        </li>
-
-        <li ng-show="dashboard.current.loader.save_gist" style="margin:10px">
-          <h6>Gist</h6>
-          <form class="input-append">
-            <input class='input-medium' placeholder='Title' type="text" ng-model="gist.title"/>
-            <button class="btn" ng-click="save_gist()"><i class="icon-github-alt"></i></button>
-          </form><br>
-          <small ng-show="gist.last">Last gist: <a target="_blank" href="{{gist.last}}">{{gist.last}}</a></small>
-        </li>
-      </ul>
-    </li>
-  </ul>
-
-
-</li>
 <li ng-show="showDropdown('share')"><a bs-tooltip="'Share'" data-placement="bottom" ng-click="elasticsearch_save('temp',dashboard.current.loader.save_temp_ttl)" bs-modal="'app/partials/dashLoaderShare.html'"><i class='icon-share'></i></a></li>
 <li ng-show="showDropdown('share')"><a bs-tooltip="'Share'" data-placement="bottom" ng-click="elasticsearch_save('temp',dashboard.current.loader.save_temp_ttl)" bs-modal="'app/partials/dashLoaderShare.html'"><i class='icon-share'></i></a></li>
 
 
 <li ng-show="dashboard.current.editable" bs-tooltip="'Configure dashboard'" data-placement="bottom"><a href='#' bs-modal="'app/partials/dasheditor.html'"><i class='icon-cog pointer'></i></a></li>
 <li ng-show="dashboard.current.editable" bs-tooltip="'Configure dashboard'" data-placement="bottom"><a href='#' bs-modal="'app/partials/dasheditor.html'"><i class='icon-cog pointer'></i></a></li>

+ 6 - 3
src/app/partials/dasheditor.html

@@ -2,7 +2,7 @@
   <div class="pull-right editor-title">Dashboard settings</div>
   <div class="pull-right editor-title">Dashboard settings</div>
 
 
   <div ng-model="editor.index" bs-tabs style="text-transform:capitalize;">
   <div ng-model="editor.index" bs-tabs style="text-transform:capitalize;">
-    <div ng-repeat="tab in ['General', 'Rows','Controls']" data-title="{{tab}}">
+    <div ng-repeat="tab in ['General', 'Rows','Controls', 'Metrics']" data-title="{{tab}}">
     </div>
     </div>
     <div ng-repeat="tab in dashboard.current.nav" data-title="{{tab.type}}">
     <div ng-repeat="tab in dashboard.current.nav" data-title="{{tab.type}}">
     </div>
     </div>
@@ -122,12 +122,15 @@
     </div>
     </div>
   </div>
   </div>
 
 
-  <div ng-repeat="pulldown in dashboard.current.nav" ng-controller="PulldownCtrl" ng-show="editor.index == 3+$index">
+  <div ng-show="editor.index == 3">
+    <ng-include src="'app/partials/loadmetrics.html'"></ng-include>
+  </div>
+
+  <div ng-repeat="pulldown in dashboard.current.nav" ng-controller="PulldownCtrl" ng-show="editor.index == 4+$index">
     <ng-include ng-show="pulldown.enable" src="edit_path(pulldown.type)"></ng-include>
     <ng-include ng-show="pulldown.enable" src="edit_path(pulldown.type)"></ng-include>
     <button ng-hide="pulldown.enable" class="btn" ng-click="pulldown.enable = true">Enable the {{pulldown.type}}</button>
     <button ng-hide="pulldown.enable" class="btn" ng-click="pulldown.enable = true">Enable the {{pulldown.type}}</button>
   </div>
   </div>
 
 
-
 </div>
 </div>
 
 
 <div class="modal-footer">
 <div class="modal-footer">

+ 25 - 0
src/app/partials/loadmetrics.html

@@ -0,0 +1,25 @@
+<div ng-controller="MetricKeysCtrl" ng-init="init()">
+  <h5>Load metrics keys into elastic search</h5>
+  <div class="row-fluid">
+    <div class="span8">
+      <label class="small">Load all metric keys at once (intensive for graphite web)</label>
+    </div>
+    <div class="span4">
+      <button class="btn btn-danger">Start load all</button>
+    </div>
+  </div>
+  <div class="row-fluid">
+    <div class="span8">
+      <label class="small">Load metric keys recursively starting at metric key path</label>
+      <input type="text" class="input-xlarge" ng-model="metricPath"> </input>
+    </div>
+    <div class="span4">
+      <button class="btn btn-danger" style="margin-top: 20px" ng-click="loadMetricsFromPath()">Start load from metric path</button>
+    </div>
+  </div>
+  <div class="row-fluid">
+    <div class="span12 alert-message block-message info">
+      {{infoText}}
+    </div>
+  </div>
+</div>

+ 8 - 4
src/app/partials/search.html

@@ -19,15 +19,19 @@
   <ul class="dropdown-menu grafana-search">
   <ul class="dropdown-menu grafana-search">
     <li>
     <li>
       <div class="grafana-search-panel">
       <div class="grafana-search-panel">
-        <input type="text" placeholder="search dashboards, metrics, or graphs" xng-focus="giveSearchFocus" ng-model="elasticsearch.query" ng-change="elasticsearch_dblist('title:'+elasticsearch.query+'*')" />
+        <input type="text" placeholder="search dashboards, metrics, or graphs" xng-focus="giveSearchFocus" ng-model="elasticsearch.query" ng-change="elasticsearch_dblist(elasticsearch.query)" />
 
 
-        <h6 ng-hide="elasticsearch.dashboards.length">No dashboards matching your query found</h6>
+        <h6 ng-hide="search_results.metrics.length">No dashboards matching your query found</h6>
         <table class="table table-condensed table-striped">
         <table class="table table-condensed table-striped">
-          <tr bindonce ng-repeat="row in elasticsearch.dashboards | orderBy:['_id']">
+          <tr bindonce ng-repeat="row in search_results.metrics">
+            <td><span class="label label-info">metric</span> {{row._id}}</td>
+          </tr>
+<!--
+          <tr bindonce ng-repeat="row in search_results | orderBy:['_id']">
             <td><a ng-click="elasticsearch_delete(row._id)"><i class="icon-remove"></i></a></td>
             <td><a ng-click="elasticsearch_delete(row._id)"><i class="icon-remove"></i></a></td>
             <td><a href="#/dashboard/elasticsearch/{{row._id}}" bo-text="row._id"></a></td>
             <td><a href="#/dashboard/elasticsearch/{{row._id}}" bo-text="row._id"></a></td>
             <td><a><i class="icon-share" ng-click="share = dashboard.share_link(row._id,'elasticsearch',row._id)" bs-modal="'app/panels/dashcontrol/share.html'"></i></a></td>
             <td><a><i class="icon-share" ng-click="share = dashboard.share_link(row._id,'elasticsearch',row._id)" bs-modal="'app/panels/dashcontrol/share.html'"></i></a></td>
-          </tr>
+          </tr> -->
         </table>
         </table>
       </div>
       </div>
     </li>
     </li>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/css/bootstrap.dark.min.css


+ 5 - 0
src/vendor/bootstrap/less/grafana.less

@@ -18,3 +18,8 @@
   //padding: 0 0 10px 10px;
   //padding: 0 0 10px 10px;
 }
 }
 
 
+.modal {
+  width: 770px;
+  margin-left: -385px;
+  top: 100px !important;
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов