diff --git a/CHANGELOG.md b/CHANGELOG.md index a67f45e69ec..930a91af1da 100644 --- a/CHANGELOG.md +++ b/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) ### Bug fixes * **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) * **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) +* **Graph**: Fixes missing line mode for thresholds, fixes [#4902](https://github.com/grafana/grafana/pull/4902) ### Enhancements * **InfluxDB**: Added new functions moving_average and difference to query editor, closes [#4698](https://github.com/grafana/grafana/issues/4698) diff --git a/README.md b/README.md index d538ba78e1e..e678e48a14d 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ the latest master builds [here](http://grafana.org/download/builds) ### Dependencies - Go 1.5 -- NodeJS +- NodeJS v0.12.0 - [Godep](https://github.com/tools/godep) ### Get Code @@ -87,8 +87,19 @@ the latest master builds [here](http://grafana.org/download/builds) 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 -Replace X.Y.Z by actual version number. ```bash cd $GOPATH/src/github.com/grafana/grafana go run build.go setup (only needed once to install godep) @@ -98,7 +109,7 @@ go run build.go build ### 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: ```bash @@ -106,6 +117,13 @@ npm install 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 To rebuild on source change (requires that you executed godep restore) ```bash diff --git a/build.go b/build.go index 0965a405e70..e1fc3599aa8 100644 --- a/build.go +++ b/build.go @@ -136,7 +136,7 @@ func readVersionFromPackageJson() { // add timestamp to iteration linuxPackageIteration = fmt.Sprintf("%s%v", linuxPackageIteration, time.Now().Unix()) } - log.Println(fmt.Sprintf("teration %v", linuxPackageIteration)) + log.Println(fmt.Sprintf("Iteration %v", linuxPackageIteration)) } } diff --git a/conf/defaults.ini b/conf/defaults.ini index 77feafdd71a..489fe02213f 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -241,14 +241,14 @@ templates_pattern = emails/*.html #################################### Logging ########################## [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" mode = console, file # Buffer length of channel, keep it as it is if you don't know what it is. 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 # For "console" mode only diff --git a/conf/sample.ini b/conf/sample.ini index 4ab923c1376..6a26589d40d 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -223,14 +223,14 @@ check_for_updates = true #################################### Logging ########################## [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" ;mode = console, file # Buffer length of channel, keep it as it is if you don't know what it is. ;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 # For "console" mode only diff --git a/docs/sources/datasources/kairosdb.md b/docs/sources/datasources/kairosdb.md index fc9b5682515..4430b427250 100644 --- a/docs/sources/datasources/kairosdb.md +++ b/docs/sources/datasources/kairosdb.md @@ -30,7 +30,7 @@ Access | Proxy = access via Grafana backend, Direct = access directory from brow ## Query editor 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. - [Query Metrics - KairosDB 0.9.4 documentation](http://kairosdb.github.io/kairosdocs/restapi/QueryMetrics.html). diff --git a/pkg/api/cloudwatch/metrics.go b/pkg/api/cloudwatch/metrics.go index 5ecdaabf516..7717ca27099 100644 --- a/pkg/api/cloudwatch/metrics.go +++ b/pkg/api/cloudwatch/metrics.go @@ -86,7 +86,7 @@ func init() { "AWS/EC2": {"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"}, "AWS/ELB": {"LoadBalancerName", "AvailabilityZone"}, "AWS/ElasticMapReduce": {"ClusterId", "JobFlowId", "JobId"}, - "AWS/ES": {}, + "AWS/ES": {"ClientId", "DomainName"}, "AWS/Events": {"RuleName"}, "AWS/Kinesis": {"StreamName", "ShardID"}, "AWS/Lambda": {"FunctionName"}, diff --git a/pkg/api/dtos/plugins.go b/pkg/api/dtos/plugins.go index 7d46cc9d348..fccb7c36849 100644 --- a/pkg/api/dtos/plugins.go +++ b/pkg/api/dtos/plugins.go @@ -29,6 +29,7 @@ type PluginListItem struct { Info *plugins.PluginInfo `json:"info"` LatestVersion string `json:"latestVersion"` HasUpdate bool `json:"hasUpdate"` + DefaultNavUrl string `json:"defaultNavUrl"` } type PluginList []PluginListItem diff --git a/pkg/api/plugins.go b/pkg/api/plugins.go index ad81d438978..7d6d5906913 100644 --- a/pkg/api/plugins.go +++ b/pkg/api/plugins.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/setting" ) func GetPluginList(c *middleware.Context) Response { @@ -46,6 +47,7 @@ func GetPluginList(c *middleware.Context) Response { Info: &pluginDef.Info, LatestVersion: pluginDef.GrafanaNetVersion, HasUpdate: pluginDef.GrafanaNetHasUpdate, + DefaultNavUrl: pluginDef.DefaultNavUrl, } if pluginSetting, exists := pluginSettingsMap[pluginDef.Id]; exists { @@ -53,6 +55,10 @@ func GetPluginList(c *middleware.Context) Response { listItem.Pinned = pluginSetting.Pinned } + if listItem.DefaultNavUrl == "" || !listItem.Enabled { + listItem.DefaultNavUrl = setting.AppSubUrl + "/plugins/" + listItem.Id + "/edit" + } + // filter out disabled if enabledFilter == "1" && !listItem.Enabled { continue diff --git a/pkg/api/render.go b/pkg/api/render.go index 9ed0c5ee6d7..65c1499d0c5 100644 --- a/pkg/api/render.go +++ b/pkg/api/render.go @@ -31,7 +31,7 @@ func RenderToPng(c *middleware.Context) { Width: queryReader.Get("width", "800"), Height: queryReader.Get("height", "400"), SessionId: c.Session.ID(), - Timeout: queryReader.Get("timeout", "15"), + Timeout: queryReader.Get("timeout", "30"), } renderOpts.Url = setting.ToAbsUrl(renderOpts.Url) diff --git a/pkg/components/renderer/renderer.go b/pkg/components/renderer/renderer.go index f81da43c295..d6091a3cb19 100644 --- a/pkg/components/renderer/renderer.go +++ b/pkg/components/renderer/renderer.go @@ -1,6 +1,7 @@ package renderer import ( + "fmt" "io" "os" "os/exec" @@ -72,6 +73,7 @@ func RenderToPng(params *RenderOpts) (string, error) { if err := cmd.Process.Kill(); err != nil { log.Error(4, "failed to kill: %v", err) } + return "", fmt.Errorf("PhantomRenderer::renderToPng timeout (>%vs)", timeout) case <-done: } diff --git a/pkg/plugins/app_plugin.go b/pkg/plugins/app_plugin.go index f565b0e2b22..cc588bf1d55 100644 --- a/pkg/plugins/app_plugin.go +++ b/pkg/plugins/app_plugin.go @@ -76,8 +76,6 @@ func (app *AppPlugin) initApp() { } } - app.DefaultNavUrl = setting.AppSubUrl + "/plugins/" + app.Id + "/edit" - // slugify pages for _, include := range app.Includes { if include.Slug == "" { diff --git a/public/app/app.ts b/public/app/app.ts index b30b75a0ca3..3434814d3b6 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -42,6 +42,8 @@ export class GrafanaApp { app.constant('grafanaVersion', "@grafanaVersion@"); app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => { + //$compileProvider.debugInfoEnabled(false); + this.registerFunctions.controller = $controllerProvider.register; this.registerFunctions.directive = $compileProvider.directive; this.registerFunctions.factory = $provide.factory; diff --git a/public/app/features/dashboard/partials/settings.html b/public/app/features/dashboard/partials/settings.html index 8d071d90495..6290ffeacba 100644 --- a/public/app/features/dashboard/partials/settings.html +++ b/public/app/features/dashboard/partials/settings.html @@ -86,7 +86,7 @@ - diff --git a/public/app/features/org/partials/newOrg.html b/public/app/features/org/partials/newOrg.html index 88c348db78f..1c0a19ddec0 100644 --- a/public/app/features/org/partials/newOrg.html +++ b/public/app/features/org/partials/newOrg.html @@ -8,14 +8,16 @@

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.

