mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-12 14:27:27 -08:00
Clean up the Lezer grammar output tree (#11333)
Signed-off-by: Marijn Haverbeke <marijn@haverbeke.nl>
This commit is contained in:
parent
e4b87a7a2a
commit
8dbb2eaf0b
|
@ -19,30 +19,24 @@ import {
|
||||||
AggregateExpr,
|
AggregateExpr,
|
||||||
And,
|
And,
|
||||||
BinaryExpr,
|
BinaryExpr,
|
||||||
BinModifiers,
|
BoolModifier,
|
||||||
Bool,
|
|
||||||
Div,
|
Div,
|
||||||
Duration,
|
Duration,
|
||||||
Eql,
|
Eql,
|
||||||
EqlRegex,
|
EqlRegex,
|
||||||
EqlSingle,
|
EqlSingle,
|
||||||
Expr,
|
|
||||||
FunctionCallArgs,
|
|
||||||
FunctionCallBody,
|
FunctionCallBody,
|
||||||
GroupingLabel,
|
|
||||||
GroupingLabels,
|
GroupingLabels,
|
||||||
Gte,
|
Gte,
|
||||||
Gtr,
|
Gtr,
|
||||||
Identifier,
|
|
||||||
LabelMatcher,
|
LabelMatcher,
|
||||||
LabelMatchers,
|
LabelMatchers,
|
||||||
LabelMatchList,
|
|
||||||
LabelName,
|
LabelName,
|
||||||
Lss,
|
Lss,
|
||||||
Lte,
|
Lte,
|
||||||
MatchOp,
|
MatchOp,
|
||||||
MatrixSelector,
|
MatrixSelector,
|
||||||
MetricIdentifier,
|
Identifier,
|
||||||
Mod,
|
Mod,
|
||||||
Mul,
|
Mul,
|
||||||
Neq,
|
Neq,
|
||||||
|
@ -61,7 +55,7 @@ import {
|
||||||
} from '@prometheus-io/lezer-promql';
|
} from '@prometheus-io/lezer-promql';
|
||||||
import { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
import { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
||||||
import { EditorState } from '@codemirror/state';
|
import { EditorState } from '@codemirror/state';
|
||||||
import { buildLabelMatchers, containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes, walkBackward, walkThrough } from '../parser';
|
import { buildLabelMatchers, containsAtLeastOneChild, containsChild, walkBackward } from '../parser';
|
||||||
import {
|
import {
|
||||||
aggregateOpModifierTerms,
|
aggregateOpModifierTerms,
|
||||||
aggregateOpTerms,
|
aggregateOpTerms,
|
||||||
|
@ -118,13 +112,13 @@ export interface Context {
|
||||||
|
|
||||||
function getMetricNameInVectorSelector(tree: SyntaxNode, state: EditorState): string {
|
function getMetricNameInVectorSelector(tree: SyntaxNode, state: EditorState): string {
|
||||||
// Find if there is a defined metric name. Should be used to autocomplete a labelValue or a labelName
|
// Find if there is a defined metric name. Should be used to autocomplete a labelValue or a labelName
|
||||||
// First find the parent "VectorSelector" to be able to find then the subChild "MetricIdentifier" if it exists.
|
// First find the parent "VectorSelector" to be able to find then the subChild "Identifier" if it exists.
|
||||||
let currentNode: SyntaxNode | null = walkBackward(tree, VectorSelector);
|
let currentNode: SyntaxNode | null = walkBackward(tree, VectorSelector);
|
||||||
if (!currentNode) {
|
if (!currentNode) {
|
||||||
// Weird case that shouldn't happen, because "VectorSelector" is by definition the parent of the LabelMatchers.
|
// Weird case that shouldn't happen, because "VectorSelector" is by definition the parent of the LabelMatchers.
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
currentNode = walkThrough(currentNode, MetricIdentifier, Identifier);
|
currentNode = currentNode.getChild(Identifier);
|
||||||
if (!currentNode) {
|
if (!currentNode) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -193,7 +187,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
if (node.parent?.type.id === OffsetExpr) {
|
if (node.parent?.type.id === OffsetExpr) {
|
||||||
// we are likely in the given situation:
|
// we are likely in the given situation:
|
||||||
// `metric_name offset 5` that leads to this tree:
|
// `metric_name offset 5` that leads to this tree:
|
||||||
// `Expr(OffsetExpr(Expr(VectorSelector(MetricIdentifier(Identifier))),Offset,⚠))`
|
// `OffsetExpr(VectorSelector(Identifier),Offset,⚠)`
|
||||||
// Here we can just autocomplete a duration.
|
// Here we can just autocomplete a duration.
|
||||||
result.push({ kind: ContextKind.Duration });
|
result.push({ kind: ContextKind.Duration });
|
||||||
break;
|
break;
|
||||||
|
@ -219,7 +213,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// when we are in the situation 'metric_name !', we have the following tree
|
// when we are in the situation 'metric_name !', we have the following tree
|
||||||
// Expr(VectorSelector(MetricIdentifier(Identifier),⚠))
|
// VectorSelector(Identifier,⚠)
|
||||||
// We should try to know if the char '!' is part of a binOp.
|
// We should try to know if the char '!' is part of a binOp.
|
||||||
// Note: as it is quite experimental, maybe it requires more condition and to check the current tree (parent, other child at the same level ..etc.).
|
// Note: as it is quite experimental, maybe it requires more condition and to check the current tree (parent, other child at the same level ..etc.).
|
||||||
const operator = state.sliceDoc(node.from, node.to);
|
const operator = state.sliceDoc(node.from, node.to);
|
||||||
|
@ -247,14 +241,12 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
}
|
}
|
||||||
if (errorNodeParent?.type.id === VectorSelector) {
|
if (errorNodeParent?.type.id === VectorSelector) {
|
||||||
// it matches 'sum b'. So here we also have to autocomplete the aggregate operation modifier only
|
// it matches 'sum b'. So here we also have to autocomplete the aggregate operation modifier only
|
||||||
// if the associated metricIdentifier is matching an aggregation operation.
|
// if the associated identifier is matching an aggregation operation.
|
||||||
// Note: here is the corresponding tree in order to understand the situation:
|
// Note: here is the corresponding tree in order to understand the situation:
|
||||||
// Expr(
|
|
||||||
// VectorSelector(
|
// VectorSelector(
|
||||||
// MetricIdentifier(Identifier),
|
// Identifier,
|
||||||
// ⚠(Identifier)
|
// ⚠(Identifier)
|
||||||
// )
|
// )
|
||||||
// )
|
|
||||||
const operator = getMetricNameInVectorSelector(node, state);
|
const operator = getMetricNameInVectorSelector(node, state);
|
||||||
if (aggregateOpTerms.filter((term) => term.label === operator).length > 0) {
|
if (aggregateOpTerms.filter((term) => term.label === operator).length > 0) {
|
||||||
result.push({ kind: ContextKind.AggregateOpModifier });
|
result.push({ kind: ContextKind.AggregateOpModifier });
|
||||||
|
@ -268,14 +260,13 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorNodeParent && containsChild(errorNodeParent, Expr)) {
|
if (errorNodeParent && containsChild(errorNodeParent, 'Expr')) {
|
||||||
// this last case can appear with the following expression:
|
// this last case can appear with the following expression:
|
||||||
// 1. http_requests_total{method="GET"} off
|
// 1. http_requests_total{method="GET"} off
|
||||||
// 2. rate(foo[5m]) un
|
// 2. rate(foo[5m]) un
|
||||||
// 3. sum(http_requests_total{method="GET"} off)
|
// 3. sum(http_requests_total{method="GET"} off)
|
||||||
// For these different cases we have this kind of tree:
|
// For these different cases we have this kind of tree:
|
||||||
// Parent (
|
// Parent (
|
||||||
// Expr(),
|
|
||||||
// ⚠(Identifier)
|
// ⚠(Identifier)
|
||||||
// )
|
// )
|
||||||
// We don't really care about the parent, here we are more interested if in the siblings of the error node, there is the node 'Expr'
|
// We don't really care about the parent, here we are more interested if in the siblings of the error node, there is the node 'Expr'
|
||||||
|
@ -291,15 +282,15 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
// 2. sum(http_requests_total{method="GET"} / o) --> BinOpModifier + metric/function/aggregation
|
// 2. sum(http_requests_total{method="GET"} / o) --> BinOpModifier + metric/function/aggregation
|
||||||
// Examples above give a different tree each time and ends up to be treated in this case.
|
// Examples above give a different tree each time and ends up to be treated in this case.
|
||||||
// But they all have the following common tree pattern:
|
// But they all have the following common tree pattern:
|
||||||
// Parent( Expr(...),
|
// Parent( ...,
|
||||||
// ... ,
|
// ... ,
|
||||||
// Expr(VectorSelector(MetricIdentifier(Identifier)))
|
// VectorSelector(Identifier)
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// So the first things to do is to get the `Parent` and to determinate if we are in this configuration.
|
// So the first things to do is to get the `Parent` and to determinate if we are in this configuration.
|
||||||
// Otherwise we would just have to autocomplete the metric / function / aggregation.
|
// Otherwise we would just have to autocomplete the metric / function / aggregation.
|
||||||
|
|
||||||
const parent = node.parent?.parent?.parent?.parent;
|
const parent = node.parent?.parent;
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
// this case can be possible if the topNode is not anymore PromQL but MetricName.
|
// this case can be possible if the topNode is not anymore PromQL but MetricName.
|
||||||
// In this particular case, then we just want to autocomplete the metric
|
// In this particular case, then we just want to autocomplete the metric
|
||||||
|
@ -307,7 +298,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// now we have to know if we have two Expr in the direct children of the `parent`
|
// now we have to know if we have two Expr in the direct children of the `parent`
|
||||||
const containExprTwice = containsChild(parent, Expr, Expr);
|
const containExprTwice = containsChild(parent, 'Expr', 'Expr');
|
||||||
if (containExprTwice) {
|
if (containExprTwice) {
|
||||||
if (parent.type.id === BinaryExpr && !containsAtLeastOneChild(parent, 0)) {
|
if (parent.type.id === BinaryExpr && !containsAtLeastOneChild(parent, 0)) {
|
||||||
// We are likely in the case 1 or 5
|
// We are likely in the case 1 or 5
|
||||||
|
@ -320,11 +311,10 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
);
|
);
|
||||||
// in case the BinaryExpr is a comparison, we should autocomplete the `bool` keyword. But only if it is not present.
|
// in case the BinaryExpr is a comparison, we should autocomplete the `bool` keyword. But only if it is not present.
|
||||||
// When the `bool` keyword is NOT present, then the expression looks like this:
|
// When the `bool` keyword is NOT present, then the expression looks like this:
|
||||||
// BinaryExpr( Expr(...), Gtr , BinModifiers, Expr(...) )
|
// BinaryExpr( ..., Gtr , ... )
|
||||||
// When the `bool` keyword is present, then the expression looks like this:
|
// When the `bool` keyword is present, then the expression looks like this:
|
||||||
// BinaryExpr( Expr(...), Gtr , BinModifiers(Bool), Expr(...) )
|
// BinaryExpr( ..., Gtr , BoolModifier(...), ... )
|
||||||
// To know if it is not present, we just have to check if the Bool is not present as a child of the BinModifiers.
|
if (containsAtLeastOneChild(parent, Eql, Gte, Gtr, Lte, Lss, Neq) && !containsAtLeastOneChild(parent, BoolModifier)) {
|
||||||
if (containsAtLeastOneChild(parent, Eql, Gte, Gtr, Lte, Lss, Neq) && !walkThrough(parent, BinModifiers, Bool)) {
|
|
||||||
result.push({ kind: ContextKind.Bool });
|
result.push({ kind: ContextKind.Bool });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,7 +324,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
{ kind: ContextKind.Function },
|
{ kind: ContextKind.Function },
|
||||||
{ kind: ContextKind.Aggregation }
|
{ kind: ContextKind.Aggregation }
|
||||||
);
|
);
|
||||||
if (parent.type.id !== FunctionCallArgs && parent.type.id !== MatrixSelector) {
|
if (parent.type.id !== FunctionCallBody && parent.type.id !== MatrixSelector) {
|
||||||
// it's too avoid to autocomplete a number in situation where it shouldn't.
|
// it's too avoid to autocomplete a number in situation where it shouldn't.
|
||||||
// Like with `sum by(rat)`
|
// Like with `sum by(rat)`
|
||||||
result.push({ kind: ContextKind.Number });
|
result.push({ kind: ContextKind.Number });
|
||||||
|
@ -365,7 +355,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
result.push({ kind: ContextKind.LabelName, metricName: getMetricNameInVectorSelector(node, state) });
|
result.push({ kind: ContextKind.LabelName, metricName: getMetricNameInVectorSelector(node, state) });
|
||||||
break;
|
break;
|
||||||
case LabelName:
|
case LabelName:
|
||||||
if (node.parent?.type.id === GroupingLabel) {
|
if (node.parent?.type.id === GroupingLabels) {
|
||||||
// In this case we are in the given situation:
|
// In this case we are in the given situation:
|
||||||
// sum by (myL)
|
// sum by (myL)
|
||||||
// So we have to continue to autocomplete any kind of labelName
|
// So we have to continue to autocomplete any kind of labelName
|
||||||
|
@ -393,7 +383,8 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
// then find the metricName if it exists
|
// then find the metricName if it exists
|
||||||
const metricName = getMetricNameInVectorSelector(node, state);
|
const metricName = getMetricNameInVectorSelector(node, state);
|
||||||
// finally get the full matcher available
|
// finally get the full matcher available
|
||||||
const labelMatchers = buildLabelMatchers(retrieveAllRecursiveNodes(walkBackward(node, LabelMatchList), LabelMatchList, LabelMatcher), state);
|
const matcherNode = walkBackward(node, LabelMatchers);
|
||||||
|
const labelMatchers = buildLabelMatchers(matcherNode ? matcherNode.getChildren(LabelMatcher) : [], state);
|
||||||
result.push({
|
result.push({
|
||||||
kind: ContextKind.LabelValue,
|
kind: ContextKind.LabelValue,
|
||||||
metricName: metricName,
|
metricName: metricName,
|
||||||
|
@ -407,10 +398,10 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
|
||||||
// Here we are likely in this situation:
|
// Here we are likely in this situation:
|
||||||
// `go[5d:4]`
|
// `go[5d:4]`
|
||||||
// and we have the given tree:
|
// and we have the given tree:
|
||||||
// Expr( SubqueryExpr(
|
// SubqueryExpr(
|
||||||
// Expr(VectorSelector(MetricIdentifier(Identifier))),
|
// VectorSelector(Identifier),
|
||||||
// Duration, Duration, ⚠(NumberLiteral)
|
// Duration, Duration, ⚠(NumberLiteral)
|
||||||
// ))
|
// )
|
||||||
// So we should continue to autocomplete a duration
|
// So we should continue to autocomplete a duration
|
||||||
result.push({ kind: ContextKind.Duration });
|
result.push({ kind: ContextKind.Duration });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,4 +13,4 @@
|
||||||
|
|
||||||
export { buildLabelMatchers, labelMatchersToString } from './matcher';
|
export { buildLabelMatchers, labelMatchersToString } from './matcher';
|
||||||
export { Parser } from './parser';
|
export { Parser } from './parser';
|
||||||
export { walkBackward, walkThrough, containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes } from './path-finder';
|
export { walkBackward, containsAtLeastOneChild, containsChild } from './path-finder';
|
||||||
|
|
|
@ -17,26 +17,21 @@ import {
|
||||||
AggregateExpr,
|
AggregateExpr,
|
||||||
And,
|
And,
|
||||||
BinaryExpr,
|
BinaryExpr,
|
||||||
BinModifiers,
|
BoolModifier,
|
||||||
Bool,
|
|
||||||
Bottomk,
|
Bottomk,
|
||||||
CountValues,
|
CountValues,
|
||||||
Eql,
|
Eql,
|
||||||
EqlSingle,
|
EqlSingle,
|
||||||
Expr,
|
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
FunctionCallArgs,
|
|
||||||
FunctionCallBody,
|
FunctionCallBody,
|
||||||
Gte,
|
Gte,
|
||||||
Gtr,
|
Gtr,
|
||||||
Identifier,
|
Identifier,
|
||||||
LabelMatcher,
|
LabelMatcher,
|
||||||
LabelMatchers,
|
LabelMatchers,
|
||||||
LabelMatchList,
|
|
||||||
Lss,
|
Lss,
|
||||||
Lte,
|
Lte,
|
||||||
MatrixSelector,
|
MatrixSelector,
|
||||||
MetricIdentifier,
|
|
||||||
Neq,
|
Neq,
|
||||||
Or,
|
Or,
|
||||||
ParenExpr,
|
ParenExpr,
|
||||||
|
@ -48,7 +43,7 @@ import {
|
||||||
Unless,
|
Unless,
|
||||||
VectorSelector,
|
VectorSelector,
|
||||||
} from '@prometheus-io/lezer-promql';
|
} from '@prometheus-io/lezer-promql';
|
||||||
import { containsAtLeastOneChild, retrieveAllRecursiveNodes, walkThrough } from './path-finder';
|
import { containsAtLeastOneChild } from './path-finder';
|
||||||
import { getType } from './type';
|
import { getType } from './type';
|
||||||
import { buildLabelMatchers } from './matcher';
|
import { buildLabelMatchers } from './matcher';
|
||||||
import { EditorState } from '@codemirror/state';
|
import { EditorState } from '@codemirror/state';
|
||||||
|
@ -105,8 +100,6 @@ export class Parser {
|
||||||
return ValueType.none;
|
return ValueType.none;
|
||||||
}
|
}
|
||||||
switch (node.type.id) {
|
switch (node.type.id) {
|
||||||
case Expr:
|
|
||||||
return this.checkAST(node.firstChild);
|
|
||||||
case AggregateExpr:
|
case AggregateExpr:
|
||||||
this.checkAggregationExpr(node);
|
this.checkAggregationExpr(node);
|
||||||
break;
|
break;
|
||||||
|
@ -117,28 +110,28 @@ export class Parser {
|
||||||
this.checkCallFunction(node);
|
this.checkCallFunction(node);
|
||||||
break;
|
break;
|
||||||
case ParenExpr:
|
case ParenExpr:
|
||||||
this.checkAST(walkThrough(node, Expr));
|
this.checkAST(node.getChild('Expr'));
|
||||||
break;
|
break;
|
||||||
case UnaryExpr:
|
case UnaryExpr:
|
||||||
const unaryExprType = this.checkAST(walkThrough(node, Expr));
|
const unaryExprType = this.checkAST(node.getChild('Expr'));
|
||||||
if (unaryExprType !== ValueType.scalar && unaryExprType !== ValueType.vector) {
|
if (unaryExprType !== ValueType.scalar && unaryExprType !== ValueType.vector) {
|
||||||
this.addDiagnostic(node, `unary expression only allowed on expressions of type scalar or instant vector, got ${unaryExprType}`);
|
this.addDiagnostic(node, `unary expression only allowed on expressions of type scalar or instant vector, got ${unaryExprType}`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubqueryExpr:
|
case SubqueryExpr:
|
||||||
const subQueryExprType = this.checkAST(walkThrough(node, Expr));
|
const subQueryExprType = this.checkAST(node.getChild('Expr'));
|
||||||
if (subQueryExprType !== ValueType.vector) {
|
if (subQueryExprType !== ValueType.vector) {
|
||||||
this.addDiagnostic(node, `subquery is only allowed on instant vector, got ${subQueryExprType} in ${node.name} instead`);
|
this.addDiagnostic(node, `subquery is only allowed on instant vector, got ${subQueryExprType} in ${node.name} instead`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MatrixSelector:
|
case MatrixSelector:
|
||||||
this.checkAST(walkThrough(node, Expr));
|
this.checkAST(node.getChild('Expr'));
|
||||||
break;
|
break;
|
||||||
case VectorSelector:
|
case VectorSelector:
|
||||||
this.checkVectorSelector(node);
|
this.checkVectorSelector(node);
|
||||||
break;
|
break;
|
||||||
case StepInvariantExpr:
|
case StepInvariantExpr:
|
||||||
const exprValue = this.checkAST(walkThrough(node, Expr));
|
const exprValue = this.checkAST(node.getChild('Expr'));
|
||||||
if (exprValue !== ValueType.vector && exprValue !== ValueType.matrix) {
|
if (exprValue !== ValueType.vector && exprValue !== ValueType.matrix) {
|
||||||
this.addDiagnostic(node, `@ modifier must be preceded by an instant selector vector or range vector selector or a subquery`);
|
this.addDiagnostic(node, `@ modifier must be preceded by an instant selector vector or range vector selector or a subquery`);
|
||||||
}
|
}
|
||||||
|
@ -164,27 +157,19 @@ export class Parser {
|
||||||
this.addDiagnostic(node, 'aggregation operator expected in aggregation expression but got nothing');
|
this.addDiagnostic(node, 'aggregation operator expected in aggregation expression but got nothing');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const expr = walkThrough(node, FunctionCallBody, FunctionCallArgs, Expr);
|
const body = node.getChild(FunctionCallBody);
|
||||||
if (!expr) {
|
const params = body ? body.getChildren('Expr') : [];
|
||||||
|
if (!params.length) {
|
||||||
this.addDiagnostic(node, 'unable to find the parameter for the expression');
|
this.addDiagnostic(node, 'unable to find the parameter for the expression');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.expectType(expr, ValueType.vector, 'aggregation expression');
|
this.expectType(params[params.length - 1], ValueType.vector, 'aggregation expression');
|
||||||
// get the parameter of the aggregation operator
|
// get the parameter of the aggregation operator
|
||||||
const params = walkThrough(node, FunctionCallBody, FunctionCallArgs, FunctionCallArgs, Expr);
|
|
||||||
if (aggregateOp.type.id === Topk || aggregateOp.type.id === Bottomk || aggregateOp.type.id === Quantile) {
|
if (aggregateOp.type.id === Topk || aggregateOp.type.id === Bottomk || aggregateOp.type.id === Quantile) {
|
||||||
if (!params) {
|
this.expectType(params[0], ValueType.scalar, 'aggregation parameter');
|
||||||
this.addDiagnostic(node, 'no parameter found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.expectType(params, ValueType.scalar, 'aggregation parameter');
|
|
||||||
}
|
}
|
||||||
if (aggregateOp.type.id === CountValues) {
|
if (aggregateOp.type.id === CountValues) {
|
||||||
if (!params) {
|
this.expectType(params[0], ValueType.string, 'aggregation parameter');
|
||||||
this.addDiagnostic(node, 'no parameter found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.expectType(params, ValueType.string, 'aggregation parameter');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +185,7 @@ export class Parser {
|
||||||
}
|
}
|
||||||
const lt = this.checkAST(lExpr);
|
const lt = this.checkAST(lExpr);
|
||||||
const rt = this.checkAST(rExpr);
|
const rt = this.checkAST(rExpr);
|
||||||
const boolModifierUsed = walkThrough(node, BinModifiers, Bool);
|
const boolModifierUsed = node.getChild(BoolModifier);
|
||||||
const isComparisonOperator = containsAtLeastOneChild(node, Eql, Neq, Lte, Lss, Gte, Gtr);
|
const isComparisonOperator = containsAtLeastOneChild(node, Eql, Neq, Lte, Lss, Gte, Gtr);
|
||||||
const isSetOperator = containsAtLeastOneChild(node, And, Or, Unless);
|
const isSetOperator = containsAtLeastOneChild(node, And, Or, Unless);
|
||||||
|
|
||||||
|
@ -259,7 +244,8 @@ export class Parser {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = retrieveAllRecursiveNodes(walkThrough(node, FunctionCallBody), FunctionCallArgs, Expr);
|
const body = node.getChild(FunctionCallBody);
|
||||||
|
const args = body ? body.getChildren('Expr') : [];
|
||||||
const funcSignature = getFunction(funcID.type.id);
|
const funcSignature = getFunction(funcID.type.id);
|
||||||
const nargs = funcSignature.argTypes.length;
|
const nargs = funcSignature.argTypes.length;
|
||||||
|
|
||||||
|
@ -295,14 +281,12 @@ export class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkVectorSelector(node: SyntaxNode): void {
|
private checkVectorSelector(node: SyntaxNode): void {
|
||||||
const labelMatchers = buildLabelMatchers(
|
const matchList = node.getChild(LabelMatchers);
|
||||||
retrieveAllRecursiveNodes(walkThrough(node, LabelMatchers, LabelMatchList), LabelMatchList, LabelMatcher),
|
const labelMatchers = buildLabelMatchers(matchList ? matchList.getChildren(LabelMatcher) : [], this.state);
|
||||||
this.state
|
|
||||||
);
|
|
||||||
let vectorSelectorName = '';
|
let vectorSelectorName = '';
|
||||||
// VectorSelector ( MetricIdentifier ( Identifier ) )
|
// VectorSelector ( Identifier )
|
||||||
// https://github.com/promlabs/lezer-promql/blob/71e2f9fa5ae6f5c5547d5738966cd2512e6b99a8/src/promql.grammar#L200
|
// https://github.com/promlabs/lezer-promql/blob/71e2f9fa5ae6f5c5547d5738966cd2512e6b99a8/src/promql.grammar#L200
|
||||||
const vectorSelectorNodeName = walkThrough(node, MetricIdentifier, Identifier);
|
const vectorSelectorNodeName = node.getChild(Identifier);
|
||||||
if (vectorSelectorNodeName) {
|
if (vectorSelectorNodeName) {
|
||||||
vectorSelectorName = this.state.sliceDoc(vectorSelectorNodeName.from, vectorSelectorNodeName.to);
|
vectorSelectorName = this.state.sliceDoc(vectorSelectorNodeName.from, vectorSelectorNodeName.to);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ import {
|
||||||
BinaryExpr,
|
BinaryExpr,
|
||||||
Div,
|
Div,
|
||||||
Eql,
|
Eql,
|
||||||
Expr,
|
|
||||||
FunctionCall,
|
|
||||||
FunctionCallArgs,
|
|
||||||
FunctionCallBody,
|
FunctionCallBody,
|
||||||
Gte,
|
Gte,
|
||||||
Gtr,
|
Gtr,
|
||||||
|
@ -28,74 +25,14 @@ import {
|
||||||
Mod,
|
Mod,
|
||||||
Mul,
|
Mul,
|
||||||
Neq,
|
Neq,
|
||||||
NumberLiteral,
|
|
||||||
Sub,
|
Sub,
|
||||||
VectorSelector,
|
VectorSelector,
|
||||||
} from '@prometheus-io/lezer-promql';
|
} from '@prometheus-io/lezer-promql';
|
||||||
import { createEditorState } from '../test/utils-test';
|
import { createEditorState } from '../test/utils-test';
|
||||||
import { containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes, walkBackward, walkThrough } from './path-finder';
|
import { containsAtLeastOneChild, containsChild, walkBackward } from './path-finder';
|
||||||
import { SyntaxNode } from '@lezer/common';
|
import { SyntaxNode } from '@lezer/common';
|
||||||
import { syntaxTree } from '@codemirror/language';
|
import { syntaxTree } from '@codemirror/language';
|
||||||
|
|
||||||
describe('walkThrough test', () => {
|
|
||||||
const testCases = [
|
|
||||||
{
|
|
||||||
title: 'should return the node when no path is given',
|
|
||||||
expr: '1 > bool 2',
|
|
||||||
pos: 0,
|
|
||||||
expectedNode: 'PromQL',
|
|
||||||
path: [] as number[],
|
|
||||||
expectedDoc: '1 > bool 2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'should find the path',
|
|
||||||
expr: "100 * (1 - avg by(instance)(irate(node_cpu{mode='idle'}[5m])))",
|
|
||||||
pos: 11,
|
|
||||||
path: [Expr, NumberLiteral],
|
|
||||||
// for the moment the function walkThrough is not able to find the following path.
|
|
||||||
// That's because the function is iterating through the tree by searching the first possible node that matched
|
|
||||||
// the node ID path[i].
|
|
||||||
// So for the current expression, and the given position we are in the sub expr (1 - avg ...).
|
|
||||||
// Expr is matching 1 and not avg.
|
|
||||||
// TODO fix this issue
|
|
||||||
// path: [Expr, AggregateExpr, AggregateOp, Avg],
|
|
||||||
expectedNode: NumberLiteral,
|
|
||||||
expectedDoc: '1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'should not find the path',
|
|
||||||
expr: 'topk(10, count by (job)({__name__=~".+"}))',
|
|
||||||
pos: 12,
|
|
||||||
path: [Expr, BinaryExpr],
|
|
||||||
expectedNode: undefined,
|
|
||||||
expectedDoc: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'should find a node in a recursive node definition',
|
|
||||||
expr: 'rate(1, 2, 3)',
|
|
||||||
pos: 0,
|
|
||||||
path: [Expr, FunctionCall, FunctionCallBody, FunctionCallArgs, FunctionCallArgs, Expr, NumberLiteral],
|
|
||||||
expectedNode: NumberLiteral,
|
|
||||||
expectedDoc: '2',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
testCases.forEach((value) => {
|
|
||||||
it(value.title, () => {
|
|
||||||
const state = createEditorState(value.expr);
|
|
||||||
const subTree = syntaxTree(state).resolve(value.pos, -1);
|
|
||||||
const node = walkThrough(subTree, ...value.path);
|
|
||||||
if (typeof value.expectedNode === 'number') {
|
|
||||||
expect(value.expectedNode).toEqual(node?.type.id);
|
|
||||||
} else {
|
|
||||||
expect(value.expectedNode).toEqual(node?.type.name);
|
|
||||||
}
|
|
||||||
if (node) {
|
|
||||||
expect(value.expectedDoc).toEqual(state.sliceDoc(node.from, node.to));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('containsAtLeastOneChild test', () => {
|
describe('containsAtLeastOneChild test', () => {
|
||||||
const testCases = [
|
const testCases = [
|
||||||
{
|
{
|
||||||
|
@ -103,14 +40,13 @@ describe('containsAtLeastOneChild test', () => {
|
||||||
expr: '1 > 2',
|
expr: '1 > 2',
|
||||||
pos: 3,
|
pos: 3,
|
||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
walkThrough: [],
|
|
||||||
child: [],
|
child: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'should find a node in the given list',
|
title: 'should find a node in the given list',
|
||||||
expr: '1 > 2',
|
expr: '1 > 2',
|
||||||
pos: 0,
|
pos: 0,
|
||||||
walkThrough: [Expr, BinaryExpr],
|
take: BinaryExpr,
|
||||||
child: [Eql, Neq, Lte, Lss, Gte, Gtr],
|
child: [Eql, Neq, Lte, Lss, Gte, Gtr],
|
||||||
expectedResult: true,
|
expectedResult: true,
|
||||||
},
|
},
|
||||||
|
@ -118,7 +54,7 @@ describe('containsAtLeastOneChild test', () => {
|
||||||
title: 'should not find a node in the given list',
|
title: 'should not find a node in the given list',
|
||||||
expr: '1 > 2',
|
expr: '1 > 2',
|
||||||
pos: 0,
|
pos: 0,
|
||||||
walkThrough: [Expr, BinaryExpr],
|
take: BinaryExpr,
|
||||||
child: [Mul, Div, Mod, Add, Sub],
|
child: [Mul, Div, Mod, Add, Sub],
|
||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
},
|
},
|
||||||
|
@ -127,7 +63,7 @@ describe('containsAtLeastOneChild test', () => {
|
||||||
it(value.title, () => {
|
it(value.title, () => {
|
||||||
const state = createEditorState(value.expr);
|
const state = createEditorState(value.expr);
|
||||||
const subTree = syntaxTree(state).resolve(value.pos, -1);
|
const subTree = syntaxTree(state).resolve(value.pos, -1);
|
||||||
const node = walkThrough(subTree, ...value.walkThrough);
|
const node = value.take == null ? subTree : subTree.getChild(value.take);
|
||||||
expect(node).toBeTruthy();
|
expect(node).toBeTruthy();
|
||||||
if (node) {
|
if (node) {
|
||||||
expect(value.expectedResult).toEqual(containsAtLeastOneChild(node, ...value.child));
|
expect(value.expectedResult).toEqual(containsAtLeastOneChild(node, ...value.child));
|
||||||
|
@ -143,24 +79,25 @@ describe('containsChild test', () => {
|
||||||
expr: 'metric_name / ignor',
|
expr: 'metric_name / ignor',
|
||||||
pos: 0,
|
pos: 0,
|
||||||
expectedResult: true,
|
expectedResult: true,
|
||||||
walkThrough: [Expr, BinaryExpr],
|
walkThrough: [BinaryExpr],
|
||||||
child: [Expr, Expr],
|
child: ['Expr', 'Expr'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Should not find all child required',
|
title: 'Should not find all child required',
|
||||||
expr: 'sum(ra)',
|
expr: 'sum(ra)',
|
||||||
pos: 0,
|
pos: 0,
|
||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
walkThrough: [Expr, AggregateExpr, FunctionCallBody, FunctionCallArgs],
|
walkThrough: [AggregateExpr, FunctionCallBody],
|
||||||
child: [Expr, Expr],
|
child: ['Expr', 'Expr'],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
testCases.forEach((value) => {
|
testCases.forEach((value) => {
|
||||||
it(value.title, () => {
|
it(value.title, () => {
|
||||||
const state = createEditorState(value.expr);
|
const state = createEditorState(value.expr);
|
||||||
const subTree = syntaxTree(state).resolve(value.pos, -1);
|
let node: SyntaxNode | null | undefined = syntaxTree(state).resolve(value.pos, -1);
|
||||||
const node: SyntaxNode | null = walkThrough(subTree, ...value.walkThrough);
|
for (const enter of value.walkThrough) {
|
||||||
|
node = node?.getChild(enter);
|
||||||
|
}
|
||||||
expect(node).toBeTruthy();
|
expect(node).toBeTruthy();
|
||||||
if (node) {
|
if (node) {
|
||||||
expect(value.expectedResult).toEqual(containsChild(node, ...value.child));
|
expect(value.expectedResult).toEqual(containsChild(node, ...value.child));
|
||||||
|
@ -169,17 +106,6 @@ describe('containsChild test', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('retrieveAllRecursiveNodes test', () => {
|
|
||||||
it('should find every occurrence', () => {
|
|
||||||
const state = createEditorState('rate(1,2,3)');
|
|
||||||
const tree = syntaxTree(state).topNode.firstChild;
|
|
||||||
expect(tree).toBeTruthy();
|
|
||||||
if (tree) {
|
|
||||||
expect(3).toEqual(retrieveAllRecursiveNodes(walkThrough(tree, FunctionCall, FunctionCallBody), FunctionCallArgs, Expr).length);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('walkbackward test', () => {
|
describe('walkbackward test', () => {
|
||||||
const testCases = [
|
const testCases = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,36 +15,12 @@ import { SyntaxNode } from '@lezer/common';
|
||||||
|
|
||||||
// walkBackward will iterate other the tree from the leaf to the root until it founds the given `exit` node.
|
// walkBackward will iterate other the tree from the leaf to the root until it founds the given `exit` node.
|
||||||
// It returns null if the exit is not found.
|
// It returns null if the exit is not found.
|
||||||
export function walkBackward(node: SyntaxNode, exit: number): SyntaxNode | null {
|
export function walkBackward(node: SyntaxNode | null, exit: number): SyntaxNode | null {
|
||||||
const cursor = node.cursor();
|
for (;;) {
|
||||||
let cursorIsMoving = true;
|
if (!node || node.type.id === exit) {
|
||||||
while (cursorIsMoving && cursor.type.id !== exit) {
|
return node;
|
||||||
cursorIsMoving = cursor.parent();
|
|
||||||
}
|
}
|
||||||
return cursor.type.id === exit ? cursor.node : null;
|
node = node.parent;
|
||||||
}
|
|
||||||
|
|
||||||
// walkThrough is going to follow the path passed in parameter.
|
|
||||||
// If it succeeds to reach the last id/name of the path, then it will return the corresponding Subtree.
|
|
||||||
// Otherwise if it's not possible to reach the last id/name of the path, it will return `null`
|
|
||||||
// Note: the way followed during the iteration of the tree to find the given path, is only from the root to the leaf.
|
|
||||||
export function walkThrough(node: SyntaxNode, ...path: (number | string)[]): SyntaxNode | null {
|
|
||||||
const cursor = node.cursor();
|
|
||||||
let i = 0;
|
|
||||||
let cursorIsMoving = true;
|
|
||||||
path.unshift(cursor.type.id);
|
|
||||||
while (i < path.length && cursorIsMoving) {
|
|
||||||
if (cursor.type.id === path[i] || cursor.type.name === path[i]) {
|
|
||||||
i++;
|
|
||||||
if (i < path.length) {
|
|
||||||
cursorIsMoving = cursor.next();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cursorIsMoving = cursor.nextSibling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i >= path.length) {
|
|
||||||
return cursor.node;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -73,28 +49,10 @@ export function containsChild(node: SyntaxNode, ...child: (number | string)[]):
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (cursor.type.id === child[i] || cursor.type.name === child[i]) {
|
if (cursor.type.is(child[i])) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
} while (i < child.length && cursor.nextSibling());
|
} while (i < child.length && cursor.nextSibling());
|
||||||
|
|
||||||
return i >= child.length;
|
return i >= child.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function retrieveAllRecursiveNodes(parentNode: SyntaxNode | null, recursiveNode: number, leaf: number): SyntaxNode[] {
|
|
||||||
const nodes: SyntaxNode[] = [];
|
|
||||||
|
|
||||||
function recursiveRetrieveNode(node: SyntaxNode | null, nodes: SyntaxNode[]) {
|
|
||||||
const subNode = node?.getChild(recursiveNode);
|
|
||||||
const le = node?.lastChild;
|
|
||||||
if (subNode && subNode.type.id === recursiveNode) {
|
|
||||||
recursiveRetrieveNode(subNode, nodes);
|
|
||||||
}
|
|
||||||
if (le && le.type.id === leaf) {
|
|
||||||
nodes.push(le);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recursiveRetrieveNode(parentNode, nodes);
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { SyntaxNode } from '@lezer/common';
|
||||||
import {
|
import {
|
||||||
AggregateExpr,
|
AggregateExpr,
|
||||||
BinaryExpr,
|
BinaryExpr,
|
||||||
Expr,
|
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
MatrixSelector,
|
MatrixSelector,
|
||||||
NumberLiteral,
|
NumberLiteral,
|
||||||
|
@ -27,7 +26,6 @@ import {
|
||||||
UnaryExpr,
|
UnaryExpr,
|
||||||
VectorSelector,
|
VectorSelector,
|
||||||
} from '@prometheus-io/lezer-promql';
|
} from '@prometheus-io/lezer-promql';
|
||||||
import { walkThrough } from './path-finder';
|
|
||||||
import { getFunction, ValueType } from '../types';
|
import { getFunction, ValueType } from '../types';
|
||||||
|
|
||||||
// Based on https://github.com/prometheus/prometheus/blob/d668a7efe3107dbdcc67bf4e9f12430ed8e2b396/promql/parser/ast.go#L191
|
// Based on https://github.com/prometheus/prometheus/blob/d668a7efe3107dbdcc67bf4e9f12430ed8e2b396/promql/parser/ast.go#L191
|
||||||
|
@ -36,8 +34,6 @@ export function getType(node: SyntaxNode | null): ValueType {
|
||||||
return ValueType.none;
|
return ValueType.none;
|
||||||
}
|
}
|
||||||
switch (node.type.id) {
|
switch (node.type.id) {
|
||||||
case Expr:
|
|
||||||
return getType(node.firstChild);
|
|
||||||
case AggregateExpr:
|
case AggregateExpr:
|
||||||
return ValueType.vector;
|
return ValueType.vector;
|
||||||
case VectorSelector:
|
case VectorSelector:
|
||||||
|
@ -53,9 +49,9 @@ export function getType(node: SyntaxNode | null): ValueType {
|
||||||
case SubqueryExpr:
|
case SubqueryExpr:
|
||||||
return ValueType.matrix;
|
return ValueType.matrix;
|
||||||
case ParenExpr:
|
case ParenExpr:
|
||||||
return getType(walkThrough(node, Expr));
|
return getType(node.getChild('Expr'));
|
||||||
case UnaryExpr:
|
case UnaryExpr:
|
||||||
return getType(walkThrough(node, Expr));
|
return getType(node.getChild('Expr'));
|
||||||
case BinaryExpr:
|
case BinaryExpr:
|
||||||
const lt = getType(node.firstChild);
|
const lt = getType(node.firstChild);
|
||||||
const rt = getType(node.lastChild);
|
const rt = getType(node.lastChild);
|
||||||
|
@ -70,7 +66,7 @@ export function getType(node: SyntaxNode | null): ValueType {
|
||||||
}
|
}
|
||||||
return getFunction(funcNode.type.id).returnType;
|
return getFunction(funcNode.type.id).returnType;
|
||||||
case StepInvariantExpr:
|
case StepInvariantExpr:
|
||||||
return getType(walkThrough(node, Expr));
|
return getType(node.getChild('Expr'));
|
||||||
default:
|
default:
|
||||||
return ValueType.none;
|
return ValueType.none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
|
|
||||||
import { buildVectorMatching } from './vector';
|
import { buildVectorMatching } from './vector';
|
||||||
import { createEditorState } from '../test/utils-test';
|
import { createEditorState } from '../test/utils-test';
|
||||||
import { walkThrough } from './path-finder';
|
import { BinaryExpr } from '@prometheus-io/lezer-promql';
|
||||||
import { BinaryExpr, Expr } from '@prometheus-io/lezer-promql';
|
|
||||||
import { syntaxTree } from '@codemirror/language';
|
import { syntaxTree } from '@codemirror/language';
|
||||||
import { VectorMatchCardinality } from '../types';
|
import { VectorMatchCardinality } from '../types';
|
||||||
|
|
||||||
|
@ -201,7 +200,7 @@ describe('buildVectorMatching test', () => {
|
||||||
testCases.forEach((value) => {
|
testCases.forEach((value) => {
|
||||||
it(value.binaryExpr, () => {
|
it(value.binaryExpr, () => {
|
||||||
const state = createEditorState(value.binaryExpr);
|
const state = createEditorState(value.binaryExpr);
|
||||||
const node = walkThrough(syntaxTree(state).topNode, Expr, BinaryExpr);
|
const node = syntaxTree(state).topNode.getChild(BinaryExpr);
|
||||||
expect(node).toBeTruthy();
|
expect(node).toBeTruthy();
|
||||||
if (node) {
|
if (node) {
|
||||||
expect(value.expectedVectorMatching).toEqual(buildVectorMatching(state, node));
|
expect(value.expectedVectorMatching).toEqual(buildVectorMatching(state, node));
|
||||||
|
|
|
@ -16,19 +16,17 @@ import { SyntaxNode } from '@lezer/common';
|
||||||
import {
|
import {
|
||||||
And,
|
And,
|
||||||
BinaryExpr,
|
BinaryExpr,
|
||||||
BinModifiers,
|
MatchingModifierClause,
|
||||||
GroupingLabel,
|
LabelName,
|
||||||
GroupingLabelList,
|
|
||||||
GroupingLabels,
|
GroupingLabels,
|
||||||
GroupLeft,
|
GroupLeft,
|
||||||
GroupRight,
|
GroupRight,
|
||||||
On,
|
On,
|
||||||
OnOrIgnoring,
|
|
||||||
Or,
|
Or,
|
||||||
Unless,
|
Unless,
|
||||||
} from '@prometheus-io/lezer-promql';
|
} from '@prometheus-io/lezer-promql';
|
||||||
import { VectorMatchCardinality, VectorMatching } from '../types';
|
import { VectorMatchCardinality, VectorMatching } from '../types';
|
||||||
import { containsAtLeastOneChild, retrieveAllRecursiveNodes } from './path-finder';
|
import { containsAtLeastOneChild } from './path-finder';
|
||||||
|
|
||||||
export function buildVectorMatching(state: EditorState, binaryNode: SyntaxNode): VectorMatching | null {
|
export function buildVectorMatching(state: EditorState, binaryNode: SyntaxNode): VectorMatching | null {
|
||||||
if (!binaryNode || binaryNode.type.id !== BinaryExpr) {
|
if (!binaryNode || binaryNode.type.id !== BinaryExpr) {
|
||||||
|
@ -40,31 +38,27 @@ export function buildVectorMatching(state: EditorState, binaryNode: SyntaxNode):
|
||||||
on: false,
|
on: false,
|
||||||
include: [],
|
include: [],
|
||||||
};
|
};
|
||||||
const binModifiers = binaryNode.getChild(BinModifiers);
|
const modifierClause = binaryNode.getChild(MatchingModifierClause);
|
||||||
if (binModifiers) {
|
if (modifierClause) {
|
||||||
const onOrIgnoring = binModifiers.getChild(OnOrIgnoring);
|
result.on = modifierClause.getChild(On) !== null;
|
||||||
if (onOrIgnoring) {
|
const labelNode = modifierClause.getChild(GroupingLabels);
|
||||||
result.on = onOrIgnoring.getChild(On) !== null;
|
const labels = labelNode ? labelNode.getChildren(LabelName) : [];
|
||||||
const labels = retrieveAllRecursiveNodes(onOrIgnoring.getChild(GroupingLabels), GroupingLabelList, GroupingLabel);
|
|
||||||
if (labels.length > 0) {
|
|
||||||
for (const label of labels) {
|
for (const label of labels) {
|
||||||
result.matchingLabels.push(state.sliceDoc(label.from, label.to));
|
result.matchingLabels.push(state.sliceDoc(label.from, label.to));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupLeft = binModifiers.getChild(GroupLeft);
|
const groupLeft = modifierClause.getChild(GroupLeft);
|
||||||
const groupRight = binModifiers.getChild(GroupRight);
|
const groupRight = modifierClause.getChild(GroupRight);
|
||||||
if (groupLeft || groupRight) {
|
const group = groupLeft || groupRight;
|
||||||
|
if (group) {
|
||||||
result.card = groupLeft ? VectorMatchCardinality.CardManyToOne : VectorMatchCardinality.CardOneToMany;
|
result.card = groupLeft ? VectorMatchCardinality.CardManyToOne : VectorMatchCardinality.CardOneToMany;
|
||||||
const includeLabels = retrieveAllRecursiveNodes(binModifiers.getChild(GroupingLabels), GroupingLabelList, GroupingLabel);
|
const labelNode = group.nextSibling;
|
||||||
if (includeLabels.length > 0) {
|
const labels = labelNode?.getChildren(LabelName) || [];
|
||||||
for (const label of includeLabels) {
|
for (const label of labels) {
|
||||||
result.include.push(state.sliceDoc(label.from, label.to));
|
result.include.push(state.sliceDoc(label.from, label.to));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const isSetOperator = containsAtLeastOneChild(binaryNode, And, Or, Unless);
|
const isSetOperator = containsAtLeastOneChild(binaryNode, And, Or, Unless);
|
||||||
if (isSetOperator && result.card === VectorMatchCardinality.CardOneToOne) {
|
if (isSetOperator && result.card === VectorMatchCardinality.CardOneToOne) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ export const promQLHighLight = styleTags({
|
||||||
StringLiteral: tags.string,
|
StringLiteral: tags.string,
|
||||||
NumberLiteral: tags.number,
|
NumberLiteral: tags.number,
|
||||||
Duration: tags.number,
|
Duration: tags.number,
|
||||||
|
Identifier: tags.variableName,
|
||||||
'Abs Absent AbsentOverTime Acos Acosh Asin Asinh Atan Atanh AvgOverTime Ceil Changes Clamp ClampMax ClampMin Cos Cosh CountOverTime DaysInMonth DayOfMonth DayOfWeek DayOfYear Deg Delta Deriv Exp Floor HistogramQuantile HoltWinters Hour Idelta Increase Irate LabelReplace LabelJoin LastOverTime Ln Log10 Log2 MaxOverTime MinOverTime Minute Month Pi PredictLinear PresentOverTime QuantileOverTime Rad Rate Resets Round Scalar Sgn Sin Sinh Sort SortDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
|
'Abs Absent AbsentOverTime Acos Acosh Asin Asinh Atan Atanh AvgOverTime Ceil Changes Clamp ClampMax ClampMin Cos Cosh CountOverTime DaysInMonth DayOfMonth DayOfWeek DayOfYear Deg Delta Deriv Exp Floor HistogramQuantile HoltWinters Hour Idelta Increase Irate LabelReplace LabelJoin LastOverTime Ln Log10 Log2 MaxOverTime MinOverTime Minute Month Pi PredictLinear PresentOverTime QuantileOverTime Rad Rate Resets Round Scalar Sgn Sin Sinh Sort SortDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
|
||||||
tags.function(tags.variableName),
|
tags.function(tags.variableName),
|
||||||
'Avg Bottomk Count Count_values Group Max Min Quantile Stddev Stdvar Sum Topk': tags.operatorKeyword,
|
'Avg Bottomk Count Count_values Group Max Min Quantile Stddev Stdvar Sum Topk': tags.operatorKeyword,
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
@top PromQL { Expr }
|
@top PromQL { expr }
|
||||||
@top MetricName { MetricIdentifier }
|
@top MetricName { Identifier }
|
||||||
|
|
||||||
@precedence {
|
@precedence {
|
||||||
|
group,
|
||||||
pow @right,
|
pow @right,
|
||||||
mul @left
|
mul @left
|
||||||
add @left,
|
add @left,
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
or @left
|
or @left
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr {
|
expr[@isGroup=Expr] {
|
||||||
AggregateExpr |
|
AggregateExpr |
|
||||||
BinaryExpr |
|
BinaryExpr |
|
||||||
FunctionCall |
|
FunctionCall |
|
||||||
|
@ -65,53 +66,38 @@ AggregateModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryExpr {
|
BinaryExpr {
|
||||||
Expr !pow Pow BinModifiers Expr |
|
expr !pow Pow binModifiers expr |
|
||||||
Expr !mul Mul BinModifiers Expr |
|
expr !mul Mul binModifiers expr |
|
||||||
Expr !mul Div BinModifiers Expr |
|
expr !mul Div binModifiers expr |
|
||||||
Expr !mul Mod BinModifiers Expr |
|
expr !mul Mod binModifiers expr |
|
||||||
Expr !mul Atan2 BinModifiers Expr |
|
expr !mul Atan2 binModifiers expr |
|
||||||
Expr !add Add BinModifiers Expr |
|
expr !add Add binModifiers expr |
|
||||||
Expr !add Sub BinModifiers Expr |
|
expr !add Sub binModifiers expr |
|
||||||
Expr !eql Eql BinModifiers Expr |
|
expr !eql Eql binModifiers expr |
|
||||||
Expr !eql Gte BinModifiers Expr |
|
expr !eql Gte binModifiers expr |
|
||||||
Expr !eql Gtr BinModifiers Expr |
|
expr !eql Gtr binModifiers expr |
|
||||||
Expr !eql Lte BinModifiers Expr |
|
expr !eql Lte binModifiers expr |
|
||||||
Expr !eql Lss BinModifiers Expr |
|
expr !eql Lss binModifiers expr |
|
||||||
Expr !eql Neq BinModifiers Expr |
|
expr !eql Neq binModifiers expr |
|
||||||
Expr !and And BinModifiers Expr |
|
expr !and And binModifiers expr |
|
||||||
Expr !and Unless BinModifiers Expr |
|
expr !and Unless binModifiers expr |
|
||||||
Expr !or Or BinModifiers Expr
|
expr !or Or binModifiers expr
|
||||||
}
|
}
|
||||||
|
|
||||||
OnOrIgnoring {
|
MatchingModifierClause {
|
||||||
Ignoring GroupingLabels |
|
(Ignoring | On) GroupingLabels
|
||||||
On GroupingLabels
|
((GroupLeft | GroupRight) (!group GroupingLabels)?)?
|
||||||
}
|
}
|
||||||
|
|
||||||
BinModifiers {
|
BoolModifier { Bool }
|
||||||
Bool?
|
|
||||||
(
|
binModifiers {
|
||||||
OnOrIgnoring
|
BoolModifier?
|
||||||
(
|
MatchingModifierClause?
|
||||||
(GroupLeft | GroupRight)
|
|
||||||
(!mul GroupingLabels)? // TODO: Is the "!mul" here correct? Inserted it to resolve a shift/reduce conflict because we always want to count opening parenthesis after this to be counted toward this modifier, not toward a next sub-expression.
|
|
||||||
)?
|
|
||||||
)?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupingLabels {
|
GroupingLabels {
|
||||||
"(" GroupingLabelList ")" |
|
"(" (LabelName ("," LabelName)* ","?)? ")"
|
||||||
"(" GroupingLabelList "," ")" |
|
|
||||||
"(" ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupingLabelList {
|
|
||||||
GroupingLabelList "," GroupingLabel |
|
|
||||||
GroupingLabel
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupingLabel {
|
|
||||||
LabelName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCall {
|
FunctionCall {
|
||||||
|
@ -189,34 +175,28 @@ FunctionIdentifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCallBody {
|
FunctionCallBody {
|
||||||
"(" FunctionCallArgs ")" |
|
"(" (expr ("," expr)*)? ")"
|
||||||
"(" ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionCallArgs {
|
|
||||||
FunctionCallArgs "," Expr |
|
|
||||||
Expr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParenExpr {
|
ParenExpr {
|
||||||
"(" Expr ")"
|
"(" expr ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
OffsetExpr {
|
OffsetExpr {
|
||||||
Expr Offset Sub? Duration
|
expr Offset Sub? Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
MatrixSelector {
|
MatrixSelector {
|
||||||
// TODO: Can this not be more specific than "Expr"?
|
// TODO: Can this not be more specific than "expr"?
|
||||||
Expr "[" Duration "]"
|
expr "[" Duration "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
SubqueryExpr {
|
SubqueryExpr {
|
||||||
Expr "[" Duration ":" ("" | Duration) "]"
|
expr "[" Duration ":" ("" | Duration) "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
UnaryExpr {
|
UnaryExpr {
|
||||||
!mul UnaryOp~signed Expr
|
!mul UnaryOp~signed expr
|
||||||
}
|
}
|
||||||
|
|
||||||
UnaryOp {
|
UnaryOp {
|
||||||
|
@ -225,20 +205,13 @@ UnaryOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorSelector {
|
VectorSelector {
|
||||||
MetricIdentifier LabelMatchers |
|
Identifier LabelMatchers |
|
||||||
MetricIdentifier |
|
Identifier |
|
||||||
LabelMatchers
|
LabelMatchers
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelMatchers {
|
LabelMatchers {
|
||||||
"{" LabelMatchList "}" |
|
"{" (LabelMatcher ("," LabelMatcher)* ","?)? "}"
|
||||||
"{" LabelMatchList "," "}" |
|
|
||||||
"{" "}"
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelMatchList {
|
|
||||||
LabelMatchList "," LabelMatcher |
|
|
||||||
LabelMatcher
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchOp {
|
MatchOp {
|
||||||
|
@ -252,12 +225,8 @@ LabelMatcher {
|
||||||
LabelName MatchOp StringLiteral
|
LabelName MatchOp StringLiteral
|
||||||
}
|
}
|
||||||
|
|
||||||
MetricIdentifier {
|
|
||||||
Identifier
|
|
||||||
}
|
|
||||||
|
|
||||||
StepInvariantExpr {
|
StepInvariantExpr {
|
||||||
Expr At ( NumberLiteral | AtModifierPreprocessors "(" ")" )
|
expr At ( NumberLiteral | AtModifierPreprocessors "(" ")" )
|
||||||
}
|
}
|
||||||
|
|
||||||
AtModifierPreprocessors {
|
AtModifierPreprocessors {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Double-quoted string literal
|
# Double-quoted string literal
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ PromQL(Expr(NumberLiteral))
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(StringLiteral))
|
PromQL(StringLiteral)
|
||||||
|
|
||||||
# Single-quoted string literal
|
# Single-quoted string literal
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ PromQL(Expr(StringLiteral))
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(StringLiteral))
|
PromQL(StringLiteral)
|
||||||
|
|
||||||
# Backtick-quoted string literal
|
# Backtick-quoted string literal
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ PromQL(Expr(StringLiteral))
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(StringLiteral))
|
PromQL(StringLiteral)
|
||||||
|
|
||||||
# Backtick-quoted multi-line string literal
|
# Backtick-quoted multi-line string literal
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ string`
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(StringLiteral))
|
PromQL(StringLiteral)
|
||||||
|
|
||||||
# Addition
|
# Addition
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ PromQL(Expr(StringLiteral))
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(BinaryExpr(Expr(NumberLiteral), Add, BinModifiers, Expr(NumberLiteral))))
|
PromQL(BinaryExpr(NumberLiteral, Add, NumberLiteral))
|
||||||
|
|
||||||
# Complex expression
|
# Complex expression
|
||||||
|
|
||||||
|
@ -55,87 +55,53 @@ sum by(job, mode) (rate(node_cpu_seconds_total[1m])) / on(job) group_left sum by
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
AggregateExpr(
|
AggregateExpr(
|
||||||
AggregateOp(Sum),
|
AggregateOp(Sum),
|
||||||
AggregateModifier(
|
AggregateModifier(
|
||||||
By,
|
By,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName,
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
),
|
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(Rate),
|
FunctionIdentifier(Rate),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
MatrixSelector(
|
MatrixSelector(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Duration
|
Duration
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Div,
|
Div,
|
||||||
BinModifiers(
|
MatchingModifierClause(
|
||||||
OnOrIgnoring(
|
|
||||||
On,
|
On,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
),
|
|
||||||
GroupLeft
|
GroupLeft
|
||||||
),
|
),
|
||||||
Expr(
|
|
||||||
AggregateExpr(
|
AggregateExpr(
|
||||||
AggregateOp(Sum),
|
AggregateOp(Sum),
|
||||||
AggregateModifier(
|
AggregateModifier(
|
||||||
By,
|
By,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(Rate),
|
FunctionIdentifier(Rate),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
MatrixSelector(
|
MatrixSelector(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Duration
|
Duration
|
||||||
)
|
)
|
||||||
|
@ -144,12 +110,6 @@ PromQL(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Case insensitivity for aggregations and binop modifiers.
|
# Case insensitivity for aggregations and binop modifiers.
|
||||||
|
@ -159,67 +119,43 @@ SuM BY(testlabel1) (testmetric1) / IGNOring(testlabel2) AVG withOUT(testlabel3)
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
AggregateExpr(
|
AggregateExpr(
|
||||||
AggregateOp(Sum),
|
AggregateOp(Sum),
|
||||||
AggregateModifier(
|
AggregateModifier(
|
||||||
By,
|
By,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(Identifier)
|
Identifier
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Div,
|
Div,
|
||||||
BinModifiers(
|
MatchingModifierClause(
|
||||||
OnOrIgnoring(
|
|
||||||
Ignoring,
|
Ignoring,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Expr(
|
|
||||||
AggregateExpr(
|
AggregateExpr(
|
||||||
AggregateOp(Avg),
|
AggregateOp(Avg),
|
||||||
AggregateModifier(
|
AggregateModifier(
|
||||||
Without,
|
Without,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Case insensitivity for set operators
|
# Case insensitivity for set operators
|
||||||
|
@ -229,85 +165,40 @@ metric1 and metric2 AND metric3 unless metric4 UNLESS metric5 or metric6 OR metr
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
VectorSelector(Identifier),
|
||||||
VectorSelector(
|
And,
|
||||||
MetricIdentifier(Identifier)
|
VectorSelector(Identifier)
|
||||||
)
|
|
||||||
),
|
),
|
||||||
And,
|
And,
|
||||||
BinModifiers,
|
VectorSelector(Identifier)
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(Identifier)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
And,
|
|
||||||
BinModifiers,
|
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(Identifier)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Unless,
|
Unless,
|
||||||
BinModifiers,
|
VectorSelector(Identifier)
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(Identifier)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Unless,
|
Unless,
|
||||||
BinModifiers,
|
VectorSelector(Identifier)
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(Identifier)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Or,
|
Or,
|
||||||
BinModifiers,
|
VectorSelector(Identifier)
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(Identifier)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Or,
|
Or,
|
||||||
BinModifiers,
|
VectorSelector(Identifier)
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(Identifier)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Duration units
|
# Duration units
|
||||||
|
|
||||||
foo[1y2w3d4h5m6s7ms]
|
foo[1y2w3d4h5m6s7ms]
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(MatrixSelector(Expr(VectorSelector(MetricIdentifier(Identifier))),Duration)))
|
PromQL(MatrixSelector(VectorSelector(Identifier),Duration))
|
||||||
|
|
||||||
# Incorrectly ordered duration units
|
# Incorrectly ordered duration units
|
||||||
|
|
||||||
|
@ -315,7 +206,7 @@ foo[1m2h]
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(SubqueryExpr(Expr(VectorSelector(MetricIdentifier(Identifier))),Duration,⚠,Duration)))
|
PromQL(SubqueryExpr(VectorSelector(Identifier),Duration,⚠,Duration))
|
||||||
|
|
||||||
# Using a function name as a metric name
|
# Using a function name as a metric name
|
||||||
|
|
||||||
|
@ -323,7 +214,7 @@ rate
|
||||||
|
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(Expr(VectorSelector(MetricIdentifier(Identifier))))
|
PromQL(VectorSelector(Identifier))
|
||||||
|
|
||||||
# Match operators
|
# Match operators
|
||||||
|
|
||||||
|
@ -332,39 +223,29 @@ metric_name{a="1",b!="2",c=~"3",d!~"4"}
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(Identifier),
|
Identifier,
|
||||||
LabelMatchers(
|
LabelMatchers(
|
||||||
LabelMatchList(
|
|
||||||
LabelMatchList(
|
|
||||||
LabelMatchList(
|
|
||||||
LabelMatchList(
|
|
||||||
LabelMatcher(
|
LabelMatcher(
|
||||||
LabelName,
|
LabelName,
|
||||||
MatchOp(EqlSingle),
|
MatchOp(EqlSingle),
|
||||||
StringLiteral
|
StringLiteral
|
||||||
)
|
|
||||||
),
|
),
|
||||||
LabelMatcher(
|
LabelMatcher(
|
||||||
LabelName,
|
LabelName,
|
||||||
MatchOp(Neq),
|
MatchOp(Neq),
|
||||||
StringLiteral
|
StringLiteral
|
||||||
)
|
|
||||||
),
|
),
|
||||||
LabelMatcher(
|
LabelMatcher(
|
||||||
LabelName,
|
LabelName,
|
||||||
MatchOp(EqlRegex),
|
MatchOp(EqlRegex),
|
||||||
StringLiteral
|
StringLiteral
|
||||||
)
|
|
||||||
),
|
),
|
||||||
LabelMatcher(
|
LabelMatcher(
|
||||||
LabelName,
|
LabelName,
|
||||||
MatchOp(NeqRegex),
|
MatchOp(NeqRegex),
|
||||||
StringLiteral
|
StringLiteral
|
||||||
)
|
)
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -376,17 +257,13 @@ metric_name > bool 1
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(Identifier)
|
Identifier
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Gtr,
|
Gtr,
|
||||||
BinModifiers(Bool),
|
BoolModifier(Bool),
|
||||||
Expr(NumberLiteral)
|
NumberLiteral
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -397,42 +274,26 @@ metric1 + on(foo) group_left(bar, baz) metric2
|
||||||
==>
|
==>
|
||||||
|
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(Identifier)
|
Identifier
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Add,
|
Add,
|
||||||
BinModifiers(
|
MatchingModifierClause(
|
||||||
OnOrIgnoring(
|
|
||||||
On,
|
On,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
),
|
|
||||||
GroupLeft,
|
GroupLeft,
|
||||||
GroupingLabels(
|
GroupingLabels(
|
||||||
GroupingLabelList(
|
LabelName,
|
||||||
GroupingLabelList(
|
LabelName
|
||||||
GroupingLabel(LabelName)
|
|
||||||
),
|
|
||||||
GroupingLabel(LabelName)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Function last_over_time
|
# Function last_over_time
|
||||||
|
@ -441,27 +302,17 @@ last_over_time(data[1m])
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(LastOverTime),
|
FunctionIdentifier(LastOverTime),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
MatrixSelector(
|
MatrixSelector(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Duration
|
Duration
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Function sgn
|
# Function sgn
|
||||||
|
@ -470,22 +321,14 @@ sgn(data)
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(Sgn),
|
FunctionIdentifier(Sgn),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Function clamp
|
# Function clamp
|
||||||
|
@ -494,26 +337,12 @@ clamp(data,0,1)
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(Clamp),
|
FunctionIdentifier(Clamp),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
VectorSelector(Identifier),
|
||||||
FunctionCallArgs(
|
NumberLiteral,
|
||||||
FunctionCallArgs(
|
NumberLiteral
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Expr(NumberLiteral)
|
|
||||||
),
|
|
||||||
Expr(NumberLiteral)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -523,14 +352,14 @@ PromQL(
|
||||||
start
|
start
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(VectorSelector(MetricIdentifier(Identifier))))
|
PromQL(VectorSelector(Identifier))
|
||||||
|
|
||||||
# Metric end
|
# Metric end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(VectorSelector(MetricIdentifier(Identifier))))
|
PromQL(VectorSelector(Identifier))
|
||||||
|
|
||||||
# Simple At start
|
# Simple At start
|
||||||
|
|
||||||
|
@ -538,19 +367,13 @@ foo @ start()
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
),
|
||||||
)
|
|
||||||
)
|
|
||||||
At,
|
At,
|
||||||
AtModifierPreprocessors(Start),
|
AtModifierPreprocessors(Start),
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Simple At end
|
# Simple At end
|
||||||
|
@ -559,19 +382,13 @@ foo @ end()
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
),
|
||||||
)
|
|
||||||
)
|
|
||||||
At,
|
At,
|
||||||
AtModifierPreprocessors(End),
|
AtModifierPreprocessors(End),
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Simple At number
|
# Simple At number
|
||||||
|
@ -580,19 +397,13 @@ foo @ 1234
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
),
|
||||||
)
|
|
||||||
)
|
|
||||||
At,
|
At,
|
||||||
NumberLiteral
|
NumberLiteral
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# At Modifier with space between bracket
|
# At Modifier with space between bracket
|
||||||
|
@ -601,19 +412,13 @@ foo @ start( )
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
),
|
||||||
)
|
|
||||||
)
|
|
||||||
At,
|
At,
|
||||||
AtModifierPreprocessors(Start),
|
AtModifierPreprocessors(Start),
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Complex test with At modifier
|
# Complex test with At modifier
|
||||||
|
@ -624,46 +429,26 @@ topk(7, rate(process_cpu_seconds_total[1h] @ 1234))
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
BinaryExpr(
|
BinaryExpr(
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(Rate),
|
FunctionIdentifier(Rate),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
MatrixSelector(
|
MatrixSelector(
|
||||||
Expr(VectorSelector(MetricIdentifier(Identifier))),
|
VectorSelector(Identifier),
|
||||||
Duration
|
Duration
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
And,
|
And,
|
||||||
BinModifiers,
|
|
||||||
Expr(
|
|
||||||
AggregateExpr(
|
AggregateExpr(
|
||||||
AggregateOp(Topk),
|
AggregateOp(Topk),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
NumberLiteral,
|
||||||
FunctionCallArgs(Expr(NumberLiteral)),
|
|
||||||
Expr(
|
|
||||||
FunctionCall(
|
FunctionCall(
|
||||||
FunctionIdentifier(Rate),
|
FunctionIdentifier(Rate),
|
||||||
FunctionCallBody(
|
FunctionCallBody(
|
||||||
FunctionCallArgs(
|
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
MatrixSelector(VectorSelector(Identifier), Duration),
|
||||||
MatrixSelector(
|
|
||||||
Expr(
|
|
||||||
VectorSelector(MetricIdentifier(Identifier))
|
|
||||||
),
|
|
||||||
Duration
|
|
||||||
)
|
|
||||||
),
|
|
||||||
At,
|
At,
|
||||||
NumberLiteral
|
NumberLiteral
|
||||||
)
|
)
|
||||||
|
@ -672,12 +457,6 @@ PromQL(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# At modifier with negative number
|
# At modifier with negative number
|
||||||
|
@ -686,19 +465,13 @@ foo @ - 1234
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
),
|
||||||
)
|
|
||||||
)
|
|
||||||
At,
|
At,
|
||||||
NumberLiteral
|
NumberLiteral
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# At modifier with explicit positive number
|
# At modifier with explicit positive number
|
||||||
|
@ -707,19 +480,13 @@ foo @ + 1234
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(
|
PromQL(
|
||||||
Expr(
|
|
||||||
StepInvariantExpr(
|
StepInvariantExpr(
|
||||||
Expr(
|
|
||||||
VectorSelector(
|
VectorSelector(
|
||||||
MetricIdentifier(
|
|
||||||
Identifier
|
Identifier
|
||||||
)
|
),
|
||||||
)
|
|
||||||
)
|
|
||||||
At,
|
At,
|
||||||
NumberLiteral
|
NumberLiteral
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Metric prefixed by Inf
|
# Metric prefixed by Inf
|
||||||
|
@ -727,123 +494,123 @@ PromQL(
|
||||||
infra
|
infra
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(VectorSelector(MetricIdentifier(Identifier))))
|
PromQL(VectorSelector(Identifier))
|
||||||
|
|
||||||
# Metric prefixed by Nan
|
# Metric prefixed by Nan
|
||||||
|
|
||||||
nananere
|
nananere
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(VectorSelector(MetricIdentifier(Identifier))))
|
PromQL(VectorSelector(Identifier))
|
||||||
|
|
||||||
# Mixed-case NaN.
|
# Mixed-case NaN.
|
||||||
|
|
||||||
NaN
|
NaN
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Lower-cased NaN.
|
# Lower-cased NaN.
|
||||||
|
|
||||||
nan
|
nan
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Inf.
|
# Inf.
|
||||||
|
|
||||||
Inf
|
Inf
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Negative Inf.
|
# Negative Inf.
|
||||||
|
|
||||||
-Inf
|
-Inf
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Positive Inf.
|
# Positive Inf.
|
||||||
|
|
||||||
+Inf
|
+Inf
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Lower-cased Inf.
|
# Lower-cased Inf.
|
||||||
|
|
||||||
inf
|
inf
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Upper-cased Inf.
|
# Upper-cased Inf.
|
||||||
|
|
||||||
INF
|
INF
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Negative number literal.
|
# Negative number literal.
|
||||||
|
|
||||||
-42
|
-42
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Explicitly positive number literal.
|
# Explicitly positive number literal.
|
||||||
|
|
||||||
+42
|
+42
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(NumberLiteral))
|
PromQL(NumberLiteral)
|
||||||
|
|
||||||
# Trying to illegally use NaN as a metric name.
|
# Trying to illegally use NaN as a metric name.
|
||||||
|
|
||||||
NaN{foo="bar"}
|
NaN{foo="bar"}
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(BinaryExpr(Expr(NumberLiteral),⚠,BinModifiers,Expr(VectorSelector(LabelMatchers(LabelMatchList(LabelMatcher(LabelName,MatchOp(EqlSingle),StringLiteral))))))))
|
PromQL(BinaryExpr(NumberLiteral,⚠,VectorSelector(LabelMatchers(LabelMatcher(LabelName,MatchOp(EqlSingle),StringLiteral)))))
|
||||||
|
|
||||||
# Trying to illegally use Inf as a metric name.
|
# Trying to illegally use Inf as a metric name.
|
||||||
|
|
||||||
Inf{foo="bar"}
|
Inf{foo="bar"}
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(BinaryExpr(Expr(NumberLiteral),⚠,BinModifiers,Expr(VectorSelector(LabelMatchers(LabelMatchList(LabelMatcher(LabelName,MatchOp(EqlSingle),StringLiteral))))))))
|
PromQL(BinaryExpr(NumberLiteral,⚠,VectorSelector(LabelMatchers(LabelMatcher(LabelName,MatchOp(EqlSingle),StringLiteral)))))
|
||||||
|
|
||||||
# Negative offset
|
# Negative offset
|
||||||
|
|
||||||
foo offset -5d
|
foo offset -5d
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(OffsetExpr(Expr(VectorSelector(MetricIdentifier(Identifier))), Offset, Sub, Duration)))
|
PromQL(OffsetExpr(VectorSelector(Identifier), Offset, Sub, Duration))
|
||||||
|
|
||||||
# Negative offset with space
|
# Negative offset with space
|
||||||
|
|
||||||
foo offset - 5d
|
foo offset - 5d
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(OffsetExpr(Expr(VectorSelector(MetricIdentifier(Identifier))), Offset, Sub, Duration)))
|
PromQL(OffsetExpr(VectorSelector(Identifier), Offset, Sub, Duration))
|
||||||
|
|
||||||
# Positive offset
|
# Positive offset
|
||||||
|
|
||||||
foo offset 5d
|
foo offset 5d
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(OffsetExpr(Expr(VectorSelector(MetricIdentifier(Identifier))), Offset, Duration)))
|
PromQL(OffsetExpr(VectorSelector(Identifier), Offset, Duration))
|
||||||
|
|
||||||
# Parsing only metric names with alternative @top { "top": "MetricName" }
|
# Parsing only metric names with alternative @top { "top": "MetricName" }
|
||||||
|
|
||||||
sum:my_metric_name:rate5m
|
sum:my_metric_name:rate5m
|
||||||
|
|
||||||
==>
|
==>
|
||||||
MetricName(MetricIdentifier(Identifier))
|
MetricName(Identifier)
|
||||||
|
|
||||||
# Testing Atan2 inherited precedence level
|
# Testing Atan2 inherited precedence level
|
||||||
|
|
||||||
1 + foo atan2 bar
|
1 + foo atan2 bar
|
||||||
|
|
||||||
==>
|
==>
|
||||||
PromQL(Expr(BinaryExpr(Expr(NumberLiteral),Add,BinModifiers,Expr(BinaryExpr(Expr(VectorSelector(MetricIdentifier(Identifier))),Atan2,BinModifiers,Expr(VectorSelector(MetricIdentifier(Identifier))))))))
|
PromQL(BinaryExpr(NumberLiteral,Add,BinaryExpr(VectorSelector(Identifier),Atan2,VectorSelector(Identifier))))
|
||||||
|
|
|
@ -52,27 +52,27 @@ describe('SeriesName', () => {
|
||||||
{ name: '}', className: 'legend-label-brace' },
|
{ name: '}', className: 'legend-label-brace' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const testLabelContainerElement = (text:string, expectedText:string, container: ShallowWrapper) => {
|
const testLabelContainerElement = (text: string, expectedText: string, container: ShallowWrapper) => {
|
||||||
expect(text).toEqual(expectedText);
|
expect(text).toEqual(expectedText);
|
||||||
expect(container.prop('className')).toEqual('legend-label-container');
|
expect(container.prop('className')).toEqual('legend-label-container');
|
||||||
expect(container.childAt(0).prop('className')).toEqual('legend-label-name');
|
expect(container.childAt(0).prop('className')).toEqual('legend-label-name');
|
||||||
expect(container.childAt(2).prop('className')).toEqual('legend-label-value');
|
expect(container.childAt(2).prop('className')).toEqual('legend-label-value');
|
||||||
}
|
};
|
||||||
|
|
||||||
testCases.forEach((tc, i) => {
|
testCases.forEach((tc, i) => {
|
||||||
const child = seriesName.childAt(i);
|
const child = seriesName.childAt(i);
|
||||||
const firstChildElement = child.childAt(0);
|
const firstChildElement = child.childAt(0);
|
||||||
const firstChildElementClass = firstChildElement.prop('className')
|
const firstChildElementClass = firstChildElement.prop('className');
|
||||||
const text = child
|
const text = child
|
||||||
.children()
|
.children()
|
||||||
.map((ch) => ch.text())
|
.map((ch) => ch.text())
|
||||||
.join('');
|
.join('');
|
||||||
switch (child.children().length) {
|
switch (child.children().length) {
|
||||||
case 1:
|
case 1:
|
||||||
switch(firstChildElementClass) {
|
switch (firstChildElementClass) {
|
||||||
case 'legend-label-container':
|
case 'legend-label-container':
|
||||||
testLabelContainerElement(text, `${tc.name}="${tc.value}"`, firstChildElement)
|
testLabelContainerElement(text, `${tc.name}="${tc.value}"`, firstChildElement);
|
||||||
break
|
break;
|
||||||
default:
|
default:
|
||||||
expect(text).toEqual(tc.name);
|
expect(text).toEqual(tc.name);
|
||||||
expect(child.prop('className')).toEqual(tc.className);
|
expect(child.prop('className')).toEqual(tc.className);
|
||||||
|
@ -80,7 +80,7 @@ describe('SeriesName', () => {
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
const container = child.childAt(1);
|
const container = child.childAt(1);
|
||||||
testLabelContainerElement(text, `, ${tc.name}="${tc.value}"`, container)
|
testLabelContainerElement(text, `, ${tc.name}="${tc.value}"`, container);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fail('incorrect number of children: ' + child.children().length);
|
fail('incorrect number of children: ' + child.children().length);
|
||||||
|
|
|
@ -11,7 +11,7 @@ const SeriesName: FC<SeriesNameProps> = ({ labels, format }) => {
|
||||||
const setClipboardMsg = useToastContext();
|
const setClipboardMsg = useToastContext();
|
||||||
|
|
||||||
const toClipboard = (e: React.MouseEvent<HTMLSpanElement>) => {
|
const toClipboard = (e: React.MouseEvent<HTMLSpanElement>) => {
|
||||||
let copyText = e.currentTarget.innerText || '';
|
const copyText = e.currentTarget.innerText || '';
|
||||||
navigator.clipboard
|
navigator.clipboard
|
||||||
.writeText(copyText.trim())
|
.writeText(copyText.trim())
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
Loading…
Reference in a new issue