Browse Source

prometheus: initial heatmap support

Alexander Zobnin 7 years ago
parent
commit
efa869bb89

+ 63 - 3
public/app/plugins/datasource/prometheus/datasource.ts

@@ -106,17 +106,29 @@ export class PrometheusDatasource {
     });
     });
 
 
     return this.$q.all(allQueryPromise).then(responseList => {
     return this.$q.all(allQueryPromise).then(responseList => {
-      var result = [];
+      let result = [];
 
 
       _.each(responseList, (response, index) => {
       _.each(responseList, (response, index) => {
         if (response.status === 'error') {
         if (response.status === 'error') {
           throw response.error;
           throw response.error;
         }
         }
 
 
+        let prometheusResult = response.data.data.result;
+
         if (activeTargets[index].format === 'table') {
         if (activeTargets[index].format === 'table') {
-          result.push(self.transformMetricDataToTable(response.data.data.result, responseList.length, index));
+          result.push(self.transformMetricDataToTable(prometheusResult, responseList.length, index));
+        } else if (activeTargets[index].format === 'heatmap') {
+          let seriesList = [];
+          prometheusResult.sort(sortSeriesByLabel);
+          for (let metricData of prometheusResult) {
+            seriesList.push(
+              self.transformMetricData(metricData, activeTargets[index], start, end, queries[index].step)
+            );
+          }
+          seriesList = self.transformToHistogramOverTime(seriesList);
+          result.push(...seriesList);
         } else {
         } else {
-          for (let metricData of response.data.data.result) {
+          for (let metricData of prometheusResult) {
             if (response.data.data.resultType === 'matrix') {
             if (response.data.data.resultType === 'matrix') {
               result.push(self.transformMetricData(metricData, activeTargets[index], start, end, queries[index].step));
               result.push(self.transformMetricData(metricData, activeTargets[index], start, end, queries[index].step));
             } else if (response.data.data.resultType === 'vector') {
             } else if (response.data.data.resultType === 'vector') {
@@ -378,6 +390,24 @@ export class PrometheusDatasource {
     return { target: metricLabel, datapoints: dps };
     return { target: metricLabel, datapoints: dps };
   }
   }
 
 
+  transformToHistogramOverTime(seriesList, options?) {
+    /*      t1 = timestamp1, t2 = timestamp2 etc.
+            t1  t2  t3          t1  t2  t3
+    le10    10  10  0     =>    10  10  0
+    le20    20  10  30    =>    10  0   30
+    le30    30  10  35    =>    10  0   5
+    */
+    for (let i = seriesList.length - 1; i > 0; i--) {
+      let topSeries = seriesList[i].datapoints;
+      let bottomSeries = seriesList[i - 1].datapoints;
+      for (let j = 0; j < topSeries.length; j++) {
+        topSeries[j][0] -= bottomSeries[j][0];
+      }
+    }
+
+    return seriesList;
+  }
+
   createMetricLabel(labelData, options) {
   createMetricLabel(labelData, options) {
     if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) {
     if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) {
       return this.getOriginalMetricName(labelData);
       return this.getOriginalMetricName(labelData);
@@ -412,3 +442,33 @@ export class PrometheusDatasource {
     return Math.ceil(date.valueOf() / 1000);
     return Math.ceil(date.valueOf() / 1000);
   }
   }
 }
 }
+
+function sortSeriesByLabel(s1, s2) {
+  let le1, le2;
+
+  try {
+    // fail if not integer. might happen with bad queries
+    le1 = parseHistogramLabel(s1.metric.le);
+    le2 = parseHistogramLabel(s2.metric.le);
+  } catch (err) {
+    console.log(err);
+    return 0;
+  }
+
+  if (le1 > le2) {
+    return 1;
+  }
+
+  if (le1 < le2) {
+    return -1;
+  }
+
+  return 0;
+}
+
+function parseHistogramLabel(le: string): number {
+  if (le === '+Inf') {
+    return +Infinity;
+  }
+  return parseInt(le);
+}

+ 8 - 1
public/app/plugins/datasource/prometheus/query_ctrl.ts

@@ -31,7 +31,11 @@ class PrometheusQueryCtrl extends QueryCtrl {
       return { factor: f, label: '1/' + f };
       return { factor: f, label: '1/' + f };
     });
     });
 
 
-    this.formats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
+    this.formats = [
+      { text: 'Time series', value: 'time_series' },
+      { text: 'Table', value: 'table' },
+      { text: 'Heatmap', value: 'heatmap' },
+    ];
 
 
     this.instant = false;
     this.instant = false;
 
 
@@ -45,7 +49,10 @@ class PrometheusQueryCtrl extends QueryCtrl {
   getDefaultFormat() {
   getDefaultFormat() {
     if (this.panelCtrl.panel.type === 'table') {
     if (this.panelCtrl.panel.type === 'table') {
       return 'table';
       return 'table';
+    } else if (this.panelCtrl.panel.type === 'heatmap') {
+      return 'heatmap';
     }
     }
+
     return 'time_series';
     return 'time_series';
   }
   }