metric_find_query.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import _ from 'lodash';
  2. export default class PrometheusMetricFindQuery {
  3. datasource: any;
  4. query: any;
  5. range: any;
  6. constructor(datasource, query, timeSrv) {
  7. this.datasource = datasource;
  8. this.query = query;
  9. this.range = timeSrv.timeRange();
  10. }
  11. process() {
  12. const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]+)\)\s*$/;
  13. const metricNamesRegex = /^metrics\((.+)\)\s*$/;
  14. const queryResultRegex = /^query_result\((.+)\)\s*$/;
  15. const labelValuesQuery = this.query.match(labelValuesRegex);
  16. if (labelValuesQuery) {
  17. if (labelValuesQuery[1]) {
  18. return this.labelValuesQuery(labelValuesQuery[2], labelValuesQuery[1]);
  19. } else {
  20. return this.labelValuesQuery(labelValuesQuery[2], null);
  21. }
  22. }
  23. const metricNamesQuery = this.query.match(metricNamesRegex);
  24. if (metricNamesQuery) {
  25. return this.metricNameQuery(metricNamesQuery[1]);
  26. }
  27. const queryResultQuery = this.query.match(queryResultRegex);
  28. if (queryResultQuery) {
  29. return this.queryResultQuery(queryResultQuery[1]);
  30. }
  31. // if query contains full metric name, return metric name and label list
  32. return this.metricNameAndLabelsQuery(this.query);
  33. }
  34. labelValuesQuery(label, metric) {
  35. let url;
  36. if (!metric) {
  37. // return label values globally
  38. url = '/api/v1/label/' + label + '/values';
  39. return this.datasource.metadataRequest(url).then(function(result) {
  40. return _.map(result.data.data, function(value) {
  41. return { text: value };
  42. });
  43. });
  44. } else {
  45. const start = this.datasource.getPrometheusTime(this.range.from, false);
  46. const end = this.datasource.getPrometheusTime(this.range.to, true);
  47. url = '/api/v1/series?match[]=' + encodeURIComponent(metric) + '&start=' + start + '&end=' + end;
  48. return this.datasource.metadataRequest(url).then(function(result) {
  49. const _labels = _.map(result.data.data, function(metric) {
  50. return metric[label] || '';
  51. }).filter(function(label) {
  52. return label !== '';
  53. });
  54. return _.uniq(_labels).map(function(metric) {
  55. return {
  56. text: metric,
  57. expandable: true,
  58. };
  59. });
  60. });
  61. }
  62. }
  63. metricNameQuery(metricFilterPattern) {
  64. const url = '/api/v1/label/__name__/values';
  65. return this.datasource.metadataRequest(url).then(function(result) {
  66. return _.chain(result.data.data)
  67. .filter(function(metricName) {
  68. const r = new RegExp(metricFilterPattern);
  69. return r.test(metricName);
  70. })
  71. .map(function(matchedMetricName) {
  72. return {
  73. text: matchedMetricName,
  74. expandable: true,
  75. };
  76. })
  77. .value();
  78. });
  79. }
  80. queryResultQuery(query) {
  81. const end = this.datasource.getPrometheusTime(this.range.to, true);
  82. return this.datasource.performInstantQuery({ expr: query }, end).then(function(result) {
  83. return _.map(result.data.data.result, function(metricData) {
  84. let text = metricData.metric.__name__ || '';
  85. delete metricData.metric.__name__;
  86. text +=
  87. '{' +
  88. _.map(metricData.metric, function(v, k) {
  89. return k + '="' + v + '"';
  90. }).join(',') +
  91. '}';
  92. text += ' ' + metricData.value[1] + ' ' + metricData.value[0] * 1000;
  93. return {
  94. text: text,
  95. expandable: true,
  96. };
  97. });
  98. });
  99. }
  100. metricNameAndLabelsQuery(query) {
  101. const start = this.datasource.getPrometheusTime(this.range.from, false);
  102. const end = this.datasource.getPrometheusTime(this.range.to, true);
  103. const url = '/api/v1/series?match[]=' + encodeURIComponent(query) + '&start=' + start + '&end=' + end;
  104. const self = this;
  105. return this.datasource.metadataRequest(url).then(function(result) {
  106. return _.map(result.data.data, metric => {
  107. return {
  108. text: self.datasource.getOriginalMetricName(metric),
  109. expandable: true,
  110. };
  111. });
  112. });
  113. }
  114. }