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

Merge pull request #85 from rashidkpc/master

Derive Queries Panel
Rashid Khan 12 лет назад
Родитель
Сommit
b164e5ea79
4 измененных файлов с 174 добавлено и 1 удалено
  1. 1 1
      config.js
  2. 17 0
      panels/derivequeries/editor.html
  3. 32 0
      panels/derivequeries/module.html
  4. 124 0
      panels/derivequeries/module.js

+ 1 - 1
config.js

@@ -20,6 +20,6 @@ var config = new Settings(
   kibana_index:     "kibana-int", 
   modules:          ['histogram','map','pie','table','stringquery','sort',
                     'timepicker','text','fields','hits','dashcontrol',
-                    'column'],
+                    'column','derivequeries'],
   }
 );

+ 17 - 0
panels/derivequeries/editor.html

@@ -0,0 +1,17 @@
+<div>
+  <div class="row-fluid">    
+    <div class="span12">
+      The derive queries panel takes a query and a field, then runs a terms facet against both and generates a list of terms to query on. For example, you might want to see a histogram of the top 5 requests that return a 404. <strong>You should be careful not to select a high cardinality field</strong> as Elasticsearch must load all of these values into memory.
+    </div>
+  </div>
+  <div class="row-fluid">
+    <div class="span3">
+      <label class="small">Length</label>
+      <input type="number" style="width:80%" ng-model="panel.size" ng-change="set_refresh(true)">
+    </div>
+    <div class="span8">
+      <label class="small">Exclude Terms(s) (comma seperated)</label>
+        <input array-join type="text" style="width:90%" ng-change="set_refresh(true)" ng-model='panel.exclude'></input>
+    </div>
+  </div>
+</div>

+ 32 - 0
panels/derivequeries/module.html

@@ -0,0 +1,32 @@
+<kibana-panel ng-controller='derivequeries' ng-init="init()">
+  <span ng-show='panel.spyable' style="position:absolute;right:0px;top:0px" class='panelextra pointer'>
+      <i bs-modal="'partials/modal.html'" class="icon-eye-open"></i>
+  </span>
+  <div ng-show="!panel.multi">
+    <form>
+      <table class="form-horizontal">
+        <tr>
+          <td><label><small>{{panel.label}}</small></label></td>
+          <td><label><small>Field</small></label></td>
+        </tr>
+        <tr>
+          <td width="97%" style="padding-right:20px">
+            <input type="text" style="width:100%" ng-model="panel.query">
+          </td>
+          <td ng-show="panel.fields.length > 0">
+            <select class="input-small" ng-model="panel.field" ng-options="f for f in panel.fields"></select>
+          </td>
+          <td ng-show="panel.fields.length == 0">
+            <input class="input-small" ng-model="panel.field" type="text"/>
+          </td>
+          <td style="margin-left:20px" width="1%">
+            <button style="margin-top:0px" type="submit" class="btn btn-info" ng-click="get_data()"><i class="icon-search"></i></button>
+          </td>
+          <td width="1%">
+            <button style="margin-top:0px"  type="submit" class="btn btn-danger" ng-click="panel.query='';get_data()"><i class="icon-ban-circle"></i></button>
+          </td>
+        <tr>
+      </table>
+    </form>
+  </div>
+</kibana-panel>

+ 124 - 0
panels/derivequeries/module.js

@@ -0,0 +1,124 @@
+/*
+
+  ## Termsquery
+
+  Broadcasts an array of queries based on the results of a terms facet
+
+  ### Parameters
+  * label :: The label to stick over the field 
+  * query :: A string to use as a filter for the terms facet
+  * field :: the field to facet on
+  * size :: how many queries to generate
+  * fields :: a list of fields known to us
+  
+  ### Group Events
+  #### Sends
+  * query :: Always broadcast as an array, even in multi: false
+  * get_time :: Request the time object from the timepicker
+  #### Receives
+  * query :: An array of queries. This is probably needs to be fixed.
+  * time :: populate index and time
+  * fields :: A list of fields known to us
+*/
+
+angular.module('kibana.derivequeries', [])
+.controller('derivequeries', function($scope, eventBus) {
+
+  // Set and populate defaults
+  var _d = {
+    label   : "Search",
+    query   : "*",
+    group   : "default",
+    field   : '_type',
+    fields  : [],
+    spyable : true,
+    size    : 5,
+    exclude : []
+  }
+  _.defaults($scope.panel,_d);
+
+  $scope.init = function() {
+    eventBus.register($scope,'fields', function(event, fields) {
+      $scope.panel.fields = fields.all;
+    });
+    eventBus.register($scope,'time', function(event,time){set_time(time)});
+    eventBus.register($scope,'query', function(event, query) {
+      $scope.panel.query = _.isArray(query) ? query[0] : query;
+      $scope.get_data();
+    });
+    // Now that we're all setup, request the time from our group
+    eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
+  }
+
+  $scope.get_data = function() {
+    // Make sure we have everything for the request to complete
+    if(_.isUndefined($scope.index) || _.isUndefined($scope.time))
+      return
+
+    $scope.panel.loading = true;
+    var request = $scope.ejs.Request().indices($scope.index);
+
+    // Terms mode
+    request = request
+      .facet(ejs.TermsFacet('query')
+        .field($scope.panel.field)
+        .size($scope.panel['size'])
+        .exclude($scope.panel.exclude)
+        .facetFilter(ejs.QueryFilter(
+          ejs.FilteredQuery(
+            ejs.QueryStringQuery($scope.panel.query || '*'),
+            ejs.RangeFilter($scope.time.field)
+              .from($scope.time.from)
+              .to($scope.time.to)
+            )))).size(0)
+
+    $scope.populate_modal(request);
+
+    var results = request.doSearch();
+
+    // Populate scope when we have results
+    results.then(function(results) {
+      $scope.panel.loading = false;
+      var data = [];
+      _.each(results.facets.query.terms, function(v) {
+        data.push($scope.panel.field+":"+v.term)
+      });
+      console.log(data)
+      $scope.send_query(data)
+    });
+  }
+
+  $scope.set_refresh = function (state) { 
+    $scope.refresh = state; 
+  }
+
+  $scope.close_edit = function() {
+    if($scope.refresh)
+      $scope.get_data();
+    $scope.refresh =  false;
+  }
+
+  $scope.populate_modal = function(request) {
+    $scope.modal = {
+      title: "Inspector",
+      body : "<h5>Last Elasticsearch Query</h5><pre>"+
+          'curl -XGET '+config.elasticsearch+'/'+$scope.index+"/_search?pretty -d'\n"+
+          angular.toJson(JSON.parse(request.toString()),true)+
+        "'</pre>", 
+    } 
+  }
+
+  function set_time(time) {
+    $scope.time = time;
+    $scope.index = _.isUndefined(time.index) ? $scope.index : time.index
+    $scope.get_data();
+  }
+
+  $scope.send_query = function(query) {
+    var _query = _.isArray(query) ? query : [query]
+    eventBus.broadcast($scope.$id,$scope.panel.group,'query',_query)
+  }
+
+
+
+});