| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- ///<reference path="../../../headers/common.d.ts" />
- import {PrometheusDatasource} from "./datasource";
- import _ from 'lodash';
- export class PromCompleter {
- labelQueryCache: any;
- labelNameCache: any;
- labelValueCache: any;
- identifierRegexps = [/\[/, /[a-zA-Z0-9_:]/];
- constructor(private datasource: PrometheusDatasource) {
- this.labelQueryCache = {};
- this.labelNameCache = {};
- this.labelValueCache = {};
- }
- getCompletions(editor, session, pos, prefix, callback) {
- let token = session.getTokenAt(pos.row, pos.column);
- var metricName;
- switch (token.type) {
- case 'entity.name.tag':
- metricName = this.findMetricName(session, pos.row, pos.column);
- if (!metricName) {
- callback(null, this.transformToCompletions(['__name__', 'instance', 'job'], 'label name'));
- return;
- }
- if (this.labelNameCache[metricName]) {
- callback(null, this.labelNameCache[metricName]);
- return;
- }
- return this.getLabelNameAndValueForMetric(metricName).then(result => {
- var labelNames = this.transformToCompletions(
- _.uniq(_.flatten(result.map(r => {
- return Object.keys(r.metric);
- })))
- , 'label name');
- this.labelNameCache[metricName] = labelNames;
- callback(null, labelNames);
- });
- case 'string.quoted':
- metricName = this.findMetricName(session, pos.row, pos.column);
- if (!metricName) {
- callback(null, []);
- return;
- }
- var labelNameToken = this.findToken(session, pos.row, pos.column, 'entity.name.tag', null, 'paren.lparen');
- if (!labelNameToken) {
- callback(null, []);
- return;
- }
- var labelName = labelNameToken.value;
- if (this.labelValueCache[metricName] && this.labelValueCache[metricName][labelName]) {
- callback(null, this.labelValueCache[metricName][labelName]);
- return;
- }
- return this.getLabelNameAndValueForMetric(metricName).then(result => {
- var labelValues = this.transformToCompletions(
- _.uniq(result.map(r => {
- return r.metric[labelName];
- }))
- , 'label value');
- this.labelValueCache[metricName] = this.labelValueCache[metricName] || {};
- this.labelValueCache[metricName][labelName] = labelValues;
- callback(null, labelValues);
- });
- }
- if (token.type === 'paren.lparen' && token.value === '[') {
- var vectors = [];
- for (let unit of ['s', 'm', 'h']) {
- for (let value of [1,5,10,30]) {
- vectors.push({caption: value+unit, value: '['+value+unit, meta: 'range vector'});
- }
- }
- vectors.push({caption: '$__interval', value: '[$__interval', meta: 'range vector'});
- vectors.push({caption: '$__interval_ms', value: '[$__interval_ms', meta: 'range vector'});
- callback(null, vectors);
- return;
- }
- var query = prefix;
- return this.datasource.performSuggestQuery(query, true).then(metricNames => {
- callback(null, metricNames.map(name => {
- let value = name;
- if (prefix === '(') {
- value = '(' + name;
- }
- return {
- caption: name,
- value: value,
- meta: 'metric',
- };
- }));
- });
- }
- getLabelNameAndValueForMetric(metricName) {
- if (this.labelQueryCache[metricName]) {
- return Promise.resolve(this.labelQueryCache[metricName]);
- }
- var op = '=~';
- if (/[a-zA-Z_:][a-zA-Z0-9_:]*/.test(metricName)) {
- op = '=';
- }
- var expr = '{__name__' + op + '"' + metricName + '"}';
- return this.datasource.performInstantQuery({ expr: expr }, new Date().getTime() / 1000).then(response => {
- this.labelQueryCache[metricName] = response.data.data.result;
- return response.data.data.result;
- });
- }
- transformToCompletions(words, meta) {
- return words.map(name => {
- return {
- caption: name,
- value: name,
- meta: meta,
- score: Number.MAX_VALUE
- };
- });
- }
- findMetricName(session, row, column) {
- var metricName = '';
- var tokens;
- var nameLabelNameToken = this.findToken(session, row, column, 'entity.name.tag', '__name__', 'paren.lparen');
- if (nameLabelNameToken) {
- tokens = session.getTokens(nameLabelNameToken.row);
- var nameLabelValueToken = tokens[nameLabelNameToken.index + 2];
- if (nameLabelValueToken && nameLabelValueToken.type === 'string.quoted') {
- metricName = nameLabelValueToken.value.slice(1, -1); // cut begin/end quotation
- }
- } else {
- var metricNameToken = this.findToken(session, row, column, 'identifier', null, null);
- if (metricNameToken) {
- tokens = session.getTokens(metricNameToken.row);
- if (tokens[metricNameToken.index + 1].type === 'paren.lparen') {
- metricName = metricNameToken.value;
- }
- }
- }
- return metricName;
- }
- findToken(session, row, column, target, value, guard) {
- var tokens, idx;
- for (var r = row; r >= 0; r--) {
- tokens = session.getTokens(r);
- if (r === row) { // current row
- var c = 0;
- for (idx = 0; idx < tokens.length; idx++) {
- c += tokens[idx].value.length;
- if (c >= column) {
- break;
- }
- }
- } else {
- idx = tokens.length - 1;
- }
- for (; idx >= 0; idx--) {
- if (tokens[idx].type === guard) {
- return null;
- }
- if (tokens[idx].type === target
- && (!value || tokens[idx].value === value)) {
- tokens[idx].row = r;
- tokens[idx].index = idx;
- return tokens[idx];
- }
- }
- }
- return null;
- }
- }
|