completer.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. ///<reference path="../../../headers/common.d.ts" />
  2. import {PrometheusDatasource} from "./datasource";
  3. import _ from 'lodash';
  4. export class PromCompleter {
  5. labelNameCache: any;
  6. identifierRegexps = [/[\[\]a-zA-Z_0-9=]/];
  7. constructor(private datasource: PrometheusDatasource) {
  8. this.labelNameCache = {};
  9. }
  10. getCompletions(editor, session, pos, prefix, callback) {
  11. let token = session.getTokenAt(pos.row, pos.column);
  12. switch (token.type) {
  13. case 'label.name':
  14. var metricName = this.findMetricName(session, pos.row, pos.column);
  15. if (!metricName) {
  16. callback(null, this.transformToCompletions(['__name__', 'instance', 'job']));
  17. return;
  18. }
  19. if (this.labelNameCache[metricName]) {
  20. callback(null, this.labelNameCache[metricName]);
  21. return;
  22. }
  23. var op = '=~';
  24. if (/[a-zA-Z_:][a-zA-Z0-9_:]*/.test(metricName)) {
  25. op = '=';
  26. }
  27. var expr = '{__name__' + op + '"' + metricName + '"}';
  28. this.datasource.performInstantQuery({ expr: expr }, new Date().getTime() / 1000).then(response => {
  29. var labelNames = this.transformToCompletions(
  30. _.uniq(_.flatten(response.data.data.result.map(r => {
  31. return Object.keys(r.metric);
  32. })))
  33. );
  34. this.labelNameCache[metricName] = labelNames;
  35. callback(null, labelNames);
  36. });
  37. return;
  38. case 'label.value':
  39. callback(null, []);
  40. return;
  41. }
  42. if (prefix === '[') {
  43. var vectors = [];
  44. for (let unit of ['s', 'm', 'h']) {
  45. for (let value of [1,5,10,30]) {
  46. vectors.push({caption: value+unit, value: '['+value+unit, meta: 'range vector'});
  47. }
  48. }
  49. callback(null, vectors);
  50. return;
  51. }
  52. var query = prefix;
  53. var line = editor.session.getLine(pos.row);
  54. return this.datasource.performSuggestQuery(query, true).then(metricNames => {
  55. callback(null, metricNames.map(name => {
  56. let value = name;
  57. if (prefix === '(') {
  58. value = '(' + name;
  59. }
  60. return {
  61. caption: name,
  62. value: value,
  63. meta: 'metric',
  64. };
  65. }));
  66. });
  67. }
  68. transformToCompletions(words) {
  69. return words.map(name => {
  70. return {
  71. caption: name,
  72. value: name,
  73. meta: "label name",
  74. score: Number.MAX_VALUE
  75. };
  76. });
  77. }
  78. findMetricName(session, row, column) {
  79. var metricName = '';
  80. var tokens;
  81. var nameLabelNameToken = this.findToken(session, row, column, 'label.name', '__name__', 'paren.lparen');
  82. if (nameLabelNameToken) {
  83. tokens = session.getTokens(nameLabelNameToken.row);
  84. var nameLabelValueToken = tokens[nameLabelNameToken.index + 2];
  85. if (nameLabelValueToken && nameLabelValueToken.type === 'label.value') {
  86. metricName = nameLabelValueToken.value.slice(1, -1); // cut begin/end quotation
  87. }
  88. } else {
  89. var metricNameToken = this.findToken(session, row, column, 'identifier', null, null);
  90. if (metricNameToken) {
  91. tokens = session.getTokens(metricNameToken.row);
  92. if (tokens[metricNameToken.index + 1].type === 'paren.lparen') {
  93. metricName = metricNameToken.value;
  94. }
  95. }
  96. }
  97. return metricName;
  98. }
  99. findToken(session, row, column, target, value, guard) {
  100. var tokens, idx;
  101. for (var r = row; r >= 0; r--) {
  102. tokens = session.getTokens(r);
  103. if (r === row) { // current row
  104. var c = 0;
  105. for (idx = 0; idx < tokens.length; idx++) {
  106. c += tokens[idx].value.length;
  107. if (c >= column) {
  108. break;
  109. }
  110. }
  111. } else {
  112. idx = tokens.length - 1;
  113. }
  114. for (; idx >= 0; idx--) {
  115. if (tokens[idx].type === guard) {
  116. return null;
  117. }
  118. if (tokens[idx].type === target
  119. && (!value || tokens[idx].value === value)) {
  120. tokens[idx].row = r;
  121. tokens[idx].index = idx;
  122. return tokens[idx];
  123. }
  124. }
  125. }
  126. return null;
  127. }
  128. }