module.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. define([
  2. 'angular',
  3. 'app',
  4. 'jquery',
  5. 'lodash',
  6. 'kbn',
  7. 'moment',
  8. 'components/timeSeries',
  9. './seriesOverridesCtrl',
  10. 'services/panelSrv',
  11. 'services/annotationsSrv',
  12. 'services/datasourceSrv',
  13. 'jquery.flot',
  14. 'jquery.flot.events',
  15. 'jquery.flot.selection',
  16. 'jquery.flot.time',
  17. 'jquery.flot.stack',
  18. 'jquery.flot.stackpercent',
  19. 'jquery.flot.fillbelow',
  20. 'jquery.flot.crosshair'
  21. ],
  22. function (angular, app, $, _, kbn, moment, TimeSeries) {
  23. 'use strict';
  24. var module = angular.module('grafana.panels.graph');
  25. app.useModule(module);
  26. module.controller('GraphCtrl', function($scope, $rootScope, panelSrv, annotationsSrv, timeSrv) {
  27. $scope.panelMeta = {
  28. editorTabs: [],
  29. fullEditorTabs : [
  30. {
  31. title: 'General',
  32. src:'app/partials/panelgeneral.html'
  33. },
  34. {
  35. title: 'Metrics',
  36. src:'app/partials/metrics.html'
  37. },
  38. {
  39. title:'Axes & Grid',
  40. src:'app/panels/graph/axisEditor.html'
  41. },
  42. {
  43. title:'Display Styles',
  44. src:'app/panels/graph/styleEditor.html'
  45. }
  46. ],
  47. fullscreenEdit: true,
  48. fullscreenView: true,
  49. description : "Graphing"
  50. };
  51. // Set and populate defaults
  52. var _d = {
  53. datasource: null,
  54. /** @scratch /panels/histogram/3
  55. * renderer:: sets client side (flot) or native graphite png renderer (png)
  56. */
  57. renderer: 'flot',
  58. /** @scratch /panels/histogram/3
  59. * x-axis:: Show the x-axis
  60. */
  61. 'x-axis' : true,
  62. /** @scratch /panels/histogram/3
  63. * y-axis:: Show the y-axis
  64. */
  65. 'y-axis' : true,
  66. /** @scratch /panels/histogram/3
  67. * scale:: Scale the y-axis by this factor
  68. */
  69. scale : 1,
  70. /** @scratch /panels/histogram/3
  71. * y_formats :: 'none','bytes','bits','bps','short', 's', 'ms'
  72. */
  73. y_formats : ['short', 'short'],
  74. /** @scratch /panels/histogram/5
  75. * grid object:: Min and max y-axis values
  76. * grid.min::: Minimum y-axis value
  77. * grid.ma1::: Maximum y-axis value
  78. */
  79. grid : {
  80. leftMax: null,
  81. rightMax: null,
  82. leftMin: null,
  83. rightMin: null,
  84. threshold1: null,
  85. threshold2: null,
  86. threshold1Color: 'rgba(216, 200, 27, 0.27)',
  87. threshold2Color: 'rgba(234, 112, 112, 0.22)'
  88. },
  89. annotate : {
  90. enable : false,
  91. },
  92. /** @scratch /panels/histogram/3
  93. * resolution:: If auto_int is true, shoot for this many bars.
  94. */
  95. resolution : 100,
  96. /** @scratch /panels/histogram/3
  97. * ==== Drawing options
  98. * lines:: Show line chart
  99. */
  100. lines : true,
  101. /** @scratch /panels/histogram/3
  102. * fill:: Area fill factor for line charts, 1-10
  103. */
  104. fill : 0,
  105. /** @scratch /panels/histogram/3
  106. * linewidth:: Weight of lines in pixels
  107. */
  108. linewidth : 1,
  109. /** @scratch /panels/histogram/3
  110. * points:: Show points on chart
  111. */
  112. points : false,
  113. /** @scratch /panels/histogram/3
  114. * pointradius:: Size of points in pixels
  115. */
  116. pointradius : 5,
  117. /** @scratch /panels/histogram/3
  118. * bars:: Show bars on chart
  119. */
  120. bars : false,
  121. /** @scratch /panels/histogram/3
  122. * stack:: Stack multiple series
  123. */
  124. stack : false,
  125. /** @scratch /panels/histogram/3
  126. * legend:: Display the legend
  127. */
  128. legend: {
  129. show: true, // disable/enable legend
  130. values: false, // disable/enable legend values
  131. min: false,
  132. max: false,
  133. current: false,
  134. total: false,
  135. avg: false
  136. },
  137. /** @scratch /panels/histogram/3
  138. * ==== Transformations
  139. /** @scratch /panels/histogram/3
  140. * percentage:: Show the y-axis as a percentage of the axis total. Only makes sense for multiple
  141. * queries
  142. */
  143. percentage : false,
  144. nullPointMode : 'connected',
  145. steppedLine: false,
  146. tooltip : {
  147. value_type: 'cumulative',
  148. shared: false,
  149. },
  150. targets: [{}],
  151. aliasColors: {},
  152. seriesOverrides: [],
  153. };
  154. _.defaults($scope.panel,_d);
  155. _.defaults($scope.panel.tooltip, _d.tooltip);
  156. _.defaults($scope.panel.annotate, _d.annotate);
  157. _.defaults($scope.panel.grid, _d.grid);
  158. _.defaults($scope.panel.legend, _d.legend);
  159. $scope.hiddenSeries = {};
  160. $scope.updateTimeRange = function () {
  161. $scope.range = timeSrv.timeRange();
  162. $scope.rangeUnparsed = timeSrv.timeRange(false);
  163. $scope.resolution = Math.ceil($(window).width() * ($scope.panel.span / 12));
  164. $scope.interval = kbn.calculateInterval($scope.range, $scope.resolution, $scope.panel.interval);
  165. };
  166. $scope.get_data = function() {
  167. $scope.updateTimeRange();
  168. var metricsQuery = {
  169. range: $scope.rangeUnparsed,
  170. interval: $scope.interval,
  171. targets: $scope.panel.targets,
  172. format: $scope.panel.renderer === 'png' ? 'png' : 'json',
  173. maxDataPoints: $scope.resolution,
  174. cacheTimeout: $scope.panel.cacheTimeout
  175. };
  176. $scope.annotationsPromise = annotationsSrv.getAnnotations($scope.rangeUnparsed, $scope.dashboard);
  177. return $scope.datasource.query(metricsQuery)
  178. .then($scope.dataHandler)
  179. .then(null, function(err) {
  180. $scope.panelMeta.loading = false;
  181. $scope.panelMeta.error = err.message || "Timeseries data request error";
  182. $scope.inspector.error = err;
  183. $scope.legend = [];
  184. $scope.render([]);
  185. });
  186. };
  187. $scope.dataHandler = function(results) {
  188. $scope.panelMeta.loading = false;
  189. $scope.legend = [];
  190. // png renderer returns just a url
  191. if (_.isString(results)) {
  192. $scope.render(results);
  193. return;
  194. }
  195. $scope.datapointsWarning = false;
  196. $scope.datapointsCount = 0;
  197. $scope.datapointsOutside = false;
  198. var data = _.map(results.data, $scope.seriesHandler);
  199. $scope.datapointsWarning = $scope.datapointsCount === 0 || $scope.datapointsOutside;
  200. $scope.annotationsPromise
  201. .then(function(annotations) {
  202. data.annotations = annotations;
  203. $scope.render(data);
  204. }, function() {
  205. $scope.render(data);
  206. });
  207. };
  208. $scope.seriesHandler = function(seriesData, index) {
  209. var datapoints = seriesData.datapoints;
  210. var alias = seriesData.target;
  211. var color = $scope.panel.aliasColors[alias] || $rootScope.colors[index];
  212. var seriesInfo = {
  213. alias: alias,
  214. color: color,
  215. };
  216. $scope.legend.push(seriesInfo);
  217. var series = new TimeSeries({
  218. datapoints: datapoints,
  219. info: seriesInfo,
  220. });
  221. if (datapoints && datapoints.length > 0) {
  222. var last = moment.utc(datapoints[datapoints.length - 1][1] * 1000);
  223. var from = moment.utc($scope.range.from);
  224. if (last - from < -10000) {
  225. $scope.datapointsOutside = true;
  226. }
  227. $scope.datapointsCount += datapoints.length;
  228. }
  229. return series;
  230. };
  231. $scope.render = function(data) {
  232. $scope.$emit('render', data);
  233. };
  234. $scope.changeSeriesColor = function(series, color) {
  235. series.color = color;
  236. $scope.panel.aliasColors[series.alias] = series.color;
  237. $scope.render();
  238. };
  239. $scope.toggleSeries = function(serie, event) {
  240. if (event.ctrlKey || event.metaKey || event.shiftKey) {
  241. if ($scope.hiddenSeries[serie.alias]) {
  242. delete $scope.hiddenSeries[serie.alias];
  243. }
  244. else {
  245. $scope.hiddenSeries[serie.alias] = true;
  246. }
  247. } else {
  248. $scope.toggleSeriesExclusiveMode(serie);
  249. }
  250. $scope.$emit('toggleLegend', $scope.legend);
  251. };
  252. $scope.toggleSeriesExclusiveMode = function(serie) {
  253. var hidden = $scope.hiddenSeries;
  254. if (hidden[serie.alias]) {
  255. delete hidden[serie.alias];
  256. }
  257. // check if every other series is hidden
  258. var alreadyExclusive = _.every($scope.legend, function(value) {
  259. if (value.alias === serie.alias) {
  260. return true;
  261. }
  262. return hidden[value.alias];
  263. });
  264. if (alreadyExclusive) {
  265. // remove all hidden series
  266. _.each($scope.legend, function(value) {
  267. delete $scope.hiddenSeries[value.alias];
  268. });
  269. }
  270. else {
  271. // hide all but this serie
  272. _.each($scope.legend, function(value) {
  273. if (value.alias === serie.alias) {
  274. return;
  275. }
  276. $scope.hiddenSeries[value.alias] = true;
  277. });
  278. }
  279. };
  280. $scope.toggleYAxis = function(info) {
  281. var override = _.findWhere($scope.panel.seriesOverrides, { alias: info.alias });
  282. if (!override) {
  283. override = { alias: info.alias };
  284. $scope.panel.seriesOverrides.push(override);
  285. }
  286. override.yaxis = info.yaxis === 2 ? 1 : 2;
  287. $scope.render();
  288. };
  289. $scope.toggleGridMinMax = function(key) {
  290. $scope.panel.grid[key] = _.toggle($scope.panel.grid[key], null, 0);
  291. $scope.render();
  292. };
  293. $scope.addSeriesOverride = function(override) {
  294. $scope.panel.seriesOverrides.push(override || {});
  295. };
  296. $scope.removeSeriesOverride = function(override) {
  297. $scope.panel.seriesOverrides = _.without($scope.panel.seriesOverrides, override);
  298. $scope.render();
  299. };
  300. panelSrv.init($scope);
  301. });
  302. });