Browse Source

heatmap: use buckets from histogram with 'tsbuckets' mode

Alexander Zobnin 7 years ago
parent
commit
97c54e6956

+ 8 - 8
public/app/plugins/panel/heatmap/heatmap_ctrl.ts

@@ -5,12 +5,7 @@ import TimeSeries from 'app/core/time_series2';
 import { axesEditor } from './axes_editor';
 import { heatmapDisplayEditor } from './display_editor';
 import rendering from './rendering';
-import {
-  convertToHeatMap,
-  convertToCards,
-  elasticHistogramToHeatmap,
-  calculateBucketSize,
-} from './heatmap_data_converter';
+import { convertToHeatMap, convertToCards, histogramToHeatmap, calculateBucketSize } from './heatmap_data_converter';
 
 let X_BUCKET_NUMBER_DEFAULT = 30;
 let Y_BUCKET_NUMBER_DEFAULT = 10;
@@ -139,12 +134,13 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
       return;
     }
 
-    let xBucketSize, yBucketSize, heatmapStats, bucketsData;
+    let xBucketSize, yBucketSize, heatmapStats, bucketsData, tsBuckets;
     let logBase = this.panel.yAxis.logBase;
 
     if (this.panel.dataFormat === 'tsbuckets') {
       heatmapStats = this.parseHistogramSeries(this.series);
-      bucketsData = elasticHistogramToHeatmap(this.series);
+      bucketsData = histogramToHeatmap(this.series);
+      tsBuckets = _.map(this.series, 'label');
 
       // Calculate bucket size based on ES heatmap data
       let xBucketBoundSet = _.map(_.keys(bucketsData), key => Number(key));
@@ -210,6 +206,10 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
       cards: cards,
       cardStats: cardStats,
     };
+
+    if (tsBuckets) {
+      this.data.tsBuckets = tsBuckets;
+    }
   }
 
   onDataReceived(dataList) {

+ 40 - 0
public/app/plugins/panel/heatmap/heatmap_data_converter.ts

@@ -51,6 +51,45 @@ function elasticHistogramToHeatmap(seriesList) {
   return heatmap;
 }
 
+function histogramToHeatmap(seriesList) {
+  let heatmap = {};
+
+  for (let i = 0; i < seriesList.length; i++) {
+    let series = seriesList[i];
+    let bound = i;
+    if (isNaN(bound)) {
+      return heatmap;
+    }
+
+    for (let point of series.datapoints) {
+      let count = point[VALUE_INDEX];
+      let time = point[TIME_INDEX];
+
+      if (!_.isNumber(count)) {
+        continue;
+      }
+
+      let bucket = heatmap[time];
+      if (!bucket) {
+        bucket = heatmap[time] = { x: time, buckets: {} };
+      }
+
+      bucket.buckets[bound] = {
+        y: bound,
+        count: count,
+        bounds: {
+          top: null,
+          bottom: bound,
+        },
+        values: [],
+        points: [],
+      };
+    }
+  }
+
+  return heatmap;
+}
+
 /**
  * Convert buckets into linear array of "cards" - objects, represented heatmap elements.
  * @param  {Object} buckets
@@ -433,6 +472,7 @@ function emptyXOR(foo: any, bar: any): boolean {
 
 export {
   convertToHeatMap,
+  histogramToHeatmap,
   elasticHistogramToHeatmap,
   convertToCards,
   mergeZeroBuckets,

+ 44 - 4
public/app/plugins/panel/heatmap/rendering.ts

@@ -296,6 +296,42 @@ export default function link(scope, elem, attrs, ctrl) {
       .remove();
   }
 
+  function addYAxisFromBuckets() {
+    const tsBuckets = data.tsBuckets;
+
+    scope.yScale = yScale = d3
+      .scaleLinear()
+      .domain([0, tsBuckets.length - 1])
+      .range([chartHeight, 0]);
+
+    const tick_values = _.map(tsBuckets, (b, i) => i);
+    const tickFormatter = val => tsBuckets[val];
+
+    let yAxis = d3
+      .axisLeft(yScale)
+      .tickValues(tick_values)
+      .tickFormat(tickFormatter)
+      .tickSizeInner(0 - width)
+      .tickSizeOuter(0)
+      .tickPadding(Y_AXIS_TICK_PADDING);
+
+    heatmap
+      .append('g')
+      .attr('class', 'axis axis-y')
+      .call(yAxis);
+
+    // Calculate Y axis width first, then move axis into visible area
+    const posY = margin.top;
+    const posX = getYAxisWidth(heatmap) + Y_AXIS_TICK_PADDING;
+    heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
+
+    // Remove vertical line in the right of axis labels (called domain in d3)
+    heatmap
+      .select('.axis-y')
+      .select('.domain')
+      .remove();
+  }
+
   // Adjust data range to log base
   function adjustLogRange(min, max, logBase) {
     let y_min, y_max;
@@ -362,10 +398,14 @@ export default function link(scope, elem, attrs, ctrl) {
     chartTop = margin.top;
     chartBottom = chartTop + chartHeight;
 
-    if (panel.yAxis.logBase === 1) {
-      addYAxis();
+    if (panel.dataFormat === 'tsbuckets') {
+      addYAxisFromBuckets();
     } else {
-      addLogYAxis();
+      if (panel.yAxis.logBase === 1) {
+        addYAxis();
+      } else {
+        addLogYAxis();
+      }
     }
 
     yAxisWidth = getYAxisWidth(heatmap) + Y_AXIS_TICK_PADDING;
@@ -414,7 +454,7 @@ export default function link(scope, elem, attrs, ctrl) {
     addHeatmapCanvas();
     addAxes();
 
-    if (panel.yAxis.logBase !== 1) {
+    if (panel.yAxis.logBase !== 1 && panel.dataFormat !== 'tsbuckets') {
       let log_base = panel.yAxis.logBase;
       let domain = yScale.domain();
       let tick_values = logScaleTickValues(domain, log_base);