grafana/public/app/plugins/datasource/prometheus/completer.ts

189 lines
5.4 KiB
TypeScript
Raw Normal View History

///<reference path="../../../headers/common.d.ts" />
import {PrometheusDatasource} from "./datasource";
import _ from 'lodash';
export class PromCompleter {
labelQueryCache: any;
labelNameCache: any;
labelValueCache: any;
2017-10-17 05:26:16 -05:00
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) {
2017-09-11 19:31:05 -05:00
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;
}
2017-10-07 15:05:31 -05:00
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);
});
2017-09-11 19:31:05 -05:00
case 'string.quoted':
metricName = this.findMetricName(session, pos.row, pos.column);
if (!metricName) {
callback(null, []);
return;
}
2017-09-11 19:31:05 -05:00
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;
}
2017-10-07 15:05:31 -05:00
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 (prefix === '[') {
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'});
}
}
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;
2017-09-11 19:31:05 -05:00
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];
2017-09-11 19:31:05 -05:00
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;
}
}