| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- ///<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;
- }
- }
|