Skip to content

Commit

Permalink
Re-implement histogram panel using Aggregation API, and add uniq mode
Browse files Browse the repository at this point in the history
to search cardinality.
  • Loading branch information
chenryn committed Nov 19, 2014
1 parent 8763cad commit 6cb4d28
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/app/panels/histogram/editor.html
Expand Up @@ -3,7 +3,7 @@
<h5>Values</h5> <h5>Values</h5>
<div class="editor-option"> <div class="editor-option">
<label class="small">Chart value</label> <label class="small">Chart value</label>
<select ng-change="set_refresh(true)" class="input-small" ng-model="panel.mode" ng-options="f for f in ['count','min','mean','max','total']"></select> <select ng-change="set_refresh(true)" class="input-small" ng-model="panel.mode" ng-options="f for f in ['count','uniq','min','mean','max','total']"></select>
</div> </div>
<div class="editor-option" ng-show="panel.mode != 'count'"> <div class="editor-option" ng-show="panel.mode != 'count'">
<label class="small">Value Field <tip>This field must contain a numeric value</tip></label> <label class="small">Value Field <tip>This field must contain a numeric value</tip></label>
Expand Down
58 changes: 33 additions & 25 deletions src/app/panels/histogram/module.js
Expand Up @@ -354,20 +354,26 @@ function (angular, app, $, _, kbn, moment, timeSeries, numeral) {
filterSrv.getBoolFilter(filterSrv.ids()) filterSrv.getBoolFilter(filterSrv.ids())
); );


var facet = $scope.ejs.DateHistogramFacet(q.id); var aggr = $scope.ejs.DateHistogramAggregation(q.id);


if($scope.panel.mode === 'count') { if($scope.panel.mode === 'count') {
facet = facet.field($scope.panel.time_field).global(true); aggr = aggr.field($scope.panel.time_field);
} else if($scope.panel.mode === 'uniq') {
aggr = aggr.field($scope.panel.time_field).agg($scope.ejs.CardinalityAggregation(q.id).field($scope.panel.value_field));
} else { } else {
if(_.isNull($scope.panel.value_field)) { if(_.isNull($scope.panel.value_field)) {
$scope.panel.error = "In " + $scope.panel.mode + " mode a field must be specified"; $scope.panel.error = "In " + $scope.panel.mode + " mode a field must be specified";
return; return;
} }
facet = facet.keyField($scope.panel.time_field).valueField($scope.panel.value_field).global(true); aggr = aggr.field($scope.panel.time_field).agg($scope.ejs.StatsAggregation(q.id).field($scope.panel.value_field));
} }
facet = facet.interval(_interval).facetFilter($scope.ejs.QueryFilter(query)); request = request.agg(
request = request.facet(facet) $scope.ejs.GlobalAggregation(q.id).agg(
.size($scope.panel.annotate.enable ? $scope.panel.annotate.size : 0); $scope.ejs.FilterAggregation(q.id).filter($scope.ejs.QueryFilter(query)).agg(
aggr.interval(_interval)
)
)
).size($scope.panel.annotate.enable ? $scope.panel.annotate.size : 0);
}); });


