From e78c48620fc4a9e0f6d63fae05205afd1fc50a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 19 Sep 2014 13:24:15 +0200 Subject: [PATCH 1/9] Trying to improve yaxis precision --- src/app/components/kbn.js | 76 ++++-------------------------- src/app/components/timeSeries.js | 16 +++---- src/app/directives/grafanaGraph.js | 22 ++++++--- 3 files changed, 33 insertions(+), 81 deletions(-) diff --git a/src/app/components/kbn.js b/src/app/components/kbn.js index 7c61b22c83b..e41722747fb 100644 --- a/src/app/components/kbn.js +++ b/src/app/components/kbn.js @@ -7,6 +7,7 @@ function($, _, moment) { 'use strict'; var kbn = {}; + kbn.formatFunctions = {}; kbn.round_interval = function(interval) { switch (true) { @@ -497,52 +498,7 @@ function($, _, moment) { return (size.toFixed(decimals) + ext); }; - kbn.getFormatFunction = function(formatName, decimals) { - switch(formatName) { - case 'short': - return function(val) { - return kbn.shortFormat(val, decimals); - }; - case 'bytes': - return function(val) { - return kbn.byteFormat(val, decimals); - }; - case 'bits': - return function(val) { - return kbn.bitFormat(val, decimals); - }; - case 'bps': - return function(val) { - return kbn.bpsFormat(val, decimals); - }; - case 's': - return function(val) { - return kbn.sFormat(val, decimals); - }; - case 'ms': - return function(val) { - return kbn.msFormat(val, decimals); - }; - case 'µs': - return function(val) { - return kbn.microsFormat(val, decimals); - }; - case 'ns': - return function(val) { - return kbn.nanosFormat(val, decimals); - }; - case 'percent': - return function(val, axis) { - return kbn.noneFormat(val, axis ? axis.tickDecimals : null) + ' %'; - }; - default: - return function(val, axis) { - return kbn.noneFormat(val, axis ? axis.tickDecimals : null); - }; - } - }; - - kbn.noneFormat = function(value, decimals) { + kbn.toFixed = function(value, decimals) { var factor = decimals ? Math.pow(10, decimals) : 1; var formatted = String(Math.round(value * factor) / factor); @@ -553,7 +509,6 @@ function($, _, moment) { // If tickDecimals was specified, ensure that we have exactly that // much precision; otherwise default to the value's own precision. - if (decimals != null) { var decimalPos = formatted.indexOf("."); var precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1; @@ -565,17 +520,13 @@ function($, _, moment) { return formatted; }; - kbn.msFormat = function(size, decimals) { - // Less than 1 milli, downscale to micro - if (size !== 0 && Math.abs(size) < 1) { - return kbn.microsFormat(size * 1000, decimals); - } - else if (Math.abs(size) < 1000) { - return size.toFixed(decimals) + " ms"; + kbn.formatFunctions.ms = function(size, decimals) { + if (Math.abs(size) < 1000) { + return kbn.toFixed(size, decimals) + " ms"; } // Less than 1 min else if (Math.abs(size) < 60000) { - return (size / 1000).toFixed(decimals) + " s"; + return kbn.toFixed(size / 1000, decimals) + " s"; } // Less than 1 hour, devide in minutes else if (Math.abs(size) < 3600000) { @@ -594,12 +545,7 @@ function($, _, moment) { }; kbn.sFormat = function(size, decimals) { - // Less than 1 sec, downscale to milli - if (size !== 0 && Math.abs(size) < 1) { - return kbn.msFormat(size * 1000, decimals); - } - // Less than 10 min, use seconds - else if (Math.abs(size) < 600) { + if (Math.abs(size) < 600) { return size.toFixed(decimals) + " s"; } // Less than 1 hour, devide in minutes @@ -623,12 +569,8 @@ function($, _, moment) { }; kbn.microsFormat = function(size, decimals) { - // Less than 1 micro, downscale to nano - if (size !== 0 && Math.abs(size) < 1) { - return kbn.nanosFormat(size * 1000, decimals); - } - else if (Math.abs(size) < 1000) { - return size.toFixed(decimals) + " µs"; + if (Math.abs(size) < 1000) { + return kbn.toFixed(size, decimals) + " µs"; } else if (Math.abs(size) < 1000000) { return (size / 1000).toFixed(decimals) + " ms"; diff --git a/src/app/components/timeSeries.js b/src/app/components/timeSeries.js index 4c58c211cc3..576e8be8e8a 100644 --- a/src/app/components/timeSeries.js +++ b/src/app/components/timeSeries.js @@ -100,21 +100,21 @@ function (_, kbn) { } if (result.length) { - this.info.avg = (this.info.total / result.length); this.info.current = result[result.length-1][1]; - - var formater = kbn.getFormatFunction(yFormats[this.yaxis - 1], 2); - this.info.avg = this.info.avg != null ? formater(this.info.avg) : null; - this.info.current = this.info.current != null ? formater(this.info.current) : null; - this.info.min = this.info.min != null ? formater(this.info.min) : null; - this.info.max = this.info.max != null ? formater(this.info.max) : null; - this.info.total = this.info.total != null ? formater(this.info.total) : null; } return result; }; + TimeSeries.prototype.updateLegendValues = function(formater, decimals) { + this.info.avg = this.info.avg != null ? formater(this.info.avg, decimals) : null; + this.info.current = this.info.current != null ? formater(this.info.current, decimals) : null; + this.info.min = this.info.min != null ? formater(this.info.min, decimals) : null; + this.info.max = this.info.max != null ? formater(this.info.max, decimals) : null; + this.info.total = this.info.total != null ? formater(this.info.total, decimals) : null; + }; + return TimeSeries; }); diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index ee6b0fb7dd7..53edcf1bc13 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -88,6 +88,18 @@ function (angular, $, kbn, moment, _) { } } + function updateLegendValues(plot) { + var yaxis = plot.getYAxes(); + console.log('drawSeries', yaxis); + + for (var i = 0; i < data.length; i++) { + var series = data[i]; + var formater = kbn.formatFunctions[scope.panel.y_formats[series.yaxis - 1]]; + series.updateLegendValues(formater, yaxis[series.yaxis - 1].tickDecimals); + } + + } + // Function for rendering panel function render_panel() { if (shouldAbortRender()) { @@ -110,11 +122,7 @@ function (angular, $, kbn, moment, _) { // Populate element var options = { - hooks: { - drawSeries: [function() { - console.log('drawSeries', arguments); - }] - }, + hooks: { draw: [updateLegendValues] }, legend: { show: false }, series: { stackpercent: panel.stack ? panel.percentage : false, @@ -318,7 +326,9 @@ function (angular, $, kbn, moment, _) { } function configureAxisMode(axis, format) { - axis.tickFormatter = kbn.getFormatFunction(format, 1); + axis.tickFormatter = function(val, axis) { + return kbn.formatFunctions[format](val, axis.tickDecimals); + }; } function time_format(interval, ticks, min, max) { From 81747e162326d3381a7f0b0a88e372e76f11ed07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 09:03:04 +0200 Subject: [PATCH 2/9] Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations, Fixes #851 --- CHANGELOG.md | 3 +++ src/app/services/annotationsSrv.js | 3 ++- src/app/services/elasticsearch/es-datasource.js | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79bc9c23752..c70461859dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # 1.9.0 (unreleased) +# 1.8.1 (unreleased) + **Fixes** - [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series +- [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations # 1.8.0 (2014-09-22) diff --git a/src/app/services/annotationsSrv.js b/src/app/services/annotationsSrv.js index 04fb4224cc6..25c76caeb77 100644 --- a/src/app/services/annotationsSrv.js +++ b/src/app/services/annotationsSrv.js @@ -13,7 +13,8 @@ define([ var timezone; this.init = function() { - $rootScope.$on('refresh', this.clearCache); + $rootScope.onAppEvent('refresh', this.clearCache); + $rootScope.onAppEvent('setup-dashboard', this.clearCache); }; this.clearCache = function() { diff --git a/src/app/services/elasticsearch/es-datasource.js b/src/app/services/elasticsearch/es-datasource.js index 04d1e62ce04..f9ec01dbd4c 100644 --- a/src/app/services/elasticsearch/es-datasource.js +++ b/src/app/services/elasticsearch/es-datasource.js @@ -94,6 +94,10 @@ function (angular, _, config, kbn, moment) { for (var i = 0; i < fieldNames.length; i++) { fieldValue = fieldValue[fieldNames[i]]; + if (!fieldValue) { + console.log('could not find field in annotatation: ', fieldName); + return ''; + } } if (_.isArray(fieldValue)) { From f4e24038feebf6c52d144c1634fa6c4c0a354210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 10:51:20 +0200 Subject: [PATCH 3/9] Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. Closes #840, Closes #853 --- CHANGELOG.md | 2 ++ src/app/controllers/dashboardCtrl.js | 10 ++++----- src/app/controllers/grafanaCtrl.js | 6 ++++- src/app/controllers/graphiteImport.js | 13 ++++++----- src/app/controllers/row.js | 1 + src/app/directives/dashUpload.js | 12 +++++----- src/app/partials/dashboard.html | 2 +- src/app/partials/import.html | 12 ++++++---- src/app/routes/dashboard-from-db.js | 29 ++++++++++++++++++++----- src/app/routes/dashboard-from-file.js | 2 +- src/app/routes/dashboard-from-script.js | 2 +- 11 files changed, 61 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c70461859dd..dce1108a1c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ **Fixes** - [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series - [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations +- [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor +- [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. # 1.8.0 (2014-09-22) diff --git a/src/app/controllers/dashboardCtrl.js b/src/app/controllers/dashboardCtrl.js index 424f0e225e8..709e33ae7d3 100644 --- a/src/app/controllers/dashboardCtrl.js +++ b/src/app/controllers/dashboardCtrl.js @@ -19,19 +19,18 @@ function (angular, $, config, _) { dashboardSrv, dashboardViewStateSrv, panelMoveSrv, - timer, $timeout) { $scope.editor = { index: 0 }; $scope.panelNames = config.panels; var resizeEventTimeout; - $scope.init = function() { + this.init = function(dashboardData) { $scope.availablePanels = config.panels; - $scope.onAppEvent('setup-dashboard', $scope.setupDashboard); - $scope.onAppEvent('show-json-editor', $scope.showJsonEditor); $scope.reset_row(); $scope.registerWindowResizeEvent(); + $scope.onAppEvent('show-json-editor', $scope.showJsonEditor); + $scope.setupDashboard(dashboardData); }; $scope.registerWindowResizeEvent = function() { @@ -41,7 +40,7 @@ function (angular, $, config, _) { }); }; - $scope.setupDashboard = function(event, dashboardData) { + $scope.setupDashboard = function(dashboardData) { $rootScope.performance.dashboardLoadStart = new Date().getTime(); $rootScope.performance.panelsInitialized = 0; $rootScope.performance.panelsRendered = 0; @@ -129,6 +128,5 @@ function (angular, $, config, _) { return $scope.editorTabs; }; - $scope.init(); }); }); diff --git a/src/app/controllers/grafanaCtrl.js b/src/app/controllers/grafanaCtrl.js index 060c0bc0803..5d406dee1b6 100644 --- a/src/app/controllers/grafanaCtrl.js +++ b/src/app/controllers/grafanaCtrl.js @@ -10,7 +10,7 @@ function (angular, config, _, $, store) { var module = angular.module('grafana.controllers'); - module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope) { + module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope, $controller) { $scope.grafanaVersion = grafanaVersion[0] === '@' ? 'master' : grafanaVersion; $scope.consoleEnabled = store.getBool('grafanaConsole'); @@ -32,6 +32,10 @@ function (angular, config, _, $, store) { store.set('grafanaConsole', $scope.consoleEnabled); }; + $scope.initDashboard = function(dashboardData, viewScope) { + $controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData); + }; + $rootScope.onAppEvent = function(name, callback) { var unbind = $rootScope.$on(name, callback); this.$on('$destroy', unbind); diff --git a/src/app/controllers/graphiteImport.js b/src/app/controllers/graphiteImport.js index d60c8ada3be..a552cd73560 100644 --- a/src/app/controllers/graphiteImport.js +++ b/src/app/controllers/graphiteImport.js @@ -1,14 +1,15 @@ define([ 'angular', 'app', - 'lodash' + 'lodash', + 'kbn' ], -function (angular, app, _) { +function (angular, app, _, kbn) { 'use strict'; var module = angular.module('grafana.controllers'); - module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv) { + module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv, $location) { $scope.init = function() { $scope.datasources = datasourceSrv.getMetricSources(); @@ -79,7 +80,7 @@ function (angular, app, _) { } panel = { - type: 'graphite', + type: 'graph', span: 12 / graphsPerRow, title: graph[1].title, targets: [], @@ -95,7 +96,9 @@ function (angular, app, _) { currentRow.panels.push(panel); }); - $scope.emitAppEvent('setup-dashboard', newDashboard); + window.grafanaImportDashboard = newDashboard; + $location.path('/dashboard/import/' + kbn.slugifyForUrl(newDashboard.title)); + $scope.dismiss(); } diff --git a/src/app/controllers/row.js b/src/app/controllers/row.js index 621c3eddda5..b877f7d10fb 100644 --- a/src/app/controllers/row.js +++ b/src/app/controllers/row.js @@ -13,6 +13,7 @@ function (angular, app, _) { title: "Row", height: "150px", collapse: false, + editable: true, panels: [], }; diff --git a/src/app/directives/dashUpload.js b/src/app/directives/dashUpload.js index 1d7c4ec405e..ba214cf19a4 100644 --- a/src/app/directives/dashUpload.js +++ b/src/app/directives/dashUpload.js @@ -1,12 +1,13 @@ define([ - 'angular' + 'angular', + 'kbn' ], -function (angular) { +function (angular, kbn) { 'use strict'; var module = angular.module('grafana.directives'); - module.directive('dashUpload', function(timer, alertSrv) { + module.directive('dashUpload', function(timer, alertSrv, $location) { return { restrict: 'A', link: function(scope) { @@ -14,9 +15,10 @@ function (angular) { var files = evt.target.files; // FileList object var readerOnload = function() { return function(e) { - var dashboard = JSON.parse(e.target.result); scope.$apply(function() { - scope.emitAppEvent('setup-dashboard', dashboard); + window.grafanaImportDashboard = JSON.parse(e.target.result); + var title = kbn.slugifyForUrl(window.grafanaImportDashboard.title); + $location.path('/dashboard/import/' + title); }); }; }; diff --git a/src/app/partials/dashboard.html b/src/app/partials/dashboard.html index 8afe5d40824..2fa9bbcf2eb 100644 --- a/src/app/partials/dashboard.html +++ b/src/app/partials/dashboard.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/app/partials/import.html b/src/app/partials/import.html index f81468465d4..e89aff41342 100644 --- a/src/app/partials/import.html +++ b/src/app/partials/import.html @@ -16,11 +16,15 @@
-
- +
+
- + +
- {{dash.name}}{{dash.name}} + + import + +
diff --git a/src/app/routes/dashboard-from-db.js b/src/app/routes/dashboard-from-db.js index a5a37ece12d..67c25ab4946 100644 --- a/src/app/routes/dashboard-from-db.js +++ b/src/app/routes/dashboard-from-db.js @@ -22,7 +22,13 @@ function (angular) { templateUrl: 'app/partials/dashboard.html', controller : 'DashFromDBProvider', reloadOnSearch: false, + }) + .when('/dashboard/import/:id', { + templateUrl: 'app/partials/dashboard.html', + controller : 'DashFromImportCtrl', + reloadOnSearch: false, }); + }); module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) { @@ -31,12 +37,23 @@ function (angular) { var isTemp = window.location.href.indexOf('dashboard/temp') !== -1; db.getDashboard($routeParams.id, isTemp) - .then(function(dashboard) { - $scope.emitAppEvent('setup-dashboard', dashboard); - }).then(null, function(error) { - $scope.emitAppEvent('setup-dashboard', { title: 'Grafana'}); - alertSrv.set('Error', error, 'error'); - }); + .then(function(dashboard) { + $scope.initDashboard(dashboard, $scope); + }).then(null, function(error) { + $scope.initDashboard({ title: 'Grafana'}, $scope); + alertSrv.set('Error', error, 'error'); + }); + }); + + module.controller('DashFromImportCtrl', function($scope, $location, alertSrv) { + + if (!window.grafanaImportDashboard) { + alertSrv.set('Not found', 'Cannot reload page with unsaved imported dashboard', 'warning', 7000); + $location.path(''); + return; + } + + $scope.initDashboard(window.grafanaImportDashboard, $scope); }); }); diff --git a/src/app/routes/dashboard-from-file.js b/src/app/routes/dashboard-from-file.js index dc54eaddaf6..82db05480b4 100644 --- a/src/app/routes/dashboard-from-file.js +++ b/src/app/routes/dashboard-from-file.js @@ -52,7 +52,7 @@ function (angular, $, config, _) { }; file_load($routeParams.jsonFile).then(function(result) { - $scope.emitAppEvent('setup-dashboard', result); + $scope.initDashboard(result, $scope); }); }); diff --git a/src/app/routes/dashboard-from-script.js b/src/app/routes/dashboard-from-script.js index cacdf9939b6..fa3abd36e81 100644 --- a/src/app/routes/dashboard-from-script.js +++ b/src/app/routes/dashboard-from-script.js @@ -53,7 +53,7 @@ function (angular, $, config, _, kbn, moment) { }; script_load($routeParams.jsFile).then(function(result) { - $scope.emitAppEvent('setup-dashboard', result.data); + $scope.initDashboard(result.data, $scope); }); }); From 34f36fff5c296e9f22a697f213bf7ca926288f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 11:17:34 +0200 Subject: [PATCH 4/9] small fix for graphite-web import --- src/app/controllers/graphiteImport.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/controllers/graphiteImport.js b/src/app/controllers/graphiteImport.js index a552cd73560..091f4b8fe5f 100644 --- a/src/app/controllers/graphiteImport.js +++ b/src/app/controllers/graphiteImport.js @@ -73,7 +73,7 @@ function (angular, app, _, kbn) { newDashboard.title = state.name; newDashboard.rows.push(currentRow); - _.each(state.graphs, function(graph) { + _.each(state.graphs, function(graph, index) { if (currentRow.panels.length === graphsPerRow) { currentRow = angular.copy(rowTemplate); newDashboard.rows.push(currentRow); @@ -84,7 +84,8 @@ function (angular, app, _, kbn) { span: 12 / graphsPerRow, title: graph[1].title, targets: [], - datasource: datasource + datasource: datasource, + id: index + 1 }; _.each(graph[1].target, function(target) { From bce6e75cfaf336767b778a3d7a46912c5f35734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 11:35:08 +0200 Subject: [PATCH 5/9] InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id, Fixes #859 --- CHANGELOG.md | 1 + src/app/services/influxdb/influxdbDatasource.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce1108a1c7..92bdd66eca0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations - [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor - [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. +- [Issue #859](https://github.com/grafana/grafana/issues/859). InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id # 1.8.0 (2014-09-22) diff --git a/src/app/services/influxdb/influxdbDatasource.js b/src/app/services/influxdb/influxdbDatasource.js index c076fb2c5e1..8ad003cc632 100644 --- a/src/app/services/influxdb/influxdbDatasource.js +++ b/src/app/services/influxdb/influxdbDatasource.js @@ -203,7 +203,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { else { var self = this; return this._influxRequest('POST', '/series', data).then(function() { - self._removeUnslugifiedDashboard(title, false); + self._removeUnslugifiedDashboard(id, title, false); return { title: title, url: '/dashboard/db/' + id }; }, function(err) { throw 'Failed to save dashboard to InfluxDB: ' + err.data; @@ -211,7 +211,9 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { } }; - InfluxDatasource.prototype._removeUnslugifiedDashboard = function(id, isTemp) { + InfluxDatasource.prototype._removeUnslugifiedDashboard = function(id, title, isTemp) { + if (id === title) { return; } + var self = this; self._getDashboardInternal(id, isTemp).then(function(dashboard) { if (dashboard !== null) { From d5ffe6acef74b2c9bb34e5ff7b9eef2c830668ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 12:14:20 +0200 Subject: [PATCH 6/9] White theme: Fixes for hidden series legend text and disabled annotations color, Closes #852 --- CHANGELOG.md | 1 + src/app/partials/graphite/editor.html | 2 ++ src/app/partials/submenu.html | 7 ------- src/css/less/graph.less | 2 +- src/css/less/submenu.less | 2 +- src/css/less/variables.dark.less | 1 + src/css/less/variables.light.less | 3 ++- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92bdd66eca0..82390a8e88c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor - [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. - [Issue #859](https://github.com/grafana/grafana/issues/859). InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id +- [Issue #852](https://github.com/grafana/grafana/issues/852). White theme: Fixes for hidden series legend text and disabled annotations color # 1.8.0 (2014-09-22) diff --git a/src/app/partials/graphite/editor.html b/src/app/partials/graphite/editor.html index dcbc4306e0f..f54c830d46b 100755 --- a/src/app/partials/graphite/editor.html +++ b/src/app/partials/graphite/editor.html @@ -76,6 +76,7 @@
+
  • @@ -125,6 +126,7 @@
+
diff --git a/src/app/partials/submenu.html b/src/app/partials/submenu.html index 42884a84058..e82e2505afb 100644 --- a/src/app/partials/submenu.html +++ b/src/app/partials/submenu.html @@ -17,9 +17,6 @@
    -
  • - VARIABLES -
  • ${{variable.name}}: @@ -31,10 +28,6 @@
'; }; - kbn.byteFormat = function(size, decimals) { - var ext, steps = 0; - - if(_.isUndefined(decimals)) { - decimals = 2; - } else if (decimals === 0) { - decimals = undefined; - } - - while (Math.abs(size) >= 1024) { - steps++; - size /= 1024; - } - - switch (steps) { - case 0: - ext = " B"; - break; - case 1: - ext = " KiB"; - break; - case 2: - ext = " MiB"; - break; - case 3: - ext = " GiB"; - break; - case 4: - ext = " TiB"; - break; - case 5: - ext = " PiB"; - break; - case 6: - ext = " EiB"; - break; - case 7: - ext = " ZiB"; - break; - case 8: - ext = " YiB"; - break; - } - - return (size.toFixed(decimals) + ext); + kbn.valueFormats.percent = function(size, decimals) { + return kbn.toFixed(size, decimals) + '%'; }; - kbn.bitFormat = function(size, decimals) { - var ext, steps = 0; + kbn.formatFuncCreator = function(factor, extArray) { + return function(size, decimals, scaledDecimals) { + var steps = 0; - if(_.isUndefined(decimals)) { - decimals = 2; - } else if (decimals === 0) { - decimals = undefined; - } + while (Math.abs(size) >= factor) { + steps++; + size /= factor; + } + if (steps > 0) { + decimals = scaledDecimals + (3 * steps); + } - while (Math.abs(size) >= 1024) { - steps++; - size /= 1024; - } - - switch (steps) { - case 0: - ext = " b"; - break; - case 1: - ext = " Kib"; - break; - case 2: - ext = " Mib"; - break; - case 3: - ext = " Gib"; - break; - case 4: - ext = " Tib"; - break; - case 5: - ext = " Pib"; - break; - case 6: - ext = " Eib"; - break; - case 7: - ext = " Zib"; - break; - case 8: - ext = " Yib"; - break; - } - - return (size.toFixed(decimals) + ext); - }; - - kbn.bpsFormat = function(size, decimals) { - var ext, steps = 0; - - if(_.isUndefined(decimals)) { - decimals = 2; - } else if (decimals === 0) { - decimals = undefined; - } - - while (Math.abs(size) >= 1000) { - steps++; - size /= 1000; - } - - switch (steps) { - case 0: - ext = " bps"; - break; - case 1: - ext = " Kbps"; - break; - case 2: - ext = " Mbps"; - break; - case 3: - ext = " Gbps"; - break; - case 4: - ext = " Tbps"; - break; - case 5: - ext = " Pbps"; - break; - case 6: - ext = " Ebps"; - break; - case 7: - ext = " Zbps"; - break; - case 8: - ext = " Ybps"; - break; - } - - return (size.toFixed(decimals) + ext); - }; - - kbn.shortFormat = function(size, decimals) { - var ext, steps = 0; - - if(_.isUndefined(decimals)) { - decimals = 2; - } else if (decimals === 0) { - decimals = undefined; - } - - while (Math.abs(size) >= 1000) { - steps++; - size /= 1000; - } - - switch (steps) { - case 0: - ext = ""; - break; - case 1: - ext = " K"; - break; - case 2: - ext = " Mil"; - break; - case 3: - ext = " Bil"; - break; - case 4: - ext = " Tri"; - break; - case 5: - ext = " Quadr"; - break; - case 6: - ext = " Quint"; - break; - case 7: - ext = " Sext"; - break; - case 8: - ext = " Sept"; - break; - } - - return (size.toFixed(decimals) + ext); + return kbn.toFixed(size, decimals) + extArray[steps]; + }; }; kbn.toFixed = function(value, decimals) { @@ -520,84 +352,87 @@ function($, _, moment) { return formatted; }; - kbn.formatFunctions.ms = function(size, decimals) { + kbn.valueFormats.bits = kbn.formatFuncCreator(1024, [' b', ' Kib', ' Mib', ' Gib', ' Tib', ' Pib', ' Eib', ' Zib', ' Yib']); + kbn.valueFormats.bytes = kbn.formatFuncCreator(1024, [' B', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB']); + kbn.valueFormats.bps = kbn.formatFuncCreator(1000, [' bps', ' Kbps', ' Mbps', ' Gbps', ' Tbps', ' Pbps', ' Ebps', ' Zbps', ' Ybps']); + kbn.valueFormats.short = kbn.formatFuncCreator(1000, ['', ' K', ' Mil', ' Bil', ' Tri', ' Qaudr', ' Quint', ' Sext', ' Sept']); + kbn.valueFormats.none = kbn.toFixed; + + kbn.valueFormats.ms = function(size, decimals, scaledDecimals) { if (Math.abs(size) < 1000) { return kbn.toFixed(size, decimals) + " ms"; } // Less than 1 min else if (Math.abs(size) < 60000) { - return kbn.toFixed(size / 1000, decimals) + " s"; + return kbn.toFixed(size / 1000, scaledDecimals + 3) + " s"; } // Less than 1 hour, devide in minutes else if (Math.abs(size) < 3600000) { - return (size / 60000).toFixed(decimals) + " min"; + return kbn.toFixed(size / 60000, scaledDecimals + 5) + " min"; } // Less than one day, devide in hours else if (Math.abs(size) < 86400000) { - return (size / 3600000).toFixed(decimals) + " hour"; + return kbn.toFixed(size / 3600000, scaledDecimals + 7) + " hour"; } // Less than one year, devide in days else if (Math.abs(size) < 31536000000) { - return (size / 86400000).toFixed(decimals) + " day"; + return kbn.toFixed(size / 86400000, scaledDecimals + 8) + " day"; } - return (size / 31536000000).toFixed(decimals) + " year"; + return kbn.toFixed(size / 31536000000, scaledDecimals + 10) + " year"; }; - kbn.sFormat = function(size, decimals) { + kbn.valueFormats.s = function(size, decimals, scaledDecimals) { if (Math.abs(size) < 600) { - return size.toFixed(decimals) + " s"; + return kbn.toFixed(size, decimals) + " s"; } // Less than 1 hour, devide in minutes else if (Math.abs(size) < 3600) { - return (size / 60).toFixed(decimals) + " min"; + return kbn.toFixed(size / 60, scaledDecimals + 1) + " min"; } // Less than one day, devide in hours else if (Math.abs(size) < 86400) { - return (size / 3600).toFixed(decimals) + " hour"; + return kbn.toFixed(size / 3600, scaledDecimals + 4) + " hour"; } // Less than one week, devide in days else if (Math.abs(size) < 604800) { - return (size / 86400).toFixed(decimals) + " day"; + return kbn.toFixed(size / 86400, scaledDecimals + 5) + " day"; } // Less than one year, devide in week else if (Math.abs(size) < 31536000) { - return (size / 604800).toFixed(decimals) + " week"; + return kbn.toFixed(size / 604800, scaledDecimals + 6) + " week"; } - return (size / 3.15569e7).toFixed(decimals) + " year"; + return kbn.toFixed(size / 3.15569e7, scaledDecimals + 7) + " year"; }; - kbn.microsFormat = function(size, decimals) { + kbn.valueFormats['µs'] = function(size, decimals, scaledDecimals) { if (Math.abs(size) < 1000) { return kbn.toFixed(size, decimals) + " µs"; } else if (Math.abs(size) < 1000000) { - return (size / 1000).toFixed(decimals) + " ms"; + return kbn.toFixed(size / 1000, scaledDecimals + 3) + " ms"; } else { - return (size / 1000000).toFixed(decimals) + " s"; + return kbn.toFixed(size / 1000000, scaledDecimals + 6) + " s"; } }; - kbn.nanosFormat = function(size, decimals) { - if (Math.abs(size) < 1) { - return size.toFixed(decimals) + " ns"; - } - else if (Math.abs(size) < 1000) { - return size.toFixed(0) + " ns"; + kbn.valueFormats.ns = function(size, decimals, scaledDecimals) { + if (Math.abs(size) < 1000) { + return kbn.toFixed(size, decimals) + " ns"; } else if (Math.abs(size) < 1000000) { - return (size / 1000).toFixed(decimals) + " µs"; + return kbn.toFixed(size / 1000, scaledDecimals + 3) + " µs"; } else if (Math.abs(size) < 1000000000) { - return (size / 1000000).toFixed(decimals) + " ms"; + return kbn.toFixed(size / 1000000, scaledDecimals + 6) + " ms"; } else if (Math.abs(size) < 60000000000){ - return (size / 1000000000).toFixed(decimals) + " s"; + return kbn.toFixed(size / 1000000000, scaledDecimals + 9) + " s"; } else { - return (size / 60000000000).toFixed(decimals) + " m"; + return kbn.toFixed(size / 60000000000, scaledDecimals + 12) + " m"; } }; diff --git a/src/app/components/timeSeries.js b/src/app/components/timeSeries.js index 576e8be8e8a..a448a93649c 100644 --- a/src/app/components/timeSeries.js +++ b/src/app/components/timeSeries.js @@ -54,7 +54,7 @@ function (_, kbn) { } }; - TimeSeries.prototype.getFlotPairs = function (fillStyle, yFormats) { + TimeSeries.prototype.getFlotPairs = function (fillStyle) { var result = []; this.color = this.info.color; @@ -107,12 +107,12 @@ function (_, kbn) { return result; }; - TimeSeries.prototype.updateLegendValues = function(formater, decimals) { - this.info.avg = this.info.avg != null ? formater(this.info.avg, decimals) : null; - this.info.current = this.info.current != null ? formater(this.info.current, decimals) : null; - this.info.min = this.info.min != null ? formater(this.info.min, decimals) : null; - this.info.max = this.info.max != null ? formater(this.info.max, decimals) : null; - this.info.total = this.info.total != null ? formater(this.info.total, decimals) : null; + TimeSeries.prototype.updateLegendValues = function(formater, decimals, scaledDecimals) { + this.info.avg = this.info.avg != null ? formater(this.info.avg, decimals, scaledDecimals) : null; + this.info.current = this.info.current != null ? formater(this.info.current, decimals, scaledDecimals) : null; + this.info.min = this.info.min != null ? formater(this.info.min, decimals, scaledDecimals) : null; + this.info.max = this.info.max != null ? formater(this.info.max, decimals, scaledDecimals) : null; + this.info.total = this.info.total != null ? formater(this.info.total, decimals, scaledDecimals) : null; }; return TimeSeries; diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index 53edcf1bc13..df48de89c6f 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -90,12 +90,12 @@ function (angular, $, kbn, moment, _) { function updateLegendValues(plot) { var yaxis = plot.getYAxes(); - console.log('drawSeries', yaxis); for (var i = 0; i < data.length; i++) { var series = data[i]; - var formater = kbn.formatFunctions[scope.panel.y_formats[series.yaxis - 1]]; - series.updateLegendValues(formater, yaxis[series.yaxis - 1].tickDecimals); + var axis = yaxis[series.yaxis - 1]; + var formater = kbn.valueFormats[scope.panel.y_formats[series.yaxis - 1]]; + series.updateLegendValues(formater, axis.tickDecimals, axis.scaledDecimals); } } @@ -327,7 +327,7 @@ function (angular, $, kbn, moment, _) { function configureAxisMode(axis, format) { axis.tickFormatter = function(val, axis) { - return kbn.formatFunctions[format](val, axis.tickDecimals); + return kbn.valueFormats[format](val, axis.tickDecimals, axis.scaledDecimals); }; } @@ -378,7 +378,7 @@ function (angular, $, kbn, moment, _) { value = item.datapoint[1]; } - value = kbn.getFormatFunction(format, 2)(value, item.series.yaxis); + value = kbn.valueFormats[format](value, item.series.yaxis.tickDecimals); timestamp = dashboard.formatDate(item.datapoint[0]); $tooltip.html(group + value + " @ " + timestamp).place_tt(pos.pageX, pos.pageY); diff --git a/src/test/specs/kbn-format-specs.js b/src/test/specs/kbn-format-specs.js index 85807c277ec..e92e6d0ceec 100644 --- a/src/test/specs/kbn-format-specs.js +++ b/src/test/specs/kbn-format-specs.js @@ -3,76 +3,31 @@ define([ ], function(kbn) { 'use strict'; - describe('millisecond formating', function() { + function describeValueFormat(desc, value, tickSize, tickDecimals, result) { - it('should translate 4378634603 as 1.67 years', function() { - var str = kbn.msFormat(4378634603, 2); - expect(str).to.be('50.68 day'); + describe('value format: ' + desc, function() { + it('should translate ' + value + ' as ' + result, function() { + var scaledDecimals = tickDecimals - Math.floor(Math.log(tickSize) / Math.LN10); + var str = kbn.valueFormats[desc](value, tickDecimals, scaledDecimals); + expect(str).to.be(result); + }); }); - it('should translate 3654454 as 1.02 hour', function() { - var str = kbn.msFormat(3654454, 2); - expect(str).to.be('1.02 hour'); - }); + } - it('should not downscale when value is zero', function() { - var str = kbn.msFormat(0, 2); - expect(str).to.be('0.00 ms'); - }); + describeValueFormat('ms', 0.0024, 0.0005, 4, '0.0024 ms'); + describeValueFormat('ms', 100, 1, 0, '100 ms'); + describeValueFormat('ms', 1250, 10, 0, '1.25 s'); + describeValueFormat('ms', 1250, 300, 0, '1.3 s'); + describeValueFormat('ms', 65150, 10000, 0, '1.1 min'); + describeValueFormat('ms', 6515000, 1500000, 0, '1.8 hour'); + describeValueFormat('ms', 651500000, 150000000, 0, '8 day'); + describeValueFormat('none', 2.75e-10, 0, 10, '3e-10'); + describeValueFormat('none', 0, 0, 2, '0'); - it('should translate 365445 as 6.09 min', function() { - var str = kbn.msFormat(365445, 2); - expect(str).to.be('6.09 min'); - }); - - }); - - describe('high negative exponent, issue #696', function() { - it('should ignore decimal correction if exponent', function() { - var str = kbn.getFormatFunction('')(2.75e-10, { tickDecimals: 12 }); - expect(str).to.be('2.75e-10'); - }); - it('should format 0 correctly', function() { - var str = kbn.getFormatFunction('')(0.0, { tickDecimals: 12 }); - expect(str).to.be('0'); - }); - }); - - describe('none format tests', function() { - it('should translate 2 as 2.0000 if axis decimals is 4', function() { - var str = kbn.getFormatFunction('')(2, { tickDecimals: 4 }); - expect(str).to.be('2.0000'); - }); - }); - - describe('nanosecond formatting', function () { - it('should translate 25 to 25 ns', function () { - var str = kbn.nanosFormat(25, 2); - expect(str).to.be("25 ns"); - }); - - it('should translate 2558 to 2.56 µs', function () { - var str = kbn.nanosFormat(2558, 2); - expect(str).to.be("2.56 µs"); - }); - - it('should translate 2558000 to 2.56 ms', function () { - var str = kbn.nanosFormat(2558000, 2); - expect(str).to.be("2.56 ms"); - }); - - it('should translate 2019962000 to 2.02 s', function () { - var str = kbn.nanosFormat(2049962000, 2); - expect(str).to.be("2.05 s"); - }); - - it('should translate 95199620000 to 1.59 m', function () { - var str = kbn.nanosFormat(95199620000, 2); - expect(str).to.be("1.59 m"); - }); - - }); + describeValueFormat('ns', 25, 1, 0, '25 ns'); + describeValueFormat('ns', 2558, 50, 0, '2.56 µs'); describe('calculateInterval', function() { it('1h 100 resultion', function() { diff --git a/src/vendor/jquery/jquery.flot.js b/src/vendor/jquery/jquery.flot.js index c97ceb1bf44..87a1b17c742 100644 --- a/src/vendor/jquery/jquery.flot.js +++ b/src/vendor/jquery/jquery.flot.js @@ -1728,6 +1728,8 @@ Licensed under the MIT license. axis.delta = delta; axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec); axis.tickSize = opts.tickSize || size; + // grafana addition + axis.scaledDecimals = axis.tickDecimals - Math.floor(Math.log(axis.tickSize) / Math.LN10); // Time mode was moved to a plug-in in 0.8, and since so many people use it // we'll add an especially friendly reminder to make sure they included it.