Pārlūkot izejas kodu

Graph panel: initial elastic raw document format support, issue #5812.

Alexander Zobnin 9 gadi atpakaļ
vecāks
revīzija
06af566f3f

+ 4 - 2
public/app/plugins/panel/graph/graph.js

@@ -234,7 +234,8 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
               series.data = [
                 [i + 1, series.stats[panel.xaxis.seriesValue]]
               ];
-            } else if (panel.xaxis.mode === 'table') {
+            } else if (panel.xaxis.mode === 'table' ||
+                       panel.xaxis.mode === 'elastic') {
               series.data = [];
               for (var j = 0; j < series.datapoints.length; j++) {
                 var dataIndex = i * series.datapoints.length + j;
@@ -264,7 +265,8 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
 
             addXSeriesAxis(options);
 
-          } else if (panel.xaxis.mode === 'table') {
+          } else if (panel.xaxis.mode === 'table' ||
+                     panel.xaxis.mode === 'elastic') {
             if (data.length) {
               options.series.bars.barWidth = 0.7;
               options.series.bars.align = 'center';

+ 86 - 4
public/app/plugins/panel/graph/module.ts

@@ -148,7 +148,8 @@ class GraphCtrl extends MetricsPanelCtrl {
     this.xAxisModes = {
       'Time': 'time',
       'Series': 'series',
-      'Table': 'table'
+      'Table': 'table',
+      'Elastic Raw Doc': 'elastic'
     };
 
     this.xAxisSeriesValues = ['min', 'max', 'avg', 'current', 'total'];
@@ -195,7 +196,7 @@ class GraphCtrl extends MetricsPanelCtrl {
         // Table panel uses only first enabled tagret, so we can use dataList[0]
         // for table data representation
         dataList.splice(1, dataList.length - 1);
-        this.xAxisColumns = _.map(dataList[0].columns, function(column, index) {
+        this.xAxisColumns = _.map(dataList[0].columns, (column, index) => {
           return {
             text: column.text,
             index: index
@@ -209,6 +210,14 @@ class GraphCtrl extends MetricsPanelCtrl {
       }
 
       dataHandler = this.tableHandler;
+    } else if (this.panel.xaxis.mode === 'elastic') {
+      if (dataList.length) {
+        dataList.splice(1, dataList.length - 1);
+        var point = _.first(dataList[0].datapoints);
+        this.xAxisColumns = getFieldsFromESDoc(point);
+      }
+
+      dataHandler = this.esRawDocHandler;
     } else {
       dataHandler = this.seriesHandler;
     }
@@ -250,13 +259,12 @@ class GraphCtrl extends MetricsPanelCtrl {
       this.panel.tooltip.msResolution = this.panel.tooltip.msResolution || series.isMsResolutionNeeded();
     }
 
-
     return series;
   }
 
   tableHandler(seriesData, index) {
     var xColumnIndex = Number(this.panel.xaxis.columnIndex);
-    var valueColumnIndex = this.panel.xaxis.valueColumnIndex;
+    var valueColumnIndex = Number(this.panel.xaxis.valueColumnIndex);
     var datapoints = _.map(seriesData.rows, (row) => {
       var value = valueColumnIndex ? row[valueColumnIndex] : _.last(row);
       return [
@@ -288,6 +296,46 @@ class GraphCtrl extends MetricsPanelCtrl {
       this.panel.tooltip.msResolution = this.panel.tooltip.msResolution || series.isMsResolutionNeeded();
     }
 
+    return series;
+  }
+
+  esRawDocHandler(seriesData, index) {
+    let xField = this.panel.xaxis.esField;
+    let valueField = this.panel.xaxis.esValueField;
+    let datapoints = _.map(seriesData.datapoints, (doc) => {
+      return [
+        pluckDeep(doc, valueField),  // Y value
+        pluckDeep(doc, xField)       // X value
+      ];
+    });
+
+    // Remove empty points
+    datapoints = _.filter(datapoints, (point) => {
+      return point[0] !== undefined;
+    });
+
+    var alias = valueField;
+
+    var colorIndex = index % this.colors.length;
+    var color = this.panel.aliasColors[alias] || this.colors[colorIndex];
+
+    var series = new TimeSeries({
+      datapoints: datapoints,
+      alias: alias,
+      color: color,
+      unit: seriesData.unit,
+    });
+
+    if (datapoints && datapoints.length > 0) {
+      var last = moment.utc(datapoints[datapoints.length - 1][1]);
+      var from = moment.utc(this.range.from);
+      if (last - from < -10000) {
+        this.datapointsOutside = true;
+      }
+
+      this.datapointsCount += datapoints.length;
+      this.panel.tooltip.msResolution = this.panel.tooltip.msResolution || series.isMsResolutionNeeded();
+    }
 
     return series;
   }
@@ -396,4 +444,38 @@ class GraphCtrl extends MetricsPanelCtrl {
   }
 }
 
+function getFieldsFromESDoc(doc) {
+  let fields = [];
+  let fieldNameParts = [];
+
+  function getFieldsRecursive(obj) {
+    _.forEach(obj, (value, key) => {
+      if (_.isObject(value)) {
+        fieldNameParts.push(key);
+        getFieldsRecursive(value);
+      } else {
+        let field = fieldNameParts.concat(key).join('.');
+        fields.push(field);
+      }
+    });
+    fieldNameParts.pop();
+  }
+
+  getFieldsRecursive(doc);
+  return fields;
+}
+
+function pluckDeep(obj: any, property: string) {
+  let propertyParts = property.split('.');
+  let value = obj;
+  for (let i = 0; i < propertyParts.length; ++i) {
+    if (value[propertyParts[i]]) {
+      value = value[propertyParts[i]];
+    } else {
+      return undefined;
+    }
+  }
+  return value;
+}
+
 export {GraphCtrl, GraphCtrl as PanelCtrl}

+ 25 - 0
public/app/plugins/panel/graph/tab_axes.html

@@ -52,6 +52,7 @@
 			</div>
 		</div>
 
+		<!-- Series mode -->
 		<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'series'">
 			<label class="gf-form-label width-5">Value</label>
 			<div class="gf-form-select-wrapper max-width-15">
@@ -63,6 +64,7 @@
 			</div>
 		</div>
 
+		<!-- Table mode -->
 		<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'table'">
 			<label class="gf-form-label width-5">Column</label>
 			<div class="gf-form-select-wrapper max-width-15">
@@ -84,6 +86,29 @@
 				</select>
 			</div>
 		</div>
+
+		<!-- Elastic Raw Document mode -->
+		<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'elastic'">
+			<label class="gf-form-label width-5">Column</label>
+			<div class="gf-form-select-wrapper max-width-15">
+				<select class="gf-form-input"
+					ng-model="ctrl.panel.xaxis.esField"
+					ng-options="field for field in ctrl.xAxisColumns"
+					ng-change="ctrl.refresh()">
+				</select>
+			</div>
+		</div>
+
+		<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'elastic'">
+			<label class="gf-form-label width-5">Value</label>
+			<div class="gf-form-select-wrapper max-width-15">
+				<select class="gf-form-input"
+					ng-model="ctrl.panel.xaxis.esValueField"
+					ng-options="field for field in ctrl.xAxisColumns"
+					ng-change="ctrl.refresh()">
+				</select>
+			</div>
+		</div>
 	</div>
 
   <div class="section gf-form-group">