-
-
- Org. name - +
+
+
+ Org. name + +
+
+
+ +
-
-
- -
-
+
diff --git a/public/app/features/templating/templateValuesSrv.js b/public/app/features/templating/templateValuesSrv.js index dc878c19c08..472c24aef61 100644 --- a/public/app/features/templating/templateValuesSrv.js +++ b/public/app/features/templating/templateValuesSrv.js @@ -213,8 +213,7 @@ function (angular, _, kbn) { this.updateOptions = function(variable) { if (variable.type !== 'query') { self._updateNonQueryVariable(variable); - self.setVariableValue(variable, variable.options[0]); - return $q.when([]); + return self.validateVariableSelectionState(variable); } return datasourceSrv.get(variable.datasource) @@ -251,7 +250,7 @@ function (angular, _, kbn) { if (_.isArray(variable.current.value)) { self.selectOptionsForCurrentValue(variable); } else { - var currentOption = _.findWhere(variable.options, { text: variable.current.text }); + var currentOption = _.findWhere(variable.options, {text: variable.current.text}); if (currentOption) { return self.setVariableValue(variable, currentOption, true); } else { diff --git a/public/app/plugins/datasource/opentsdb/datasource.js b/public/app/plugins/datasource/opentsdb/datasource.js index 32139832628..16f96ae060e 100644 --- a/public/app/plugins/datasource/opentsdb/datasource.js +++ b/public/app/plugins/datasource/opentsdb/datasource.js @@ -376,11 +376,16 @@ function (angular, _, dateMath) { if (target.filters && target.filters.length > 0) { 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 { query.tags = angular.copy(target.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'); } } } diff --git a/public/app/plugins/panel/graph/tab_axes.html b/public/app/plugins/panel/graph/tab_axes.html index 81ab3deeb31..eeaf27aff78 100644 --- a/public/app/plugins/panel/graph/tab_axes.html +++ b/public/app/plugins/panel/graph/tab_axes.html @@ -46,7 +46,7 @@
Thresholds
- +
@@ -58,7 +58,7 @@
- +
@@ -68,5 +68,7 @@
+ + diff --git a/public/app/plugins/panel/pluginlist/module.html b/public/app/plugins/panel/pluginlist/module.html index 8e74f173a07..1cf7cfac34f 100644 --- a/public/app/plugins/panel/pluginlist/module.html +++ b/public/app/plugins/panel/pluginlist/module.html @@ -4,7 +4,7 @@ {{category.header}}
- + {{plugin.name}} @@ -23,7 +23,7 @@
- No additional panels installed. Browse Grafana.net + None installed. Browse Grafana.net
diff --git a/public/app/plugins/panel/singlestat/module.ts b/public/app/plugins/panel/singlestat/module.ts index 3c0b9e5342a..9fa3e8e39c6 100644 --- a/public/app/plugins/panel/singlestat/module.ts +++ b/public/app/plugins/panel/singlestat/module.ts @@ -82,7 +82,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { } onDataError(err) { - this.onDataReceived({data: []}); + this.onDataReceived([]); } onDataReceived(dataList) { @@ -91,11 +91,6 @@ class SingleStatCtrl extends MetricsPanelCtrl { var data: any = {}; 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.render(); } @@ -324,9 +319,9 @@ class SingleStatCtrl extends MetricsPanelCtrl { ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; - + var fontScale = parseInt(panel.valueFontSize) / 100; 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 thresholdMarkersWidth = gaugeWidth/5; @@ -374,15 +369,6 @@ class SingleStatCtrl extends MetricsPanelCtrl { $.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() { var width = elem.width() + 20; if (width < 30) { @@ -444,8 +430,14 @@ class SingleStatCtrl extends MetricsPanelCtrl { function render() { if (!ctrl.data) { return; } - ctrl.setValues(ctrl.data); data = ctrl.data; + + // get thresholds + data.thresholds = panel.thresholds.split(',').map(function(strVale) { + return Number(strVale.trim()); + }); + data.colorMap = panel.colors; + setElementHeight(); var body = panel.gauge.show ? '' : getBigValueHtml(); diff --git a/public/dashboards/scripted_templated.js b/public/dashboards/scripted_templated.js index a0d3e081293..33830336a9f 100644 --- a/public/dashboards/scripted_templated.js +++ b/public/dashboards/scripted_templated.js @@ -47,6 +47,7 @@ dashboard.templating = { refresh: true, options: [], current: null, + type: 'custom' }, { name: 'test2', @@ -54,6 +55,7 @@ dashboard.templating = { refresh: true, options: [], current: null, + type: 'custom' } ] }; diff --git a/public/test/specs/templateValuesSrv-specs.js b/public/test/specs/templateValuesSrv-specs.js index 3f4cd96c444..2edcd03da9a 100644 --- a/public/test/specs/templateValuesSrv-specs.js +++ b/public/test/specs/templateValuesSrv-specs.js @@ -166,7 +166,7 @@ define([ describeUpdateVariable('update custom variable', function(scenario) { 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() { @@ -286,7 +286,13 @@ define([ describeUpdateVariable('datasource variable with regex filter', function(scenario) { 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 = [ {name: 'backend1', meta: {id: 'influx'}}, {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[1].value).to.be('backend4_pee'); }); + + it('should keep current value if available', function() { + expect(scenario.variable.current.value).to.be('backend4_pee'); + }); }); }); diff --git a/tasks/options/phantomjs.js b/tasks/options/phantomjs.js index ae777a1cf74..4339f9880b6 100644 --- a/tasks/options/phantomjs.js +++ b/tasks/options/phantomjs.js @@ -15,8 +15,6 @@ module.exports = function(config,grunt) { src = confDir+src; } - var exec = require('child_process').execFileSync; - try { grunt.config('copy.phantom_bin', { src: src,