Просмотр исходного кода

Added derivative option and scale option to histogram, reorganized histogram config

Rashid Khan 12 лет назад
Родитель
Сommit
40e55f0d0d

+ 36 - 65
src/app/panels/histogram/editor.html

@@ -1,74 +1,45 @@
-  <div class="row-fluid">
-    <div class="span2">
-      <label class="small">Mode</label>
+<div class="editor-row">
+  <div class="section">
+    <h5>Values</h5>
+    <div class="editor-option">
+      <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>
     </div>
-    <div class="span2">
-      <label class="small">Time Field</label>
-        <input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.time_field">
-    </div>
-    <div class="span2" ng-show="panel.mode != 'count'">
-      <label class="small">Value Field</label>
-        <input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.value_field">
-    </div>
-    <div class="span3" ng-show="panel.mode != 'count'">
-      <label class="small">Note</label><small> In <strong>{{panel.mode}}</strong> mode the configured field <strong>must</strong> be a numeric type</small>
+    <div class="editor-option" ng-show="panel.mode != 'count'">
+      <label class="small">Value Field <tip>This field must contain a numeric value</tip></label>
+        <input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-large" ng-model="panel.value_field">
     </div>
   </div>
-  <h5>Chart Settings</h5>
-  <div class="row-fluid" style="text-align:center;margin-bottom:10px;">
-    <div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div>
-    <div class="span1"> <label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines"></div>
-    <div class="span1"> <label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points"></div>
-    <div class="span1"> <label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack"></div>
-    <div class="span1" ng-show="panel.stack">
-      <label style="white-space:nowrap" class="small">Percent <tip>Stack as a percentage of total</tip></label>
-      <input type="checkbox"  ng-model="panel.percentage" ng-checked="panel.percentage">
+  <div class="section">
+    <h5>Transform Series</h5>
+    <div class="editor-option" ng-show="panel.mode != 'count'">
+      <label class="small">Scale</label>
+        <input type="text" class="input-mini" ng-model="panel.scale">
     </div>
-    <div class="span1"> <label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend"></div>
-    <div class="span1"> <label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
-    <div class="span1"> <label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
-    <div class="span2" ng-show="panel.lines">
-      <label class="small">Line Fill</label>
-      <select class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
-    </div>
-    <div class="span2" ng-show="panel.lines">
-      <label class="small">Line Width</label>
-      <select class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
+    <div class="editor-option">
+      <label class="small">Derivative <tip>Plot the change per interval in the series</tip></label><input type="checkbox" ng-model="panel.derivative" ng-checked="panel.derivative" ng-change="set_refresh(true)">
     </div>
   </div>
-  <div class="row-fluid">
-    <div class="span2">
-      <label class="small">Time correction</label>
-      <select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
-    </div>
-    <div class="span1"> <label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive"></div>
-    <div class="span2">
-      <label class="small">Zoom Links</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
-    </div>
-        <div class="span2">
-      <label class="small">View Options</label><input type="checkbox" ng-model="panel.options" ng-checked="panel.options" />
-    </div>
-    <div class="span2">
-      <label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
-    </div>
-    <div class="span2" ng-show='panel.auto_int'>
-      <label class="small">Resolution <tip>Shoot for this many data points, rounding to sane intervals</tip></label>
-      <input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
-    </div>
-    <div class="span2" ng-hide='panel.auto_int'>
-      <label class="small">Interval <tip>Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</tip></label>
-      <input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
-    </div>
+</div>
+<h5>Time Options</h5>
+<div class="editor-row">
+  <div class="editor-option">
+    <label class="small">Time Field</label>
+      <input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.time_field">
   </div>
-  <h5>Tooltip Settings</h5>
-  <div class="row-fluid" style="margin-bottom:10px;">
-    <div class="span3">
-      <label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
-      <select class="input-medium" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
-    </div>
-    <div class="span3">
-      <label class="small">Display Query <tip>If an alias is set, it will be shown in the tooltip. If not, should it show the query?</tip></label>
-      <input type="checkbox" ng-model="panel.tooltip.query_as_alias" />
-    </div>
+  <div class="editor-option">
+    <label class="small">Time correction</label>
+    <select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
+  </div>
+  <div class="editor-option">
+    <label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
+  </div>
+  <div class="editor-option" ng-show='panel.auto_int'>
+    <label class="small">Resolution <tip>Shoot for this many data points, rounding to sane intervals</tip></label>
+    <input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
+  </div>
+  <div class="editor-option" ng-hide='panel.auto_int'>
+    <label class="small">Interval <tip>Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</tip></label>
+    <input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
   </div>
+</div>

+ 1 - 1
src/app/panels/histogram/module.html

