From ed0056dd1819c8fc267127c830066d628e36e1c1 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 15 May 2013 16:02:32 -0700 Subject: [PATCH 1/2] Derive queries panel creates a query object from a terms facet --- config.js | 2 +- panels/derivequeries/editor.html | 17 +++++ panels/derivequeries/module.html | 29 +++++++ panels/derivequeries/module.js | 125 +++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 panels/derivequeries/editor.html create mode 100644 panels/derivequeries/module.html create mode 100644 panels/derivequeries/module.js diff --git a/config.js b/config.js index d9e8804ff2e..cc2c96993f8 100644 --- a/config.js +++ b/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'], } ); diff --git a/panels/derivequeries/editor.html b/panels/derivequeries/editor.html new file mode 100644 index 00000000000..442e55d72a8 --- /dev/null +++ b/panels/derivequeries/editor.html @@ -0,0 +1,17 @@ +
+
+
+ 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. You should be careful not to select a high cardinality field as Elasticsearch must load all of these values into memory. +
+
+
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/panels/derivequeries/module.html b/panels/derivequeries/module.html new file mode 100644 index 00000000000..5599433836e --- /dev/null +++ b/panels/derivequeries/module.html @@ -0,0 +1,29 @@ + + + + +
+
+ + + + + + + + + + + +
+ + + + + + + +
+
+
+
\ No newline at end of file diff --git a/panels/derivequeries/module.js b/panels/derivequeries/module.js new file mode 100644 index 00000000000..3f7a6b8fe9c --- /dev/null +++ b/panels/derivequeries/module.js @@ -0,0 +1,125 @@ +/* + + ## 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', + spyable : true, + size : 5, + exclude : [] + } + _.defaults($scope.panel,_d); + + $scope.init = function() { + eventBus.register($scope,'fields', function(event, fields) { + $scope.panel.sort = _.clone(fields.sort); + $scope.fields = fields.all, + $scope.active = _.clone(fields.active); + }); + 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 : "
Last Elasticsearch Query
"+
+          'curl -XGET '+config.elasticsearch+'/'+$scope.index+"/_search?pretty -d'\n"+
+          angular.toJson(JSON.parse(request.toString()),true)+
+        "'
", + } + } + + 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) + } + + + +}); \ No newline at end of file From a608b80970be41e2035ad02d185311c5346d70ac Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 15 May 2013 16:09:36 -0700 Subject: [PATCH 2/2] switch field input to text input if no fields list exists --- panels/derivequeries/module.html | 7 +++++-- panels/derivequeries/module.js | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/panels/derivequeries/module.html b/panels/derivequeries/module.html index 5599433836e..7dc663bc914 100644 --- a/panels/derivequeries/module.html +++ b/panels/derivequeries/module.html @@ -13,8 +13,11 @@ - - + + + + + diff --git a/panels/derivequeries/module.js b/panels/derivequeries/module.js index 3f7a6b8fe9c..f49f66bb48b 100644 --- a/panels/derivequeries/module.js +++ b/panels/derivequeries/module.js @@ -30,6 +30,7 @@ angular.module('kibana.derivequeries', []) query : "*", group : "default", field : '_type', + fields : [], spyable : true, size : 5, exclude : [] @@ -38,9 +39,7 @@ angular.module('kibana.derivequeries', []) $scope.init = function() { eventBus.register($scope,'fields', function(event, fields) { - $scope.panel.sort = _.clone(fields.sort); - $scope.fields = fields.all, - $scope.active = _.clone(fields.active); + $scope.panel.fields = fields.all; }); eventBus.register($scope,'time', function(event,time){set_time(time)}); eventBus.register($scope,'query', function(event, query) {