metricKeys.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. define([
  2. 'angular',
  3. 'lodash',
  4. 'config'
  5. ],
  6. function (angular, _, config) {
  7. 'use strict';
  8. var module = angular.module('grafana.controllers');
  9. module.controller('MetricKeysCtrl', function($scope, $http, $q) {
  10. var elasticSearchUrlForMetricIndex = config.elasticsearch + '/' + config.grafana_metrics_index + '/';
  11. var httpOptions = {};
  12. if (config.elasticsearchBasicAuth) {
  13. httpOptions.withCredentials = true;
  14. httpOptions.headers = {
  15. "Authorization": "Basic " + config.elasticsearchBasicAuth
  16. };
  17. }
  18. $scope.init = function () {
  19. $scope.metricPath = "prod.apps.api.boobarella.*";
  20. $scope.metricCounter = 0;
  21. };
  22. $scope.createIndex = function () {
  23. $scope.errorText = null;
  24. $scope.infoText = null;
  25. deleteIndex()
  26. .then(createIndex)
  27. .then(function () {
  28. $scope.infoText = "Index created!";
  29. })
  30. .then(null, function (err) {
  31. $scope.errorText = angular.toJson(err);
  32. });
  33. };
  34. $scope.loadMetricsFromPath = function() {
  35. $scope.errorText = null;
  36. $scope.infoText = null;
  37. $scope.metricCounter = 0;
  38. return loadMetricsRecursive($scope.metricPath)
  39. .then(function() {
  40. $scope.infoText = "Indexing completed!";
  41. }, function(err) {
  42. $scope.errorText = "Error: " + err;
  43. });
  44. };
  45. $scope.loadAll = function() {
  46. $scope.infoText = "Fetching all metrics from graphite...";
  47. getFromEachGraphite('/metrics/index.json', saveMetricsArray)
  48. .then(function() {
  49. $scope.infoText = "Indexing complete!";
  50. }).then(null, function(err) {
  51. $scope.errorText = err;
  52. });
  53. };
  54. function getFromEachGraphite(request, data_callback, error_callback) {
  55. return $q.all(_.map(config.datasources, function(datasource) {
  56. if (datasource.type = 'graphite') {
  57. return $http.get(datasource.url + request)
  58. .then(data_callback, error_callback);
  59. }
  60. }));
  61. }
  62. function saveMetricsArray(data, currentIndex) {
  63. if (!data && !data.data && data.data.length === 0) {
  64. return $q.reject('No metrics from graphite');
  65. }
  66. if (data.data.length === currentIndex) {
  67. return $q.when('done');
  68. }
  69. currentIndex = currentIndex || 0;
  70. return saveMetricKey(data.data[currentIndex])
  71. .then(function() {
  72. return saveMetricsArray(data, currentIndex + 1);
  73. });
  74. }
  75. function deleteIndex()
  76. {
  77. var deferred = $q.defer();
  78. $http.delete(elasticSearchUrlForMetricIndex, httpOptions)
  79. .success(function() {
  80. deferred.resolve('ok');
  81. })
  82. .error(function(data, status) {
  83. if (status === 404) {
  84. deferred.resolve('ok');
  85. }
  86. else {
  87. deferred.reject('elastic search returned unexpected error');
  88. }
  89. });
  90. return deferred.promise;
  91. }
  92. function createIndex()
  93. {
  94. return $http.put(elasticSearchUrlForMetricIndex, {
  95. settings: {
  96. analysis: {
  97. analyzer: {
  98. metric_path_ngram : { tokenizer : "my_ngram_tokenizer" }
  99. },
  100. tokenizer: {
  101. my_ngram_tokenizer : {
  102. type : "nGram",
  103. min_gram : "3",
  104. max_gram : "8",
  105. token_chars: ["letter", "digit", "punctuation", "symbol"]
  106. }
  107. }
  108. }
  109. },
  110. mappings: {
  111. metricKey: {
  112. properties: {
  113. metricPath: {
  114. type: "multi_field",
  115. fields: {
  116. "metricPath": { type: "string", index: "analyzed", index_analyzer: "standard" },
  117. "metricPath_ng": { type: "string", index: "analyzed", index_analyzer: "metric_path_ngram" }
  118. }
  119. }
  120. }
  121. }
  122. }
  123. }, httpOptions);
  124. }
  125. function receiveMetric(result) {
  126. var data = result.data;
  127. if (!data || data.length === 0) {
  128. console.log('no data');
  129. return;
  130. }
  131. var funcs = _.map(data, function(metric) {
  132. if (metric.expandable) {
  133. return loadMetricsRecursive(metric.id + ".*");
  134. }
  135. if (metric.leaf) {
  136. return saveMetricKey(metric.id);
  137. }
  138. });
  139. return $q.all(funcs);
  140. }
  141. function saveMetricKey(metricId) {
  142. // Create request with id as title. Rethink this.
  143. var request = $scope.ejs.Document(config.grafana_metrics_index, 'metricKey', metricId).source({
  144. metricPath: metricId
  145. });
  146. return request.doIndex(
  147. function() {
  148. $scope.infoText = "Indexing " + metricId;
  149. $scope.metricCounter = $scope.metricCounter + 1;
  150. },
  151. function() {
  152. $scope.errorText = "failed to save metric " + metricId;
  153. }
  154. );
  155. }
  156. function loadMetricsRecursive(metricPath)
  157. {
  158. return getFromEachGraphite('/metrics/find/?query=' + metricPath, receiveMetric);
  159. }
  160. });
  161. });