@@ -47,7 +47,7 @@
       <i class='icon-circle' ng-style="{color: series.info.color}"></i>
       <span class='small histogram-legend-item'>{{series.info.alias}} ({{series.hits}})</span>
     </span>
-    <span ng-show="panel.legend" class="small"><span ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong>{{panel.interval}}</strong> | (<strong>{{hits}}</strong> hits)</span>
+    <span ng-show="panel.legend" class="small"><span ng-show="panel.derivative">change in </span><span class="strong" ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong>{{panel.interval}}</strong> | (<strong>{{hits}}</strong> hits)</span>
   </div>
   <form class="form-inline bordered histogram-options" ng-show="options">
     <span>

+ 44 - 6
src/app/panels/histogram/module.js

@@ -61,10 +61,14 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
         }
       ],
       editorTabs : [
+        {
+          title:'Style',
+          src:'app/panels/histogram/styleEditor.html'
+        },
         {
           title:'Queries',
           src:'app/partials/querySelect.html'
-        }
+        },
       ],
       status  : "Stable",
       description : "A bucketed time series chart of the current query or queries. Uses the "+
@@ -98,11 +102,14 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
       'x-axis'    : true,
       'y-axis'    : true,
       percentage  : false,
+      zerofill    : true,
       interactive : true,
       options     : true,
+      derivative  : false,
+      scale       : 1,
       tooltip     : {
         value_type: 'cumulative',
-        query_as_alias: false
+        query_as_alias: true
       }
     };
 
@@ -115,6 +122,10 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
         $scope.get_data();
       });
 
+      // Always show the query if an alias isn't set. Users can set an alias if the query is too
+      // long
+      $scope.panel.tooltip.query_as_alias = true;
+
       $scope.get_data();
 
     };
@@ -249,12 +260,13 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
             // we need to initialize the data variable on the first run,
             // and when we are working on the first segment of the data.
             if(_.isUndefined($scope.data[i]) || segment === 0) {
-              time_series = new timeSeries.ZeroFilled({
+              var tsOpts = {
                 interval: _interval,
                 start_date: _range && _range.from,
                 end_date: _range && _range.to,
-                fill_style: 'minimal'
-              });
+                fill_style: $scope.panel.derivative ? 'null' : 'minimal'
+              };
+              time_series = new timeSeries.ZeroFilled(tsOpts);
               hits = 0;
             } else {
               time_series = $scope.data[i].time_series;
@@ -354,6 +366,24 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
           render_panel();
         });
 
+        var scale = function(series,factor) {
+          return _.map(series,function(p) {
+            return [p[0],p[1]*factor];
+          });
+        };
+
+        var derivative = function(series) {
+          return _.map(series, function(p,i) {
+            var _v;
+            if(i === 0 || p[1] === null) {
+              _v = [p[0],null];
+            } else {
+              _v = series[i-1][1] === null ? [p[0],null] : [p[0],p[1]-(series[i-1][1])];
+            }
+            return _v;
+          });
+        };
+
         // Function for rendering panel
         function render_panel() {
           // IE doesn't work without this
@@ -441,8 +471,16 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
               }), true);
             }
 
+
             for (var i = 0; i < scope.data.length; i++) {
-              scope.data[i].data = scope.data[i].time_series.getFlotPairs(required_times);
+              var _d = scope.data[i].time_series.getFlotPairs(required_times);
+              if(scope.panel.derivative) {
+                _d = derivative(_d);
+              }
+              if(scope.panel.scale !== 1) {
+                _d = scale(_d,scope.panel.scale);
+              }
+              scope.data[i].data = _d;
             }
 
             scope.plot = $.plot(elem, scope.data, options);

+ 58 - 0
src/app/panels/histogram/styleEditor.html

@@ -0,0 +1,58 @@
+<div class="editor-row">
+  <div class="section">
+    <h5>Chart Options</h5>
+    <div class="editor-option">
+      <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars">
+    </div>
+    <div class="editor-option">
+      <label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines">
+    </div>
+    <div class="editor-option">
+      <label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points">
+    </div>
+    <div class="editor-option">
+      <label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive">
+    </div>
+    <div class="editor-option">
+      <label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
+    <div class="editor-option">
+      <label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
+    <div class="editor-option" ng-show="panel.lines">
+      <label class="small">Line Fill</label>
+      <select class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
+    </div>
+    <div class="editor-option" ng-show="panel.lines">
+      <label class="small">Line Width</label>
+      <select class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
+    </div>
+  </div>
+  <div class="section">
+    <h5>Multiple Series</h5>
+    <div class="editor-option">
+      <label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack">
+    </div>
+    <div class="editor-option" ng-show="panel.stack">
+      <label style="white-space:nowrap" class="small">Percent <tip>Stack as a percentage of total</tip></label>
+      <input type="checkbox"  ng-model="panel.percentage" ng-checked="panel.percentage">
+    </div>
+    <div class="editor-option" ng-show="panel.stack">
+      <label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
+      <select class="input-small" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
+    </div>
+  </div>
+</div>
+
+<div class="editor-row">
+  <div class="section">
+    <h5>Header<h5>
+    <div class="editor-option">
+      <label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend">
+    </div>
+    <div class="editor-option">
+      <label class="small">Zoom</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
+    </div>
+    <div class="editor-option">
+      <label class="small">View</label><input type="checkbox" ng-model="panel.options" ng-checked="panel.options" />
+    </div>
+  </div>
+</div>

