Explorar o código

Merge branch 'master' of github.com:torkelo/grafana-private into pro

Torkel Ödegaard %!s(int64=11) %!d(string=hai) anos
pai
achega
373118c5ee

+ 11 - 2
CHANGELOG.md

@@ -1,4 +1,13 @@
-# 1.9.0 (unreleased)
+# 1.9.1 (unreleased)
+
+**Enhancements**
+- [Issue #1028](https://github.com/grafana/grafana/issues/1028). Graph: New legend option ``hideEmtpy`` to hide series with only null values
+
+**Fixes**
+- [Issue #1199](https://github.com/grafana/grafana/issues/1199). Graph: fix for series tooltip when one series is hidden/disabled
+- [Issue #1207](https://github.com/grafana/grafana/issues/1207). Graphite: movingAverage / movingMedian parameter type impovement, now handles int and interval parameter
+
+# 1.9.0 (2014-12-02)
 
 **Enhancements**
 - [Issue #1130](https://github.com/grafana/grafana/issues/1130). SinglestatPanel: Added null point handling, and value to text mapping
@@ -16,7 +25,7 @@
 
 # 1.9.0-rc1 (2014-11-17)
 
-**UI Improvements*
+**UI Improvements**
 - [Issue #770](https://github.com/grafana/grafana/issues/770). UI: Panel dropdown menu replaced with a new panel menu
 
 **Graph**

+ 2 - 2
latest.json

@@ -1,4 +1,4 @@
 {
-	"version": "1.9.0-rc1",
-	"url": "http://grafanarel.s3.amazonaws.com/grafana-1.9.0-rc1.tar.gz"
+	"version": "1.9.0",
+	"url": "http://grafanarel.s3.amazonaws.com/grafana-1.9.0.tar.gz"
 }

+ 1 - 1
package.json

@@ -4,7 +4,7 @@
     "company": "Coding Instinct AB"
   },
   "name": "grafana",
-  "version": "1.9.0-rc1",
+  "version": "1.9.0",
   "repository": {
     "type": "git",
     "url": "http://github.com/torkelo/grafana.git"

+ 6 - 0
src/app/controllers/graphiteTarget.js

@@ -162,6 +162,11 @@ function (angular, _, config, gfunc, Parser) {
             return new MetricSegment({ value: segment.text, expandable: segment.expandable });
           });
 
+          if ($scope.altSegments.length === 0) {
+            return;
+          }
+
+          // add template variables
           _.each(templateSrv.variables, function(variable) {
             $scope.altSegments.unshift(new MetricSegment({
               type: 'template',
@@ -170,6 +175,7 @@ function (angular, _, config, gfunc, Parser) {
             }));
           });
 
+          // add wildcard option
           $scope.altSegments.unshift(new MetricSegment('*'));
         })
         .then(null, function(err) {

+ 4 - 2
src/app/features/panellinkeditor/module.html

@@ -1,6 +1,6 @@
 <div class="editor-row">
   <div class="section">
-		<h5>Drilldown / detail link<tip>These links appear in the dropdown menu in the panel menu</tip></h5>
+		<h5>Drilldown / detail link<tip>These links appear in the dropdown menu in the panel menu. </tip></h5>
 
 		<div class="grafana-target" ng-repeat="link in panel.links"j>
 			<div class="grafana-target-inner">
@@ -32,7 +32,9 @@
 						<input type="text" ng-model="link.url" class="input-large grafana-target-segment-input">
 					</li>
 
-					<li class="grafana-target-segment">params</li>
+					<li class="grafana-target-segment">params
+						<tip>Use var-variableName=value to pass templating variables.</tip>
+					</li>
 					<li>
 						<input type="text" ng-model="link.params" class="input-medium grafana-target-segment-input">
 					</li>

+ 1 - 0
src/app/panels/graph/axisEditor.html

@@ -44,6 +44,7 @@
 		<editor-opt-bool text="Values" model="panel.legend.values" change="render()"></editor-opt-bool>
 		<editor-opt-bool text="Table" model="panel.legend.alignAsTable" change="render()"></editor-opt-bool>
 		<editor-opt-bool text="Right side" model="panel.legend.rightSide" change="render()"></editor-opt-bool>
+		<editor-opt-bool text="Hide empty" model="panel.legend.hideEmpty" tip="Hides series with only null values" change="render()"></editor-opt-bool>
 	</div>
 
   <div class="section" ng-if="panel.legend.values">

+ 3 - 3
src/app/panels/graph/graph.tooltip.js

@@ -99,9 +99,9 @@ function ($) {
             lasthoverIndex = hoverIndex;
           }
 
-          results.push({ value: value, hoverIndex: newhoverIndex });
+          results.push({ value: value, hoverIndex: newhoverIndex, series: series });
         } else {
-          results.push({ value: value, hoverIndex: hoverIndex });
+          results.push({ value: value, hoverIndex: hoverIndex, series: series });
         }
       }
 
@@ -149,8 +149,8 @@ function ($) {
         timestamp = dashboard.formatDate(seriesHoverInfo.time);
 
         for (i = 0; i < seriesHoverInfo.length; i++) {
-          series = seriesList[i];
           hoverInfo = seriesHoverInfo[i];
+          series = hoverInfo.series;
           value = series.formatValue(hoverInfo.value);
 
           seriesHtml += '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">';

+ 6 - 0
src/app/panels/graph/legend.js

@@ -125,6 +125,12 @@ function (angular, app, _, kbn, $) {
 
           for (i = 0; i < seriesList.length; i++) {
             var series = seriesList[i];
+
+            // ignore empty series
+            if (panel.legend.hideEmpty && series.allIsNull) {
+              continue;
+            }
+
             var html = '<div class="graph-legend-series';
             if (series.yaxis === 2) { html += ' pull-right'; }
             if (scope.hiddenSeries[series.alias]) { html += ' graph-legend-series-hidden'; }

+ 3 - 8
src/app/panels/singlestat/module.js

@@ -128,10 +128,6 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
     };
 
     $scope.getDecimalsForValue = function(value) {
-      var opts = {};
-      if (value === 0 || value === 1) {
-        return { decimals: 0, scaledDecimals: 0 };
-      }
 
       var delta = value / 2;
       var dec = -Math.floor(Math.log(delta) / Math.LN10);
@@ -157,13 +153,12 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
 
       size *= magn;
 
-      if (opts.minTickSize != null && size < opts.minTickSize) {
-        size = opts.minTickSize;
-      }
+      // reduce starting decimals if not needed
+      if (Math.floor(value) === value) { dec = 0; }
 
       var result = {};
       result.decimals = Math.max(0, dec);
-      result.scaledDecimals = result.decimals - Math.floor(Math.log(size) / Math.LN11) + 2;
+      result.scaledDecimals = result.decimals - Math.floor(Math.log(size) / Math.LN10) + 2;
 
       return result;
     };

+ 1 - 1
src/app/panels/singlestat/singleStatPanel.js

@@ -55,7 +55,7 @@ function (angular, app, _, $) {
 
         function getColorForValue(value) {
           for (var i = data.thresholds.length - 1; i >= 0 ; i--) {
-            if (value > data.thresholds[i]) {
+            if (value >= data.thresholds[i]) {
               return data.colorMap[i];
             }
           }

+ 1 - 1
src/app/partials/dashboard.html

@@ -21,7 +21,7 @@
 								<i bs-tooltip="'Expand row'" data-placement="right" class="icon-caret-left pointer" ></i>
 							</span>
 						</div>
-						<span class="row-text pointer" ng-click="toggle_row(row)" ng-bind="row.title"></span>
+						<div class="row-text pointer" ng-click="toggle_row(row)" ng-bind="row.title"></div>
 					</div>
 					<div class="row-open" ng-show="!row.collapse">
 						<div class='row-tab bgSuccess dropdown' ng-show="row.editable">

+ 1 - 1
src/app/partials/graphite/editor.html

@@ -102,7 +102,7 @@
 					<input type="text"
 								class="input-mini grafana-target-segment-input"
 								ng-model="panel.cacheTimeout"
-								bs-tooltip="'Graphite parameter to overwride memcache default timeout (unit is seconds)'"
+								bs-tooltip="'Graphite parameter to override memcache default timeout (unit is seconds)'"
 								data-placement="right"
 								spellcheck='false'
 								placeholder="60">

+ 2 - 12
src/app/services/dashboard/dashboardSrv.js

@@ -117,18 +117,8 @@ function (angular, $, kbn, _, moment) {
       var newPanel = angular.copy(panel);
       newPanel.id = this.getNextPanelId();
 
-      while(rowIndex < this.rows.length) {
-        var currentRow = this.rows[rowIndex];
-        if (this.rowSpan(currentRow) <= 9) {
-          currentRow.panels.push(newPanel);
-          return;
-        }
-        rowIndex++;
-      }
-
-      var newRow = angular.copy(row);
-      newRow.panels = [newPanel];
-      this.rows.push(newRow);
+      var currentRow = this.rows[rowIndex];
+      currentRow.panels.push(newPanel);
     };
 
     p.formatDate = function(date, format) {

+ 31 - 6
src/app/services/graphite/gfunc.js

@@ -1,7 +1,8 @@
 define([
-  'lodash'
+  'lodash',
+  'jquery'
 ],
-function (_) {
+function (_, $) {
   'use strict';
 
   var index = [];
@@ -157,7 +158,12 @@ function (_) {
   addFuncDef({
     name: 'sumSeriesWithWildcards',
     category: categories.Combine,
-    params: [{ name: "node", type: "int" }],
+    params: [
+      { name: "node", type: "int" },
+      { name: "node", type: "int", optional: true },
+      { name: "node", type: "int", optional: true },
+      { name: "node", type: "int", optional: true }
+    ],
     defaultParams: [3]
   });
 
@@ -328,6 +334,11 @@ function (_) {
     defaultParams: [10]
   });
 
+  addFuncDef({
+    name: 'offsetToZero',
+    category: categories.Transform,
+  });
+
   addFuncDef({
     name: 'transformNull',
     category: categories.Transform,
@@ -501,15 +512,15 @@ function (_) {
   addFuncDef({
     name: 'movingAverage',
     category: categories.Filter,
-    params: [{ name: "window size", type: "int" }],
+    params: [{ name: "windowSize", type: "int_or_interval", options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
     defaultParams: [10]
   });
 
   addFuncDef({
     name: 'movingMedian',
     category: categories.Filter,
-    params: [{ name: "windowSize", type: "select", options: ['1min', '5min', '15min', '30min', '1hour'] }],
-    defaultParams: ['1min']
+    params: [{ name: "windowSize", type: "int_or_interval", options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
+    defaultParams: ['5']
   });
 
   addFuncDef({
@@ -561,6 +572,17 @@ function (_) {
     defaultParams: [5]
   });
 
+  addFuncDef({
+    name: 'useSeriesAbove',
+    category: categories.Filter,
+    params: [
+      { name: "value", type: "int" },
+      { name: "search", type: "string" },
+      { name: "replace", type: "string" }
+    ],
+    defaultParams: [0, 'search', 'replace']
+  });
+
   _.each(categories, function(funcList, catName) {
     categories[catName] = _.sortBy(funcList, 'name');
   });
@@ -584,6 +606,9 @@ function (_) {
       if (paramType === 'int' || paramType === 'value_or_series' || paramType === 'boolean') {
         return value;
       }
+      else if (paramType === 'int_or_interval' && $.isNumeric(value)) {
+        return value;
+      }
 
       return "'" + value + "'";
 

+ 4 - 1
src/app/services/graphite/graphiteDatasource.js

@@ -24,6 +24,7 @@ function (angular, _, $, config, kbn, moment) {
       this.supportMetrics = true;
       this.annotationEditorSrc = 'app/partials/graphite/annotation_editor.html';
       this.cacheTimeout = datasource.cacheTimeout;
+      this.withCredentials = datasource.withCredentials;
     }
 
     GraphiteDatasource.prototype.query = function(options) {
@@ -209,8 +210,10 @@ function (angular, _, $, config, kbn, moment) {
     };
 
     GraphiteDatasource.prototype.doGraphiteRequest = function(options) {
-      if (this.basicAuth) {
+      if (this.basicAuth || this.withCredentials) {
         options.withCredentials = true;
+      }
+      if (this.basicAuth) {
         options.headers = options.headers || {};
         options.headers.Authorization = 'Basic ' + this.basicAuth;
       }

+ 8 - 1
src/app/services/graphite/parser.js

@@ -67,9 +67,16 @@ define([
       }
 
       if (this.match('identifier') || this.match('number')) {
+        // hack to handle float numbers in metric segments
+        var parts = this.consumeToken().value.split('.');
+        if (parts.length === 2) {
+          this.tokens.splice(this.index, 0, { type: '.' });
+          this.tokens.splice(this.index + 1, 0, { type: 'number', value: parts[1] });
+        }
+
         return {
           type: 'segment',
-          value: this.consumeToken().value
+          value: parts[0]
         };
       }
 

+ 3 - 2
src/css/less/grafana.less

@@ -438,6 +438,9 @@ select.grafana-target-segment-input {
   max-height: 600px;
   overflow: hidden;
   line-height: 14px;
+  a {
+    color: @tooltipLinkColor;
+  }
 }
 
 .grafana-tooltip hr {
@@ -445,8 +448,6 @@ select.grafana-target-segment-input {
  color: #c8c8c8;
  margin: 0px;
  border-bottom:0px solid #c8c8c8;
- /*height:0px;
- background-color: rgb(58, 57, 57);*/
 }
 
 .tooltip.in {

+ 1 - 0
src/css/less/overrides.less

@@ -181,6 +181,7 @@ form input.ng-invalid {
   font-size: 0.9em;
   text-align: center;
   line-height: 31px;
+  height: 31px;
 }
 
 .row-close {

+ 1 - 0
src/css/less/variables.dark.less

@@ -280,6 +280,7 @@
 @tooltipBackground:       rgb(58, 57, 57);
 @tooltipArrowWidth:       5px;
 @tooltipArrowColor:       @tooltipBackground;
+@tooltipLinkColor:        @linkColor;
 
 @popoverBackground:       @heroUnitBackground;
 @popoverArrowWidth:       10px;

+ 1 - 0
src/css/less/variables.light.less

@@ -289,6 +289,7 @@
 @tooltipBackground:       #000;
 @tooltipArrowWidth:       5px;
 @tooltipArrowColor:       @tooltipBackground;
+@tooltipLinkColor:        darken(@white,11%);
 
 @popoverBackground:       @white;
 @popoverArrowWidth:       15px;

+ 0 - 10
src/test/specs/dashboardSrv-specs.js

@@ -70,16 +70,6 @@ define([
       expect(dashboard.rows[0].panels[1].id).to.be(11);
     });
 
-    it('duplicate should add row if there is no space left', function() {
-      var panel = { span: 12, attr: '123' };
-      dashboard.rows = [{ panels: [panel] }];
-      dashboard.duplicatePanel(panel, dashboard.rows[0]);
-
-      expect(dashboard.rows[0].panels[0].span).to.be(12);
-      expect(dashboard.rows[0].panels.length).to.be(1);
-      expect(dashboard.rows[1].panels[0].attr).to.be('123');
-    });
-
   });
 
   describe('when creating dashboard with editable false', function() {

+ 12 - 0
src/test/specs/gfunc-specs.js

@@ -46,6 +46,18 @@ define([
       expect(func.render('hello')).to.equal("scaleToSeconds(hello, 1)");
     });
 
+    it('should handle int or interval params with number', function() {
+      var func = gfunc.createFuncInstance('movingMedian');
+      func.params[0] = '5';
+      expect(func.render('hello')).to.equal("movingMedian(hello, 5)");
+    });
+
+    it('should handle int or interval params with interval string', function() {
+      var func = gfunc.createFuncInstance('movingMedian');
+      func.params[0] = '5min';
+      expect(func.render('hello')).to.equal("movingMedian(hello, '5min')");
+    });
+
     it('should handle metric param and int param and string param', function() {
       var func = gfunc.createFuncInstance('groupByNode');
       func.params[0] = 5;

+ 16 - 0
src/test/specs/graphiteTargetCtrl-specs.js

@@ -136,6 +136,22 @@ define([
       });
     });
 
+    describe('when getting altSegments and metricFindQuery retuns empty array', function() {
+      beforeEach(function() {
+        ctx.scope.target.target = 'test.count';
+        ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
+        ctx.scope.init();
+        ctx.scope.getAltSegments(1);
+        ctx.scope.$digest();
+        ctx.scope.$parent = { get_data: sinon.spy() };
+      });
+
+      it('should have no segments', function() {
+        expect(ctx.scope.altSegments.length).to.be(0);
+      });
+
+    });
+
     describe('targetChanged', function() {
       beforeEach(function() {
         ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));

+ 8 - 0
src/test/specs/parser-specs.js

@@ -165,6 +165,14 @@ define([
       expect(rootNode.params[1].value).to.be('#B');
     });
 
+    it('should parse metric expression with ip number segments', function() {
+      var parser = new Parser('5.10.123.5');
+      var rootNode = parser.getAst();
+      expect(rootNode.segments[0].value).to.be('5');
+      expect(rootNode.segments[1].value).to.be('10');
+      expect(rootNode.segments[2].value).to.be('123');
+      expect(rootNode.segments[3].value).to.be('5');
+    });
 
   });
 

+ 0 - 1
src/vendor/angular/angular-dragdrop.js

@@ -39,7 +39,6 @@ angular.module("ang-drag-drop",[])
                 element.attr("draggable", false);
 
                 attrs.$observe("uiDraggable", function (newValue) {
-                  console.log(newValue);
                     if(newValue){
                         element.attr("draggable", newValue);
                     }