metric_find_query.ts 4.8 KB

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