module.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*jshint globalstrict:true */
  2. /*global angular:true */
  3. /*
  4. ## Trends
  5. Shows how queries are moving from a specified time ago
  6. ### Parameters
  7. * style :: A hash of css styles
  8. * arrangement :: How should I arrange the query results? 'horizontal' or 'vertical'
  9. * ago :: Date math formatted time to look back
  10. ### Group Events
  11. #### Sends
  12. * get_time :: On panel initialization get time range to query
  13. #### Receives
  14. * time :: An object containing the time range to use and the index(es) to query
  15. * query :: An Array of queries, even if its only one
  16. */
  17. 'use strict';
  18. angular.module('kibana.trends', [])
  19. .controller('trends', function($scope, kbnIndex, querySrv, dashboard, filterSrv) {
  20. // Set and populate defaults
  21. var _d = {
  22. status : "Beta",
  23. query : ["*"],
  24. group : "default",
  25. style : { "font-size": '14pt'},
  26. ago : '1d',
  27. arrangement : 'vertical',
  28. };
  29. _.defaults($scope.panel,_d);
  30. $scope.init = function () {
  31. $scope.hits = 0;
  32. $scope.$on('refresh',function(){$scope.get_data();});
  33. $scope.get_data();
  34. };
  35. $scope.get_data = function(segment,query_id) {
  36. delete $scope.panel.error;
  37. $scope.panel.loading = true;
  38. // Make sure we have everything for the request to complete
  39. if(dashboard.indices.length === 0) {
  40. return;
  41. } else {
  42. $scope.index = segment > 0 ? $scope.index : dashboard.indices;
  43. }
  44. // Determine a time field
  45. var timeField = _.uniq(_.pluck(filterSrv.getByType('time'),'field'));
  46. if(timeField.length > 1) {
  47. $scope.panel.error = "Time field must be consistent amongst time filters";
  48. return;
  49. } else if(timeField.length === 0) {
  50. $scope.panel.error = "A time filter must exist for this panel to function";
  51. return;
  52. } else {
  53. timeField = timeField[0];
  54. }
  55. $scope.time = filterSrv.timeRange('min');
  56. $scope.old_time = {
  57. from : new Date($scope.time.from.getTime() - kbn.interval_to_seconds($scope.panel.ago)*1000),
  58. to : new Date($scope.time.to.getTime() - kbn.interval_to_seconds($scope.panel.ago)*1000)
  59. };
  60. var _segment = _.isUndefined(segment) ? 0 : segment;
  61. var request = $scope.ejs.Request();
  62. var _ids_without_time = _.difference(filterSrv.ids,filterSrv.idsByType('time'));
  63. // Build the question part of the query
  64. _.each(querySrv.ids, function(id) {
  65. var q = $scope.ejs.FilteredQuery(
  66. querySrv.getEjsObj(id),
  67. filterSrv.getBoolFilter(_ids_without_time).must(
  68. $scope.ejs.RangeFilter(timeField)
  69. .from($scope.time.from)
  70. .to($scope.time.to)
  71. ));
  72. request = request
  73. .facet($scope.ejs.QueryFacet(id)
  74. .query(q)
  75. ).size(0);
  76. });
  77. // And again for the old time period
  78. _.each(querySrv.ids, function(id) {
  79. var q = $scope.ejs.FilteredQuery(
  80. querySrv.getEjsObj(id),
  81. filterSrv.getBoolFilter(_ids_without_time).must(
  82. $scope.ejs.RangeFilter(timeField)
  83. .from($scope.old_time.from)
  84. .to($scope.old_time.to)
  85. ));
  86. request = request
  87. .facet($scope.ejs.QueryFacet("old_"+id)
  88. .query(q)
  89. ).size(0);
  90. });
  91. // TODO: Spy for trend panel
  92. //$scope.populate_modal(request);
  93. // If we're on the first segment we need to get our indices
  94. if (_segment === 0) {
  95. kbnIndex.indices(
  96. $scope.old_time.from,
  97. $scope.old_time.to,
  98. dashboard.current.index.pattern,
  99. dashboard.current.index.interval
  100. ).then(function (p) {
  101. $scope.index = _.union(p,$scope.index);
  102. request = request.indices($scope.index[_segment]);
  103. process_results(request.doSearch(),_segment,query_id);
  104. });
  105. } else {
  106. process_results(request.indices($scope.index[_segment]).doSearch(),_segment,query_id);
  107. }
  108. };
  109. // Populate scope when we have results
  110. var process_results = function(results,_segment,query_id) {
  111. results.then(function(results) {
  112. $scope.panel.loading = false;
  113. if(_segment === 0) {
  114. $scope.hits = {};
  115. $scope.data = [];
  116. query_id = $scope.query_id = new Date().getTime();
  117. }
  118. // Check for error and abort if found
  119. if(!(_.isUndefined(results.error))) {
  120. $scope.panel.error = $scope.parse_error(results.error);
  121. return;
  122. }
  123. // Convert facet ids to numbers
  124. var facetIds = _.map(_.keys(results.facets),function(k){if(!isNaN(k)){return parseInt(k, 10);}});
  125. // Make sure we're still on the same query/queries
  126. if($scope.query_id === query_id &&
  127. _.intersection(facetIds,querySrv.ids).length === querySrv.ids.length
  128. ) {
  129. var i = 0;
  130. _.each(querySrv.ids, function(id) {
  131. var v = results.facets[id];
  132. var n = results.facets[id].count;
  133. var o = results.facets['old_'+id].count;
  134. var hits = {
  135. new : _.isUndefined($scope.data[i]) || _segment === 0 ? n : $scope.data[i].hits.new+n,
  136. old : _.isUndefined($scope.data[i]) || _segment === 0 ? o : $scope.data[i].hits.old+o
  137. };
  138. $scope.hits.new += n;
  139. $scope.hits.old += o;
  140. var percent = percentage(hits.old,hits.new) == null ?
  141. '?' : Math.round(percentage(hits.old,hits.new)*100)/100;
  142. // Create series
  143. $scope.data[i] = {
  144. info: querySrv.list[id],
  145. hits: {
  146. new : hits.new,
  147. old : hits.old
  148. },
  149. percent: percent
  150. };
  151. i++;
  152. });
  153. $scope.$emit('render');
  154. if(_segment < $scope.index.length-1) {
  155. $scope.get_data(_segment+1,query_id);
  156. } else {
  157. $scope.trends = $scope.data;
  158. }
  159. }
  160. });
  161. };
  162. function percentage(x,y) {
  163. return x === 0 ? null : 100*(y-x)/x;
  164. }
  165. $scope.set_refresh = function (state) {
  166. $scope.refresh = state;
  167. };
  168. $scope.close_edit = function() {
  169. if($scope.refresh) {
  170. $scope.get_data();
  171. }
  172. $scope.refresh = false;
  173. $scope.$emit('render');
  174. };
  175. });