elasticResponse.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. define([
  2. "lodash",
  3. "./queryDef"
  4. ],
  5. function (_, queryDef) {
  6. 'use strict';
  7. function ElasticResponse(targets, response) {
  8. this.targets = targets;
  9. this.response = response;
  10. }
  11. // This is quite complex
  12. // neeed to recurise down the nested buckets to build series
  13. ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, level, props) {
  14. var value, metric, i, y, bucket, aggDef, esAgg, newSeries;
  15. aggDef = target.bucketAggs[level];
  16. esAgg = aggs[aggDef.id];
  17. if (level < target.bucketAggs.length - 1) {
  18. for (i = 0; i < esAgg.buckets.length; i++) {
  19. bucket = esAgg.buckets[i];
  20. props = _.clone(props);
  21. props[aggDef.field] = bucket.key;
  22. this.processBuckets(bucket, target, seriesList, level+1, props);
  23. }
  24. return;
  25. }
  26. for (y = 0; y < target.metrics.length; y++) {
  27. metric = target.metrics[y];
  28. switch(metric.type) {
  29. case 'count': {
  30. newSeries = { datapoints: [], metric: 'count', props: props};
  31. for (i = 0; i < esAgg.buckets.length; i++) {
  32. bucket = esAgg.buckets[i];
  33. value = bucket.doc_count;
  34. newSeries.datapoints.push([value, bucket.key]);
  35. }
  36. seriesList.push(newSeries);
  37. break;
  38. }
  39. case 'percentiles': {
  40. if (esAgg.buckets.length === 0) {
  41. break;
  42. }
  43. var firstBucket = esAgg.buckets[0];
  44. var percentiles = firstBucket[metric.id].values;
  45. for (var percentileName in percentiles) {
  46. newSeries = {datapoints: [], metric: 'p' + percentileName, props: props, field: metric.field};
  47. for (i = 0; i < esAgg.buckets.length; i++) {
  48. bucket = esAgg.buckets[i];
  49. var values = bucket[metric.id].values;
  50. newSeries.datapoints.push([values[percentileName], bucket.key]);
  51. }
  52. seriesList.push(newSeries);
  53. }
  54. break;
  55. }
  56. case 'extended_stats': {
  57. for (var statName in metric.meta) {
  58. if (!metric.meta[statName]) {
  59. continue;
  60. }
  61. newSeries = {datapoints: [], metric: statName, props: props, field: metric.field};
  62. for (i = 0; i < esAgg.buckets.length; i++) {
  63. bucket = esAgg.buckets[i];
  64. var stats = bucket[metric.id];
  65. // add stats that are in nested obj to top level obj
  66. stats.std_deviation_bounds_upper = stats.std_deviation_bounds.upper;
  67. stats.std_deviation_bounds_lower = stats.std_deviation_bounds.lower;
  68. newSeries.datapoints.push([stats[statName], bucket.key]);
  69. }
  70. seriesList.push(newSeries);
  71. }
  72. break;
  73. }
  74. default: {
  75. newSeries = { datapoints: [], metric: metric.type, field: metric.field, props: props};
  76. for (i = 0; i < esAgg.buckets.length; i++) {
  77. bucket = esAgg.buckets[i];
  78. value = bucket[metric.id].value;
  79. newSeries.datapoints.push([value, bucket.key]);
  80. }
  81. seriesList.push(newSeries);
  82. break;
  83. }
  84. }
  85. }
  86. };
  87. ElasticResponse.prototype._getMetricName = function(metric) {
  88. var metricDef = _.findWhere(queryDef.metricAggTypes, {value: metric});
  89. if (!metricDef) {
  90. metricDef = _.findWhere(queryDef.extendedStats, {value: metric});
  91. }
  92. return metricDef ? metricDef.text : metric;
  93. };
  94. ElasticResponse.prototype._getSeriesName = function(series, target, metricTypeCount) {
  95. var metricName = this._getMetricName(series.metric);
  96. if (target.alias) {
  97. var regex = /\{\{([\s\S]+?)\}\}/g;
  98. return target.alias.replace(regex, function(match, g1, g2) {
  99. var group = g1 || g2;
  100. if (group.indexOf('term ') === 0) { return series.props[group.substring(5)]; }
  101. if (series.props[group]) { return series.props[group]; }
  102. if (group === 'metric') { return metricName; }
  103. if (group === 'field') { return series.field; }
  104. return match;
  105. });
  106. }
  107. if (series.field) {
  108. metricName += ' ' + series.field;
  109. }
  110. var propKeys = _.keys(series.props);
  111. if (propKeys.length === 0) {
  112. return metricName;
  113. }
  114. var name = '';
  115. for (var propName in series.props) {
  116. name += series.props[propName] + ' ';
  117. }
  118. if (metricTypeCount === 1) {
  119. return name.trim();
  120. }
  121. return name.trim() + ' ' + metricName;
  122. };
  123. ElasticResponse.prototype.nameSeries = function(seriesList, target) {
  124. var metricTypeCount = _.uniq(_.pluck(seriesList, 'metric')).length;
  125. var fieldNameCount = _.uniq(_.pluck(seriesList, 'field')).length;
  126. for (var i = 0; i < seriesList.length; i++) {
  127. var series = seriesList[i];
  128. series.target = this._getSeriesName(series, target, metricTypeCount, fieldNameCount);
  129. }
  130. };
  131. ElasticResponse.prototype.getTimeSeries = function() {
  132. var seriesList = [];
  133. for (var i = 0; i < this.response.responses.length; i++) {
  134. var response = this.response.responses[i];
  135. if (response.error) {
  136. throw { message: response.error };
  137. }
  138. var aggregations = response.aggregations;
  139. var target = this.targets[i];
  140. var tmpSeriesList = [];
  141. this.processBuckets(aggregations, target, tmpSeriesList, 0, {});
  142. this.nameSeries(tmpSeriesList, target);
  143. for (var y = 0; y < tmpSeriesList.length; y++) {
  144. seriesList.push(tmpSeriesList[y]);
  145. }
  146. }
  147. return { data: seriesList };
  148. };
  149. return ElasticResponse;
  150. });