if($scope.panel.annotate.enable) { if($scope.panel.annotate.enable) {
Expand Down Expand Up @@ -419,7 +425,7 @@ function (angular, app, $, _, kbn, moment, timeSeries, numeral) {
counters; // Stores the bucketed hit counts. counters; // Stores the bucketed hit counts.


_.each(queries, function(q) { _.each(queries, function(q) {
var query_results = results.facets[q.id]; var query_results = results.aggregations[q.id][q.id][q.id];
// we need to initialize the data variable on the first run, // we need to initialize the data variable on the first run,
// and when we are working on the first segment of the data. // and when we are working on the first segment of the data.
if(_.isUndefined(data[i]) || segment === 0) { if(_.isUndefined(data[i]) || segment === 0) {
Expand All @@ -439,38 +445,40 @@ function (angular, app, $, _, kbn, moment, timeSeries, numeral) {
} }


// push each entry into the time series, while incrementing counters // push each entry into the time series, while incrementing counters
_.each(query_results.entries, function(entry) { _.each(query_results.buckets, function(entry) {
var value; var value;


hits += entry.count; // The series level hits counter hits += entry.doc_count; // The series level hits counter
$scope.hits += entry.count; // Entire dataset level hits counter $scope.hits += entry.doc_count; // Entire dataset level hits counter
counters[entry.time] = (counters[entry.time] || 0) + entry.count; counters[entry.key] = (counters[entry.key] || 0) + entry.doc_count;


if($scope.panel.mode === 'count') { if($scope.panel.mode === 'count') {
value = (time_series._data[entry.time] || 0) + entry.count; value = (time_series._data[entry.key] || 0) + entry.doc_count;
} else if ($scope.panel.mode === 'uniq') {
value = (time_series._data[entry.key] || 0) + entry[q.id].value;
} else if ($scope.panel.mode === 'mean') { } else if ($scope.panel.mode === 'mean') {
// Compute the ongoing mean by // Compute the ongoing mean by
// multiplying the existing mean by the existing hits // multiplying the existing mean by the existing hits
// plus the new mean multiplied by the new hits // plus the new mean multiplied by the new hits
// divided by the total hits // divided by the total hits
value = (((time_series._data[entry.time] || 0)*(counters[entry.time]-entry.count)) + value = (((time_series._data[entry.key] || 0)*(counters[entry.key]-entry.doc_count)) +
entry.mean*entry.count)/(counters[entry.time]); entry[q.id].avg*entry.doc_count)/(counters[entry.key]);
} else if ($scope.panel.mode === 'min'){ } else if ($scope.panel.mode === 'min'){
if(_.isUndefined(time_series._data[entry.time])) { if(_.isUndefined(time_series._data[entry.key])) {
value = entry.min; value = entry[q.id].min;
} else { } else {
value = time_series._data[entry.time] < entry.min ? time_series._data[entry.time] : entry.min; value = time_series._data[entry.key] < entry[q.id].min ? time_series._data[entry.key] : entry[q.id].min;
} }
} else if ($scope.panel.mode === 'max'){ } else if ($scope.panel.mode === 'max'){
if(_.isUndefined(time_series._data[entry.time])) { if(_.isUndefined(time_series._data[entry.key])) {
value = entry.max; value = entry[q.id].max;
} else { } else {
value = time_series._data[entry.time] > entry.max ? time_series._data[entry.time] : entry.max; value = time_series._data[entry.key] > entry[q.id].max ? time_series._data[entry.key] : entry[q.id].max;
} }
} else if ($scope.panel.mode === 'total'){ } else if ($scope.panel.mode === 'total'){
value = (time_series._data[entry.time] || 0) + entry.total; value = (time_series._data[entry.key] || 0) + entry[q.id].sum;
} }
time_series.addValue(entry.time, value); time_series.addValue(entry.key, value);
}); });


$scope.legend[i] = {query:q,hits:hits}; $scope.legend[i] = {query:q,hits:hits};
Expand All @@ -482,10 +490,10 @@ function (angular, app, $, _, kbn, moment, timeSeries, numeral) {
counters: counters counters: counters
}; };


var monitorTitle = $scope.panel.queries.check[i] +' for query: '+ ( queries[i].alias || queries[i].query ); var monitorTitle = $scope.panel.queries.check[q.id] +' for query: '+ ( q.alias || q.query );
if ($scope.panel.queries.check[i] === 'threshold') { if ($scope.panel.queries.check[q.id] === 'threshold') {
monitor.check(data[i].counters, monitorTitle, $scope.panel.queries.threshold[i]); monitor.check(data[i].counters, monitorTitle, $scope.panel.queries.threshold[i]);
} else if ($scope.panel.queries.check[i] === 'anomaly') { } else if ($scope.panel.queries.check[q.id] === 'anomaly') {
monitor.check(data[i].counters, monitorTitle); monitor.check(data[i].counters, monitorTitle);
}; };


Expand Down

0 comments on commit 6cb4d28

Please sign in to comment.