metric_find_query.ts 4.3 KB

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