influxdbDatasource.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. define([
  2. 'angular',
  3. 'underscore',
  4. 'kbn',
  5. './influxSeries'
  6. ],
  7. function (angular, _, kbn, InfluxSeries) {
  8. 'use strict';
  9. var module = angular.module('kibana.services');
  10. module.factory('InfluxDatasource', function($q, $http) {
  11. function InfluxDatasource(datasource) {
  12. this.type = 'influxDB';
  13. this.editorSrc = 'app/partials/influxdb/editor.html';
  14. this.urls = datasource.urls;
  15. this.username = datasource.username;
  16. this.password = datasource.password;
  17. this.name = datasource.name;
  18. this.templateSettings = {
  19. interpolate : /\[\[([\s\S]+?)\]\]/g,
  20. };
  21. }
  22. InfluxDatasource.prototype.query = function(filterSrv, options) {
  23. var promises = _.map(options.targets, function(target) {
  24. var query;
  25. var alias = '';
  26. if (target.hide || !((target.series && target.column) || target.query)) {
  27. return [];
  28. }
  29. var timeFilter = getTimeFilter(options);
  30. var groupByField;
  31. if (target.rawQuery) {
  32. query = target.query;
  33. query = query.replace(";", "");
  34. var queryElements = query.split(" ");
  35. var lowerCaseQueryElements = query.toLowerCase().split(" ");
  36. var whereIndex = lowerCaseQueryElements.indexOf("where");
  37. var groupByIndex = lowerCaseQueryElements.indexOf("group");
  38. var orderIndex = lowerCaseQueryElements.indexOf("order");
  39. if (lowerCaseQueryElements[1].indexOf(',') !== -1) {
  40. groupByField = lowerCaseQueryElements[1].replace(',', '');
  41. }
  42. if (whereIndex !== -1) {
  43. queryElements.splice(whereIndex + 1, 0, timeFilter, "and");
  44. }
  45. else {
  46. if (groupByIndex !== -1) {
  47. queryElements.splice(groupByIndex, 0, "where", timeFilter);
  48. }
  49. else if (orderIndex !== -1) {
  50. queryElements.splice(orderIndex, 0, "where", timeFilter);
  51. }
  52. else {
  53. queryElements.push("where");
  54. queryElements.push(timeFilter);
  55. }
  56. }
  57. query = queryElements.join(" ");
  58. query = filterSrv.applyTemplateToTarget(query);
  59. }
  60. else {
  61. var template = "select [[group]][[group_comma]] [[func]]([[column]]) from [[series]] " +
  62. "where [[timeFilter]] [[condition_add]] [[condition_key]] [[condition_op]] [[condition_value]] " +
  63. "group by time([[interval]])[[group_comma]] [[group]] order asc";
  64. var templateData = {
  65. series: target.series,
  66. column: target.column,
  67. func: target.function,
  68. timeFilter: timeFilter,
  69. interval: target.interval || options.interval,
  70. condition_add: target.condition_filter ? 'and' : '',
  71. condition_key: target.condition_filter ? target.condition_key : '',
  72. condition_op: target.condition_filter ? target.condition_op : '',
  73. condition_value: target.condition_filter ? target.condition_value : '',
  74. group_comma: target.groupby_field_add && target.groupby_field ? ',' : '',
  75. group: target.groupby_field_add ? target.groupby_field : '',
  76. };
  77. if(!templateData.series.match('^/.*/')) {
  78. templateData.series = '"' + templateData.series + '"';
  79. }
  80. query = _.template(template, templateData, this.templateSettings);
  81. query = filterSrv.applyTemplateToTarget(query);
  82. if (target.groupby_field_add) {
  83. groupByField = target.groupby_field;
  84. }
  85. target.query = query;
  86. }
  87. if (target.alias) {
  88. alias = filterSrv.applyTemplateToTarget(target.alias);
  89. }
  90. var handleResponse = _.partial(handleInfluxQueryResponse, alias, groupByField);
  91. return this.doInfluxRequest(query, alias).then(handleResponse);
  92. }, this);
  93. return $q.all(promises).then(function(results) {
  94. return { data: _.flatten(results) };
  95. });
  96. };
  97. InfluxDatasource.prototype.listColumns = function(seriesName) {
  98. return this.doInfluxRequest('select * from /' + seriesName + '/ limit 1').then(function(data) {
  99. if (!data) {
  100. return [];
  101. }
  102. return data[0].columns;
  103. });
  104. };
  105. InfluxDatasource.prototype.listSeries = function() {
  106. return this.doInfluxRequest('select * from /.*/ limit 1').then(function(data) {
  107. return _.map(data, function(series) {
  108. return series.name;
  109. });
  110. });
  111. };
  112. InfluxDatasource.prototype.metricFindQuery = function (filterSrv, query) {
  113. var interpolated;
  114. try {
  115. interpolated = filterSrv.applyTemplateToTarget(query);
  116. }
  117. catch (err) {
  118. return $q.reject(err);
  119. }
  120. return this.doInfluxRequest(interpolated)
  121. .then(function (results) {
  122. return _.map(results[0].points, function (metric) {
  123. return {
  124. text: metric[1],
  125. expandable: false
  126. };
  127. });
  128. });
  129. };
  130. function retry(deferred, callback, delay) {
  131. return callback().then(undefined, function(reason) {
  132. if (reason.status !== 0 || reason.status >= 300) {
  133. deferred.reject(reason);
  134. }
  135. else {
  136. setTimeout(function() {
  137. return retry(deferred, callback, Math.min(delay * 2, 30000));
  138. }, delay);
  139. }
  140. });
  141. }
  142. InfluxDatasource.prototype.doInfluxRequest = function(query) {
  143. var _this = this;
  144. var deferred = $q.defer();
  145. retry(deferred, function() {
  146. var currentUrl = _this.urls.shift();
  147. _this.urls.push(currentUrl);
  148. var params = {
  149. u: _this.username,
  150. p: _this.password,
  151. time_precision: 's',
  152. q: query
  153. };
  154. var options = {
  155. method: 'GET',
  156. url: currentUrl + '/series',
  157. params: params,
  158. };
  159. return $http(options).success(function (data) {
  160. deferred.resolve(data);
  161. });
  162. }, 10);
  163. return deferred.promise;
  164. };
  165. function handleInfluxQueryResponse(alias, groupByField, seriesList) {
  166. var influxSeries = new InfluxSeries({
  167. seriesList: seriesList,
  168. alias: alias,
  169. groupByField: groupByField
  170. });
  171. return influxSeries.getTimeSeries();
  172. }
  173. function getTimeFilter(options) {
  174. var from = getInfluxTime(options.range.from);
  175. var until = getInfluxTime(options.range.to);
  176. if (until === 'now()') {
  177. return 'time > now() - ' + from;
  178. }
  179. return 'time > ' + from + ' and time < ' + until;
  180. }
  181. function getInfluxTime(date) {
  182. if (_.isString(date)) {
  183. if (date === 'now') {
  184. return 'now()';
  185. }
  186. else if (date.indexOf('now') >= 0) {
  187. return date.substring(4);
  188. }
  189. date = kbn.parseDate(date);
  190. }
  191. return to_utc_epoch_seconds(date);
  192. }
  193. function to_utc_epoch_seconds(date) {
  194. return (date.getTime() / 1000).toFixed(0) + 's';
  195. }
  196. return InfluxDatasource;
  197. });
  198. });