+ 29 - 13
src/app/panels/histogram/timeSeries.js

@@ -88,7 +88,7 @@ function (_, Interval) {
    * return the rows in the format:
    * [ [time, value], [time, value], ... ]
    *
-   * Heavy lifting is done by _get(Min|All)FlotPairs()
+   * Heavy lifting is done by _get(Min|Default|All)FlotPairs()
    * @param  {array} required_times  An array of timestamps that must be in the resulting pairs
    * @return {array}
    */
@@ -99,8 +99,8 @@ function (_, Interval) {
 
     if(this.opts.fill_style === 'all') {
       strategy = this._getAllFlotPairs;
-    } else if(this.opts.fill_style = 'default') {
-      strategy = this._getDefaultFlotPairs;
+    } else if(this.opts.fill_style === 'null') {
+      strategy = this._getNullFlotPairs;
     } else {
       strategy = this._getMinFlotPairs;
     }
@@ -114,13 +114,15 @@ function (_, Interval) {
 
     // if the first or last pair is inside either the start or end time,
     // add those times to the series with null values so the graph will stretch to contain them.
-    // Not sure this is required with flot 0.8.1's min/max params. Might be harmful?
+    // Removing, flot 0.8.1's max/min params satisfy this
+    /*
     if (this.start_time && (pairs.length === 0 || pairs[0][0] > this.start_time)) {
       pairs.unshift([this.start_time, null]);
     }
     if (this.end_time && (pairs.length === 0 || pairs[pairs.length - 1][0] < this.end_time)) {
       pairs.push([this.end_time, null]);
     }
+    */
 
     return pairs;
   };
@@ -144,7 +146,7 @@ function (_, Interval) {
     }
 
     // add the current time
-    result.push([ time, this._data[time] || 0 ]);
+    result.push([ time, this._data[time] || 0]);
 
     // check for next measurement
     if (times.length > i) {
@@ -179,17 +181,31 @@ function (_, Interval) {
 
   /**
    * ** called as a reduce stragegy in getFlotPairs() **
-   * Does no zero filling
+   * Same as min, but fills with nulls
    * @return {array}  An array of points to plot with flot
    */
-  ts.ZeroFilled.prototype._getDefaultFlotPairs = function (result, time, i, times) {
-    var next, expected_next;
+  ts.ZeroFilled.prototype._getNullFlotPairs = function (result, time, i, times) {
+    var next, expected_next, prev, expected_prev;
 
-    result.push([ times[i], this._data[times[i]] || 0 ]);
-    next = times[i + 1];
-    expected_next = this.interval.after(time);
-    for(; times.length > i && next > expected_next; expected_next = this.interval.after(expected_next)) {
-      result.push([expected_next, 0]);
+    // check for previous measurement
+    if (i > 0) {
+      prev = times[i - 1];
+      expected_prev = this.interval.before(time);
+      if (prev < expected_prev) {
+        result.push([expected_prev, null]);
+      }
+    }
+
+    // add the current time
+    result.push([ time, this._data[time] || null]);
+
+    // check for next measurement
+    if (times.length > i) {
+      next = times[i + 1];
+      expected_next = this.interval.after(time);
+      if (next > expected_next) {
+        result.push([expected_next, null]);
+      }
     }
 
     return result;

+ 0 - 10
src/app/panels/query/module.js

@@ -114,14 +114,4 @@ define([
 
   });
 
-  module.directive('queryConfig', function() {
-    return {
-      restrict: 'A',
-      template: '<div></div>',
-      link: function(scope, elem) {
-        console.log(elem);
-      }
-    };
-  });
-
 });

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/css/bootstrap.dark.min.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/css/bootstrap.light.min.css


+ 17 - 0
src/vendor/bootstrap/less/overrides.less

@@ -1,3 +1,20 @@
+div.editor-row {
+  vertical-align: top;
+}
+div.editor-row div.section {
+  margin-right: 20px;
+  vertical-align: top;
+  display: inline-block;
+}
+div.editor-option {
+  vertical-align: top;
+  display: inline-block;
+  margin-right: 10px;
+}
+div.editor-option label {
+  display: block;
+}
+
 #events {
   font-size: 12px;
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов