Pārlūkot izejas kodu

Merge branch 'master' into alerting_definitions

bergquist 9 gadi atpakaļ
vecāks
revīzija
35c73902da

+ 6 - 1
CHANGELOG.md

@@ -1,11 +1,16 @@
+# 3.0.0 stable (unreleased)
+
+* **Templating**: Fixed issue with new data source variable not persisting current selected value, fixes [#4934](https://github.com/grafana/grafana/issues/4934)
+
 # 3.0.0-beta7 (2016-05-02)
 # 3.0.0-beta7 (2016-05-02)
 
 
 ### Bug fixes
 ### Bug fixes
 * **Dashboard title**: Fixed max dashboard title width (media query) for large screens,  fixes [#4859](https://github.com/grafana/grafana/issues/4859)
 * **Dashboard title**: Fixed max dashboard title width (media query) for large screens,  fixes [#4859](https://github.com/grafana/grafana/issues/4859)
 * **Annotations**: Fixed issue with entering annotation edit view, fixes [#4857](https://github.com/grafana/grafana/issues/4857)
 * **Annotations**: Fixed issue with entering annotation edit view, fixes [#4857](https://github.com/grafana/grafana/issues/4857)
 * **Remove query**: Fixed issue with removing query for data sources without collapsable query editors, fixes [#4856](https://github.com/grafana/grafana/issues/4856)
 * **Remove query**: Fixed issue with removing query for data sources without collapsable query editors, fixes [#4856](https://github.com/grafana/grafana/issues/4856)
-* **Graphite PNG*: Fixed issue graphite png rendering option, fixes [#4864](https://github.com/grafana/grafana/issues/4864)
+* **Graphite PNG**: Fixed issue graphite png rendering option, fixes [#4864](https://github.com/grafana/grafana/issues/4864)
 * **InfluxDB**: Fixed issue missing plus group by iconn, fixes [#4862](https://github.com/grafana/grafana/issues/4862)
 * **InfluxDB**: Fixed issue missing plus group by iconn, fixes [#4862](https://github.com/grafana/grafana/issues/4862)
+* **Graph**: Fixes missing line mode for thresholds, fixes [#4902](https://github.com/grafana/grafana/pull/4902)
 
 
 ### Enhancements
 ### Enhancements
 * **InfluxDB**: Added new functions moving_average and difference to query editor, closes [#4698](https://github.com/grafana/grafana/issues/4698)
 * **InfluxDB**: Added new functions moving_average and difference to query editor, closes [#4698](https://github.com/grafana/grafana/issues/4698)

+ 21 - 3
README.md

@@ -78,7 +78,7 @@ the latest master builds [here](http://grafana.org/download/builds)
 ### Dependencies
 ### Dependencies
 
 
 - Go 1.5
 - Go 1.5
-- NodeJS
+- NodeJS v0.12.0
 - [Godep](https://github.com/tools/godep)
 - [Godep](https://github.com/tools/godep)
 
 
 ### Get Code
 ### Get Code
@@ -87,8 +87,19 @@ the latest master builds [here](http://grafana.org/download/builds)
 go get github.com/grafana/grafana
 go get github.com/grafana/grafana
 ```
 ```
 
 
+Since imports of dependencies use the absolute path github.com/grafana/grafana within the $GOPATH,
+you will need to put your version of the code in $GOPATH/src/github.com/grafana/grafana to be able
+to develop and build grafana on a cloned repository. To do so, you can clone your forked repository
+directly to $GOPATH/src/github.com/grafana or you can create a symbolic link from your version
+of the code to $GOPATH/src/github.com/grafana/grafana. The last options makes it possible to change
+easily the grafana repository you want to build.
+```bash
+go get github.com/*your_account*/grafana
+mkdir $GOPATH/src/github.com/grafana
+ln -s  github.com/*your_account*/grafana $GOPATH/src/github.com/grafana/grafana
+```
+
 ### Building the backend
 ### Building the backend
-Replace X.Y.Z by actual version number.
 ```bash
 ```bash
 cd $GOPATH/src/github.com/grafana/grafana
 cd $GOPATH/src/github.com/grafana/grafana
 go run build.go setup            (only needed once to install godep)
 go run build.go setup            (only needed once to install godep)
@@ -98,7 +109,7 @@ go run build.go build
 
 
 ### Building frontend assets
 ### Building frontend assets
 
 
-To build less to css for the frontend you will need a recent version of of node (v0.12.0),
+To build less to css for the frontend you will need a recent version of of **node (v0.12.0)**,
 npm (v2.5.0) and grunt (v0.4.5). Run the following:
 npm (v2.5.0) and grunt (v0.4.5). Run the following:
 
 
 ```bash
 ```bash
@@ -106,6 +117,13 @@ npm install
 npm run build
 npm run build
 ```
 ```
 
 
+To build the frontend assets only on changes:
+
+```bash
+sudo npm install -g grunt-cli # to do only once to install grunt command line interface
+grunt watch
+```
+
 ### Recompile backend on source change
 ### Recompile backend on source change
 To rebuild on source change (requires that you executed godep restore)
 To rebuild on source change (requires that you executed godep restore)
 ```bash
 ```bash

+ 1 - 1
build.go

@@ -136,7 +136,7 @@ func readVersionFromPackageJson() {
 			// add timestamp to iteration
 			// add timestamp to iteration
 			linuxPackageIteration = fmt.Sprintf("%s%v", linuxPackageIteration, time.Now().Unix())
 			linuxPackageIteration = fmt.Sprintf("%s%v", linuxPackageIteration, time.Now().Unix())
 		}
 		}
-		log.Println(fmt.Sprintf("teration %v", linuxPackageIteration))
+		log.Println(fmt.Sprintf("Iteration %v", linuxPackageIteration))
 	}
 	}
 }
 }
 
 

+ 2 - 2
conf/defaults.ini

@@ -241,14 +241,14 @@ templates_pattern = emails/*.html
 
 
 #################################### Logging ##########################
 #################################### Logging ##########################
 [log]
 [log]
-# Either "console", "file", default is "console"
+# Either "console", "file", "syslog". Default is console and  file
 # Use comma to separate multiple modes, e.g. "console, file"
 # Use comma to separate multiple modes, e.g. "console, file"
 mode = console, file
 mode = console, file
 
 
 # Buffer length of channel, keep it as it is if you don't know what it is.
 # Buffer length of channel, keep it as it is if you don't know what it is.
 buffer_len = 10000
 buffer_len = 10000
 
 
-# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
+# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Info"
 level = Info
 level = Info
 
 
 # For "console" mode only
 # For "console" mode only

+ 2 - 2
conf/sample.ini

@@ -223,14 +223,14 @@ check_for_updates = true
 
 
 #################################### Logging ##########################
 #################################### Logging ##########################
 [log]
 [log]
-# Either "console", "file", default is "console"
+# Either "console", "file", "syslog". Default is console and  file
 # Use comma to separate multiple modes, e.g. "console, file"
 # Use comma to separate multiple modes, e.g. "console, file"
 ;mode = console, file
 ;mode = console, file
 
 
 # Buffer length of channel, keep it as it is if you don't know what it is.
 # Buffer length of channel, keep it as it is if you don't know what it is.
 ;buffer_len = 10000
 ;buffer_len = 10000
 
 
-# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
+# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Info"
 ;level = Info
 ;level = Info
 
 
 # For "console" mode only
 # For "console" mode only

+ 1 - 1
docs/sources/datasources/kairosdb.md

@@ -30,7 +30,7 @@ Access | Proxy = access via Grafana backend, Direct = access directory from brow
 ## Query editor
 ## Query editor
 Open a graph in edit mode by click the title.
 Open a graph in edit mode by click the title.
 
 
-![](/img/v2/kairos_query_editor.png)
+![](/img/v2/kairos_query_editor.jpg)
 
 
 For details on KairosDB metric queries checkout the official.
 For details on KairosDB metric queries checkout the official.
 - [Query Metrics - KairosDB 0.9.4 documentation](http://kairosdb.github.io/kairosdocs/restapi/QueryMetrics.html).
 - [Query Metrics - KairosDB 0.9.4 documentation](http://kairosdb.github.io/kairosdocs/restapi/QueryMetrics.html).

+ 1 - 1
pkg/api/cloudwatch/metrics.go

@@ -86,7 +86,7 @@ func init() {
 		"AWS/EC2":              {"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
 		"AWS/EC2":              {"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
 		"AWS/ELB":              {"LoadBalancerName", "AvailabilityZone"},
 		"AWS/ELB":              {"LoadBalancerName", "AvailabilityZone"},
 		"AWS/ElasticMapReduce": {"ClusterId", "JobFlowId", "JobId"},
 		"AWS/ElasticMapReduce": {"ClusterId", "JobFlowId", "JobId"},
-		"AWS/ES":               {},
+		"AWS/ES":               {"ClientId", "DomainName"},
 		"AWS/Events":           {"RuleName"},
 		"AWS/Events":           {"RuleName"},
 		"AWS/Kinesis":          {"StreamName", "ShardID"},
 		"AWS/Kinesis":          {"StreamName", "ShardID"},
 		"AWS/Lambda":           {"FunctionName"},
 		"AWS/Lambda":           {"FunctionName"},

+ 1 - 0
pkg/api/dtos/plugins.go

@@ -29,6 +29,7 @@ type PluginListItem struct {
 	Info          *plugins.PluginInfo `json:"info"`
 	Info          *plugins.PluginInfo `json:"info"`
 	LatestVersion string              `json:"latestVersion"`
 	LatestVersion string              `json:"latestVersion"`
 	HasUpdate     bool                `json:"hasUpdate"`
 	HasUpdate     bool                `json:"hasUpdate"`
+	DefaultNavUrl string              `json:"defaultNavUrl"`
 }
 }
 
 
 type PluginList []PluginListItem
 type PluginList []PluginListItem

+ 6 - 0
pkg/api/plugins.go

@@ -8,6 +8,7 @@ import (
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/middleware"
 	m "github.com/grafana/grafana/pkg/models"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/plugins"
 	"github.com/grafana/grafana/pkg/plugins"
+	"github.com/grafana/grafana/pkg/setting"
 )
 )
 
 
 func GetPluginList(c *middleware.Context) Response {
 func GetPluginList(c *middleware.Context) Response {
@@ -46,6 +47,7 @@ func GetPluginList(c *middleware.Context) Response {
 			Info:          &pluginDef.Info,
 			Info:          &pluginDef.Info,
 			LatestVersion: pluginDef.GrafanaNetVersion,
 			LatestVersion: pluginDef.GrafanaNetVersion,
 			HasUpdate:     pluginDef.GrafanaNetHasUpdate,
 			HasUpdate:     pluginDef.GrafanaNetHasUpdate,
+			DefaultNavUrl: pluginDef.DefaultNavUrl,
 		}
 		}
 
 
 		if pluginSetting, exists := pluginSettingsMap[pluginDef.Id]; exists {
 		if pluginSetting, exists := pluginSettingsMap[pluginDef.Id]; exists {
@@ -53,6 +55,10 @@ func GetPluginList(c *middleware.Context) Response {
 			listItem.Pinned = pluginSetting.Pinned
 			listItem.Pinned = pluginSetting.Pinned
 		}
 		}
 
 
+		if listItem.DefaultNavUrl == "" || !listItem.Enabled {
+			listItem.DefaultNavUrl = setting.AppSubUrl + "/plugins/" + listItem.Id + "/edit"
+		}
+
 		// filter out disabled
 		// filter out disabled
 		if enabledFilter == "1" && !listItem.Enabled {
 		if enabledFilter == "1" && !listItem.Enabled {
 			continue
 			continue

+ 1 - 1
pkg/api/render.go

@@ -31,7 +31,7 @@ func RenderToPng(c *middleware.Context) {
 		Width:     queryReader.Get("width", "800"),
 		Width:     queryReader.Get("width", "800"),
 		Height:    queryReader.Get("height", "400"),
 		Height:    queryReader.Get("height", "400"),
 		SessionId: c.Session.ID(),
 		SessionId: c.Session.ID(),
-		Timeout:   queryReader.Get("timeout", "15"),
+		Timeout:   queryReader.Get("timeout", "30"),
 	}
 	}
 
 
 	renderOpts.Url = setting.ToAbsUrl(renderOpts.Url)
 	renderOpts.Url = setting.ToAbsUrl(renderOpts.Url)

+ 2 - 0
pkg/components/renderer/renderer.go

@@ -1,6 +1,7 @@
 package renderer
 package renderer
 
 
 import (
 import (
+	"fmt"
 	"io"
 	"io"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
@@ -72,6 +73,7 @@ func RenderToPng(params *RenderOpts) (string, error) {
 		if err := cmd.Process.Kill(); err != nil {
 		if err := cmd.Process.Kill(); err != nil {
 			log.Error(4, "failed to kill: %v", err)
 			log.Error(4, "failed to kill: %v", err)
 		}
 		}
+		return "", fmt.Errorf("PhantomRenderer::renderToPng timeout (>%vs)", timeout)
 	case <-done:
 	case <-done:
 	}
 	}
 
 

+ 0 - 2
pkg/plugins/app_plugin.go

@@ -76,8 +76,6 @@ func (app *AppPlugin) initApp() {
 		}
 		}
 	}
 	}
 
 
-	app.DefaultNavUrl = setting.AppSubUrl + "/plugins/" + app.Id + "/edit"
-
 	// slugify pages
 	// slugify pages
 	for _, include := range app.Includes {
 	for _, include := range app.Includes {
 		if include.Slug == "" {
 		if include.Slug == "" {

+ 2 - 0
public/app/app.ts

@@ -42,6 +42,8 @@ export class GrafanaApp {
     app.constant('grafanaVersion', "@grafanaVersion@");
     app.constant('grafanaVersion', "@grafanaVersion@");
 
 
     app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => {
     app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => {
+      //$compileProvider.debugInfoEnabled(false);
+
       this.registerFunctions.controller = $controllerProvider.register;
       this.registerFunctions.controller = $controllerProvider.register;
       this.registerFunctions.directive  = $compileProvider.directive;
       this.registerFunctions.directive  = $compileProvider.directive;
       this.registerFunctions.factory    = $provide.factory;
       this.registerFunctions.factory    = $provide.factory;

+ 1 - 1
public/app/features/dashboard/partials/settings.html

@@ -86,7 +86,7 @@
 					<button class="btn btn-inverse gf-from-btn" ng-click="_.move(dashboard.rows,$index,$index+1)">
 					<button class="btn btn-inverse gf-from-btn" ng-click="_.move(dashboard.rows,$index,$index+1)">
 						<i ng-class="{'invisible': $last}" class="fa fa-arrow-down"></i>
 						<i ng-class="{'invisible': $last}" class="fa fa-arrow-down"></i>
 					</button>
 					</button>
-					<button class="btn btn-inverse gf-form-btn" click="dashboard.rows = _.without(dashboard.rows,row)">
+					<button class="btn btn-inverse gf-form-btn" ng-click="dashboard.rows = _.without(dashboard.rows,row)">
 						<i class="fa fa-trash"></i>
 						<i class="fa fa-trash"></i>
 					</button>
 					</button>
 				</div>
 				</div>

+ 11 - 9
public/app/features/org/partials/newOrg.html

@@ -8,14 +8,16 @@
 
 
 	<p class="playlist-description">Each organization contains their own dashboards, data sources and configuration, and cannot be shared between orgs. While users may belong to more than one, mutiple organization are most frequently used in multi-tenant deployments. </p>
 	<p class="playlist-description">Each organization contains their own dashboards, data sources and configuration, and cannot be shared between orgs. While users may belong to more than one, mutiple organization are most frequently used in multi-tenant deployments. </p>
 
 
-	<div class="gf-form-group">
-		<div class="gf-form">
-			<span class="gf-form-label width-10">Org. name</span>
-			<input type="text" ng-model="newOrg.name" required class="gf-form-input max-width-21" placeholder="organization name">
+	<form>
+		<div class="gf-form-group">
+			<div class="gf-form">
+				<span class="gf-form-label width-10">Org. name</span>
+				<input type="text" ng-model="newOrg.name" required class="gf-form-input max-width-21" placeholder="organization name">
+			</div>
+			<br>
+			<div class="gf-form-buttons-row">
+				<button type="submit" class="btn btn-success" ng-click="createOrg()">Create</button>
+			</div>
 		</div>
 		</div>
-		<br>
-		<div class="gf-form-buttons-row">
-			<button class="btn btn-success" ng-click="createOrg()">Create</button>
-		</div>
-	</div>
+	</form>
 </div>
 </div>

+ 2 - 3
public/app/features/templating/templateValuesSrv.js

@@ -213,8 +213,7 @@ function (angular, _, kbn) {
     this.updateOptions = function(variable) {
     this.updateOptions = function(variable) {
       if (variable.type !== 'query') {
       if (variable.type !== 'query') {
         self._updateNonQueryVariable(variable);
         self._updateNonQueryVariable(variable);
-        self.setVariableValue(variable, variable.options[0]);
-        return $q.when([]);
+        return self.validateVariableSelectionState(variable);
       }
       }
 
 
       return datasourceSrv.get(variable.datasource)
       return datasourceSrv.get(variable.datasource)
@@ -251,7 +250,7 @@ function (angular, _, kbn) {
       if (_.isArray(variable.current.value)) {
       if (_.isArray(variable.current.value)) {
         self.selectOptionsForCurrentValue(variable);
         self.selectOptionsForCurrentValue(variable);
       } else {
       } else {
-        var currentOption = _.findWhere(variable.options, { text: variable.current.text });
+        var currentOption = _.findWhere(variable.options, {text: variable.current.text});
         if (currentOption) {
         if (currentOption) {
           return self.setVariableValue(variable, currentOption, true);
           return self.setVariableValue(variable, currentOption, true);
         } else {
         } else {

+ 7 - 2
public/app/plugins/datasource/opentsdb/datasource.js

@@ -376,11 +376,16 @@ function (angular, _, dateMath) {
 
 
       if (target.filters && target.filters.length > 0) {
       if (target.filters && target.filters.length > 0) {
         query.filters = angular.copy(target.filters);
         query.filters = angular.copy(target.filters);
+        if(query.filters){
+          for(var filter_key in query.filters){
+            query.filters[filter_key].filter = templateSrv.replace(query.filters[filter_key].filter, options.scopedVars, 'pipe');
+          }
+        }
       } else {
       } else {
         query.tags = angular.copy(target.tags);
         query.tags = angular.copy(target.tags);
         if(query.tags){
         if(query.tags){
-          for(var key in query.tags){
-            query.tags[key] = templateSrv.replace(query.tags[key], options.scopedVars, 'pipe');
+          for(var tag_key in query.tags){
+            query.tags[tag_key] = templateSrv.replace(query.tags[tag_key], options.scopedVars, 'pipe');
           }
           }
         }
         }
       }
       }

+ 4 - 2
public/app/plugins/panel/graph/tab_axes.html

@@ -46,7 +46,7 @@
     <h5 class="section-heading">Thresholds</h5>
     <h5 class="section-heading">Thresholds</h5>
     <div class="gf-form-inline">
     <div class="gf-form-inline">
       <div class="gf-form">
       <div class="gf-form">
-        <label class="gf-form-label width-5">Level 1</label>
+        <label class="gf-form-label width-6">Level 1</label>
         <input type="number" class="gf-form-input max-width-5" ng-model="ctrl.panel.grid.threshold1" ng-change="ctrl.render()" ng-model-onblur>
         <input type="number" class="gf-form-input max-width-5" ng-model="ctrl.panel.grid.threshold1" ng-change="ctrl.render()" ng-model-onblur>
       </div>
       </div>
       <div class="gf-form">
       <div class="gf-form">
@@ -58,7 +58,7 @@
     </div>
     </div>
     <div class="gf-form-inline">
     <div class="gf-form-inline">
       <div class="gf-form">
       <div class="gf-form">
-        <label class="gf-form-label width-5">Level 2</label>
+        <label class="gf-form-label width-6">Level 2</label>
         <input type="number" class="gf-form-input max-width-5" ng-model="ctrl.panel.grid.threshold2" ng-change="ctrl.render()" ng-model-onblur>
         <input type="number" class="gf-form-input max-width-5" ng-model="ctrl.panel.grid.threshold2" ng-change="ctrl.render()" ng-model-onblur>
       </div>
       </div>
       <div class="gf-form">
       <div class="gf-form">
@@ -68,5 +68,7 @@
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
+
+    <gf-form-switch class="gf-form" label="Line Mode" label-class="width-6" checked="ctrl.panel.grid.thresholdLine" on-change="ctrl.render()"></gf-form-switch>
   </div>
   </div>
 </div>
 </div>

+ 2 - 2
public/app/plugins/panel/pluginlist/module.html

@@ -4,7 +4,7 @@
       {{category.header}}
       {{category.header}}
     </h6>
     </h6>
     <div class="pluginlist-item" ng-repeat="plugin in category.list">
     <div class="pluginlist-item" ng-repeat="plugin in category.list">
-      <a class="pluginlist-link pluginlist-link-{{plugin.state}} pointer" href="plugins/{{plugin.id}}/edit">
+      <a class="pluginlist-link pluginlist-link-{{plugin.state}} pointer" href="{{plugin.defaultNavUrl}}">
         <span>
         <span>
           <img ng-src="{{plugin.info.logos.small}}" class="pluginlist-image">
           <img ng-src="{{plugin.info.logos.small}}" class="pluginlist-image">
           <span class="pluginlist-title">{{plugin.name}}</span>
           <span class="pluginlist-title">{{plugin.name}}</span>
@@ -23,7 +23,7 @@
     </div>
     </div>
     <div class="pluginlist-item" ng-show="category.list.length === 0">
     <div class="pluginlist-item" ng-show="category.list.length === 0">
       <a class="pluginlist-link pluginlist-link-{{plugin.state}}" href="https://grafana.net/plugins">
       <a class="pluginlist-link pluginlist-link-{{plugin.state}}" href="https://grafana.net/plugins">
-        <span class="pluginlist-none-installed">No additional panels installed. <span class="pluginlist-emphasis">Browse Grafana.net</span></span>
+        <span class="pluginlist-none-installed">None installed. <span class="pluginlist-emphasis">Browse Grafana.net</span></span>
       </a>
       </a>
     </div>
     </div>
   </div>
   </div>

+ 10 - 18
public/app/plugins/panel/singlestat/module.ts

@@ -82,7 +82,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
   }
   }
 
 
   onDataError(err) {
   onDataError(err) {
-    this.onDataReceived({data: []});
+    this.onDataReceived([]);
   }
   }
 
 
   onDataReceived(dataList) {
   onDataReceived(dataList) {
@@ -91,11 +91,6 @@ class SingleStatCtrl extends MetricsPanelCtrl {
     var data: any = {};
     var data: any = {};
     this.setValues(data);
     this.setValues(data);
 
 
-    data.thresholds = this.panel.thresholds.split(',').map(function(strVale) {
-      return Number(strVale.trim());
-    });
-
-    data.colorMap = this.panel.colors;
     this.data = data;
     this.data = data;
     this.render();
     this.render();
   }
   }
@@ -324,9 +319,9 @@ class SingleStatCtrl extends MetricsPanelCtrl {
         ? 'rgb(230,230,230)'
         ? 'rgb(230,230,230)'
         : 'rgb(38,38,38)';
         : 'rgb(38,38,38)';
 
 
-
+      var fontScale = parseInt(panel.valueFontSize) / 100;
       var dimension = Math.min(width, height);
       var dimension = Math.min(width, height);
-      var fontSize = Math.min(dimension/4, 100);
+      var fontSize = Math.min(dimension/5, 100) * fontScale;
       var gaugeWidth = Math.min(dimension/6, 60);
       var gaugeWidth = Math.min(dimension/6, 60);
       var thresholdMarkersWidth = gaugeWidth/5;
       var thresholdMarkersWidth = gaugeWidth/5;
 
 
@@ -374,15 +369,6 @@ class SingleStatCtrl extends MetricsPanelCtrl {
       $.plot(plotCanvas, [plotSeries], options);
       $.plot(plotCanvas, [plotSeries], options);
     }
     }
 
 
-    function getGaugeFontSize() {
-      if (panel.valueFontSize) {
-        var num = parseInt(panel.valueFontSize.substring(0, panel.valueFontSize.length - 1));
-        return (30 * (num / 100)) + 15;
-      } else {
-        return 30;
-      }
-    }
-
     function addSparkline() {
     function addSparkline() {
       var width = elem.width() + 20;
       var width = elem.width() + 20;
       if (width < 30) {
       if (width < 30) {
@@ -444,8 +430,14 @@ class SingleStatCtrl extends MetricsPanelCtrl {
 
 
     function render() {
     function render() {
       if (!ctrl.data) { return; }
       if (!ctrl.data) { return; }
-      ctrl.setValues(ctrl.data);
       data = ctrl.data;
       data = ctrl.data;
+
+      // get thresholds
+      data.thresholds = panel.thresholds.split(',').map(function(strVale) {
+        return Number(strVale.trim());
+      });
+      data.colorMap = panel.colors;
+
       setElementHeight();
       setElementHeight();
 
 
       var body = panel.gauge.show ? '' : getBigValueHtml();
       var body = panel.gauge.show ? '' : getBigValueHtml();

+ 2 - 0
public/dashboards/scripted_templated.js

@@ -47,6 +47,7 @@ dashboard.templating = {
       refresh: true,
       refresh: true,
       options: [],
       options: [],
       current: null,
       current: null,
+      type: 'custom'
     },
     },
     {
     {
       name: 'test2',
       name: 'test2',
@@ -54,6 +55,7 @@ dashboard.templating = {
       refresh: true,
       refresh: true,
       options: [],
       options: [],
       current: null,
       current: null,
+      type: 'custom'
     }
     }
   ]
   ]
 };
 };

+ 12 - 2
public/test/specs/templateValuesSrv-specs.js

@@ -166,7 +166,7 @@ define([
 
 
     describeUpdateVariable('update custom variable', function(scenario) {
     describeUpdateVariable('update custom variable', function(scenario) {
       scenario.setup(function() {
       scenario.setup(function() {
-        scenario.variable = { type: 'custom', query: 'hej, hop, asd', name: 'test'};
+        scenario.variable = {type: 'custom', query: 'hej, hop, asd', name: 'test'};
       });
       });
 
 
       it('should update options array', function() {
       it('should update options array', function() {
@@ -286,7 +286,13 @@ define([
 
 
     describeUpdateVariable('datasource variable with regex filter', function(scenario) {
     describeUpdateVariable('datasource variable with regex filter', function(scenario) {
       scenario.setup(function() {
       scenario.setup(function() {
-        scenario.variable = {type: 'datasource', query: 'graphite', name: 'test', current: {}, regex: '/pee$/' };
+        scenario.variable = {
+          type: 'datasource',
+          query: 'graphite',
+          name: 'test',
+          current: {value: 'backend4_pee', text: 'backend4_pee'},
+          regex: '/pee$/'
+        };
         scenario.metricSources = [
         scenario.metricSources = [
           {name: 'backend1', meta: {id: 'influx'}},
           {name: 'backend1', meta: {id: 'influx'}},
           {name: 'backend2_pee', meta: {id: 'graphite'}},
           {name: 'backend2_pee', meta: {id: 'graphite'}},
@@ -300,6 +306,10 @@ define([
         expect(scenario.variable.options[0].value).to.be('backend2_pee');
         expect(scenario.variable.options[0].value).to.be('backend2_pee');
         expect(scenario.variable.options[1].value).to.be('backend4_pee');
         expect(scenario.variable.options[1].value).to.be('backend4_pee');
       });
       });
+
+      it('should keep current value if available', function() {
+        expect(scenario.variable.current.value).to.be('backend4_pee');
+      });
     });
     });
 
 
   });
   });

+ 0 - 2
tasks/options/phantomjs.js

@@ -15,8 +15,6 @@ module.exports = function(config,grunt) {
         src = confDir+src;
         src = confDir+src;
       }
       }
 
 
-      var exec = require('child_process').execFileSync;
-
       try {
       try {
         grunt.config('copy.phantom_bin', {
         grunt.config('copy.phantom_bin', {
           src: src,
           src: src,