浏览代码

Fix label suggestions for multi-line aggregation queries

No label suggestions were being returned for multi-line aggregation
contexts because the parsed selector string does not see the full
context before a `by` or `without` clause.

This solution stitches together all text nodes that comprise the query
editor to ensure the selector has sufficient context to generate
suggestions.

Also, an additional workaround has been included to ensure range vector
syntax does not disrupt label suggestions in aggregation contexts.

Related: #12890
Michael Huynh 7 年之前
父节点
当前提交
2a4a19388f
共有 1 个文件被更改,包括 20 次插入7 次删除
  1. 20 7
      public/app/plugins/datasource/prometheus/language_provider.ts

+ 20 - 7
public/app/plugins/datasource/prometheus/language_provider.ts

@@ -162,16 +162,29 @@ export default class PromQlLanguageProvider extends LanguageProvider {
     let refresher: Promise<any> = null;
     const suggestions: CompletionItemGroup[] = [];
 
-    // sum(foo{bar="1"}) by (|)
-    const line = value.anchorBlock.getText();
-    const cursorOffset: number = value.anchorOffset;
-    // sum(foo{bar="1"}) by (
-    const leftSide = line.slice(0, cursorOffset);
+    // Stitch all query lines together to support multi-line queries
+    let queryOffset;
+    const queryText = value.document.getBlocks().reduce((text, block) => {
+      const blockText = block.getText();
+      if (value.anchorBlock.key === block.key) {
+        // Newline characters are not accounted for but this is irrelevant
+        // for the purpose of extracting the selector string
+        queryOffset = value.anchorOffset + text.length;
+      }
+      text += blockText;
+      return text;
+    }, '');
+
+    const leftSide = queryText.slice(0, queryOffset);
     const openParensAggregationIndex = leftSide.lastIndexOf('(');
     const openParensSelectorIndex = leftSide.slice(0, openParensAggregationIndex).lastIndexOf('(');
     const closeParensSelectorIndex = leftSide.slice(openParensSelectorIndex).indexOf(')') + openParensSelectorIndex;
-    // foo{bar="1"}
-    const selectorString = leftSide.slice(openParensSelectorIndex + 1, closeParensSelectorIndex);
+
+    let selectorString = leftSide.slice(openParensSelectorIndex + 1, closeParensSelectorIndex);
+
+    // Range vector syntax not accounted for by subsequent parse so discard it if present
+    selectorString = selectorString.replace(/\[[^\]]+\]$/, '');
+
     const selector = parseSelector(selectorString, selectorString.length - 2).selector;
 
     const labelKeys = this.labelKeys[selector];