From c6fa0b90a703ff679a9bf087fffaab4a93e1cc76 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Fri, 16 Mar 2018 02:17:51 +0900 Subject: [PATCH] prometheus editor: variable autocomplete support (PR #9988) * prometheus ace editor, template variable support * minor fix * support [[var]] notation * don't remove last ] if token type is string * Revert "don't remove last ] if token type is string" This reverts commit bce5b2d56e7d01a63b756b2b989ee9796bcc6711. * Revert "support [[var]] notation" This reverts commit 10012f8ffe8cfbec62c37d7e99c7758c8a86ab6d. * fix token type and regex --- .../datasource/prometheus/completer.ts | 26 ++++++++++++++----- .../datasource/prometheus/mode-prometheus.js | 3 +++ .../datasource/prometheus/query_ctrl.ts | 2 +- .../prometheus/specs/completer_specs.ts | 17 +++++++++++- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/completer.ts b/public/app/plugins/datasource/prometheus/completer.ts index b3ba1ba1b99..0a974378cde 100644 --- a/public/app/plugins/datasource/prometheus/completer.ts +++ b/public/app/plugins/datasource/prometheus/completer.ts @@ -5,32 +5,46 @@ export class PromCompleter { labelQueryCache: any; labelNameCache: any; labelValueCache: any; + templateVariableCompletions: any; identifierRegexps = [/\[/, /[a-zA-Z0-9_:]/]; - constructor(private datasource: PrometheusDatasource) { + constructor(private datasource: PrometheusDatasource, private templateSrv) { this.labelQueryCache = {}; this.labelNameCache = {}; this.labelValueCache = {}; + this.templateVariableCompletions = this.templateSrv.variables.map(variable => { + return { + caption: '$' + variable.name, + value: '$' + variable.name, + meta: 'variable', + score: Number.MAX_VALUE, + }; + }); } getCompletions(editor, session, pos, prefix, callback) { + let wrappedCallback = (err, completions) => { + completions = completions.concat(this.templateVariableCompletions); + return callback(err, completions); + }; + let token = session.getTokenAt(pos.row, pos.column); switch (token.type) { case 'entity.name.tag.label-matcher': this.getCompletionsForLabelMatcherName(session, pos).then(completions => { - callback(null, completions); + wrappedCallback(null, completions); }); return; case 'string.quoted.label-matcher': this.getCompletionsForLabelMatcherValue(session, pos).then(completions => { - callback(null, completions); + wrappedCallback(null, completions); }); return; case 'entity.name.tag.label-list-matcher': this.getCompletionsForBinaryOperator(session, pos).then(completions => { - callback(null, completions); + wrappedCallback(null, completions); }); return; } @@ -59,14 +73,14 @@ export class PromCompleter { meta: 'range vector', }); - callback(null, vectors); + wrappedCallback(null, vectors); return; } var query = prefix; return this.datasource.performSuggestQuery(query, true).then(metricNames => { - callback( + wrappedCallback( null, metricNames.map(name => { let value = name; diff --git a/public/app/plugins/datasource/prometheus/mode-prometheus.js b/public/app/plugins/datasource/prometheus/mode-prometheus.js index f49c39c698c..3989b590638 100644 --- a/public/app/plugins/datasource/prometheus/mode-prometheus.js +++ b/public/app/plugins/datasource/prometheus/mode-prometheus.js @@ -50,6 +50,9 @@ var PrometheusHighlightRules = function() { token : "keyword.control", regex : "by|without|on|ignoring|group_left|group_right", next : "start-label-list-matcher" + }, { + token : "variable", + regex : "\\$[A-Za-z0-9_]+" }, { token : keywordMapper, regex : "[a-zA-Z_:][a-zA-Z0-9_:]*" diff --git a/public/app/plugins/datasource/prometheus/query_ctrl.ts b/public/app/plugins/datasource/prometheus/query_ctrl.ts index ea5588b253a..3ff8006eaa6 100644 --- a/public/app/plugins/datasource/prometheus/query_ctrl.ts +++ b/public/app/plugins/datasource/prometheus/query_ctrl.ts @@ -43,7 +43,7 @@ class PrometheusQueryCtrl extends QueryCtrl { } getCompleter(query) { - return new PromCompleter(this.datasource); + return new PromCompleter(this.datasource, this.templateSrv); } getDefaultFormat() { diff --git a/public/app/plugins/datasource/prometheus/specs/completer_specs.ts b/public/app/plugins/datasource/prometheus/specs/completer_specs.ts index c736351c36b..b1c1691c0b8 100644 --- a/public/app/plugins/datasource/prometheus/specs/completer_specs.ts +++ b/public/app/plugins/datasource/prometheus/specs/completer_specs.ts @@ -1,9 +1,13 @@ import { describe, it, sinon, expect } from 'test/lib/common'; +import helpers from 'test/specs/helpers'; import { PromCompleter } from '../completer'; import { PrometheusDatasource } from '../datasource'; describe('Prometheus editor completer', function() { + var ctx = new helpers.ServiceTestContext(); + beforeEach(ctx.providePhase(['templateSrv'])); + function getSessionStub(data) { return { getTokenAt: sinon.stub().returns(data.currentToken), @@ -39,7 +43,18 @@ describe('Prometheus editor completer', function() { .returns(Promise.resolve(['node_cpu'])), }; - let completer = new PromCompleter(datasourceStub); + let templateSrv = { + variables: [ + { + name: 'var_name', + options: [ + { text: 'foo', value: 'foo', selected: false }, + { text: 'bar', value: 'bar', selected: true } + ] + } + ] + }; + let completer = new PromCompleter(datasourceStub, templateSrv); describe('When inside brackets', () => { it('Should return range vectors', () => {