mirror of
https://github.com/prometheus/prometheus.git
synced 2026-05-04 20:06:12 +02:00
feat(ui): Support anchored and smoothed keyword in promql editor (#17239)
* feat(ui): Support anchored and smoothed keyword in promql editor Signed-off-by: Augustin Husson <husson.augustin@gmail.com> * change parser logic about smoothed/anchored expression Signed-off-by: Augustin Husson <husson.augustin@gmail.com> --------- Signed-off-by: Augustin Husson <husson.augustin@gmail.com>
This commit is contained in:
parent
460d19c99a
commit
e67218a39e
@ -376,7 +376,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode, pos: num
|
||||
{ kind: ContextKind.Aggregation }
|
||||
);
|
||||
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 to avoid to autocomplete a number in situation where it shouldn't.
|
||||
// Like with `sum by(rat)`
|
||||
result.push({ kind: ContextKind.Number });
|
||||
}
|
||||
|
||||
@ -15,11 +15,14 @@ import { Diagnostic } from '@codemirror/lint';
|
||||
import { SyntaxNode, Tree } from '@lezer/common';
|
||||
import {
|
||||
AggregateExpr,
|
||||
AnchoredExpr,
|
||||
And,
|
||||
BinaryExpr,
|
||||
BoolModifier,
|
||||
Bottomk,
|
||||
Changes,
|
||||
CountValues,
|
||||
Delta,
|
||||
Eql,
|
||||
EqlSingle,
|
||||
FunctionCall,
|
||||
@ -27,6 +30,7 @@ import {
|
||||
Gte,
|
||||
Gtr,
|
||||
Identifier,
|
||||
Increase,
|
||||
LabelMatchers,
|
||||
LimitK,
|
||||
LimitRatio,
|
||||
@ -39,6 +43,9 @@ import {
|
||||
Quantile,
|
||||
QuotedLabelMatcher,
|
||||
QuotedLabelName,
|
||||
Rate,
|
||||
Resets,
|
||||
SmoothedExpr,
|
||||
StepInvariantExpr,
|
||||
SubqueryExpr,
|
||||
Topk,
|
||||
@ -52,7 +59,7 @@ import { getType } from './type';
|
||||
import { buildLabelMatchers } from './matcher';
|
||||
import { EditorState } from '@codemirror/state';
|
||||
import { syntaxTree } from '@codemirror/language';
|
||||
import { getFunction, Matcher, VectorMatchCardinality, ValueType } from '../types';
|
||||
import { getFunction, Matcher, ValueType, VectorMatchCardinality } from '../types';
|
||||
import { buildVectorMatching } from './vector';
|
||||
|
||||
export class Parser {
|
||||
@ -123,6 +130,14 @@ export class Parser {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SmoothedExpr: {
|
||||
this.checkAnchoredSmoothedExpr(node, [Rate, Increase, Delta]);
|
||||
break;
|
||||
}
|
||||
case AnchoredExpr: {
|
||||
this.checkAnchoredSmoothedExpr(node, [Resets, Changes, Rate, Increase, Delta]);
|
||||
break;
|
||||
}
|
||||
case SubqueryExpr: {
|
||||
const subQueryExprType = this.checkAST(node.getChild('Expr'));
|
||||
if (subQueryExprType !== ValueType.vector) {
|
||||
@ -300,6 +315,31 @@ export class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
private checkAnchoredSmoothedExpr(node: SyntaxNode, allowedFunctions: number[]): void {
|
||||
// A smoothed/anchored expression is supposed to work with range vectors or instant vectors.
|
||||
// So first thing to do is to check the type of the child.
|
||||
// Then, if this is used inside a function call, we need to check that the function is one of the given allowedFunctions.
|
||||
const nodeType = getType(node);
|
||||
if (nodeType !== ValueType.vector && nodeType !== ValueType.matrix) {
|
||||
this.addDiagnostic(node, `smoothed/anchored expression only allowed on instant vector or range vector selector, got ${nodeType} instead`);
|
||||
return;
|
||||
}
|
||||
const parent = node.parent?.parent;
|
||||
if (!parent || parent.type.id !== FunctionCall) {
|
||||
// Since the anchored/smoothed expression is not inside a function call, we cannot check the function name.
|
||||
// This is an acceptable case as the anchored/smoothed expression can be used on any vector expression.
|
||||
return;
|
||||
}
|
||||
const funcID = parent.firstChild?.firstChild;
|
||||
if (!funcID) {
|
||||
this.addDiagnostic(node, 'function not defined');
|
||||
return;
|
||||
}
|
||||
if (!allowedFunctions.includes(funcID.type.id)) {
|
||||
this.addDiagnostic(node, 'smoothed/anchored expression can only be used in specific functions');
|
||||
}
|
||||
}
|
||||
|
||||
private checkVectorSelector(node: SyntaxNode): void {
|
||||
const matchList = node.getChild(LabelMatchers);
|
||||
const labelMatcherOpts = [QuotedLabelName, QuotedLabelMatcher, UnquotedLabelMatcher];
|
||||
|
||||
@ -14,12 +14,14 @@
|
||||
import { SyntaxNode } from '@lezer/common';
|
||||
import {
|
||||
AggregateExpr,
|
||||
AnchoredExpr,
|
||||
BinaryExpr,
|
||||
FunctionCall,
|
||||
MatrixSelector,
|
||||
NumberDurationLiteral,
|
||||
OffsetExpr,
|
||||
ParenExpr,
|
||||
SmoothedExpr,
|
||||
StepInvariantExpr,
|
||||
StringLiteral,
|
||||
SubqueryExpr,
|
||||
@ -48,6 +50,10 @@ export function getType(node: SyntaxNode | null): ValueType {
|
||||
return ValueType.matrix;
|
||||
case SubqueryExpr:
|
||||
return ValueType.matrix;
|
||||
case SmoothedExpr:
|
||||
return getType(node.firstChild);
|
||||
case AnchoredExpr:
|
||||
return getType(node.firstChild);
|
||||
case ParenExpr:
|
||||
return getType(node.getChild('Expr'));
|
||||
case UnaryExpr:
|
||||
|
||||
@ -23,7 +23,7 @@ export const promQLHighLight = styleTags({
|
||||
'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 HistogramAvg HistogramCount HistogramFraction HistogramQuantile HistogramSum DoubleExponentialSmoothing 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 SortByLabel SortByLabelDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
|
||||
tags.function(tags.variableName),
|
||||
'Avg Bottomk Count Count_values Group LimitK LimitRatio Max Min Quantile Stddev Stdvar Sum Topk': tags.operatorKeyword,
|
||||
'By Without Bool On Ignoring GroupLeft GroupRight Offset Start End': tags.modifier,
|
||||
'By Without Bool On Ignoring GroupLeft GroupRight Offset Start End Smoothed Anchored': tags.modifier,
|
||||
'And Unless Or': tags.logicOperator,
|
||||
'Sub Add Mul Mod Div Atan2 Eql Neq Lte Lss Gte Gtr EqlRegex EqlSingle NeqRegex Pow At': tags.operator,
|
||||
UnaryOp: tags.arithmeticOperator,
|
||||
|
||||
@ -31,6 +31,8 @@ expr[@isGroup=Expr] {
|
||||
MatrixSelector |
|
||||
NumberDurationLiteral |
|
||||
OffsetExpr |
|
||||
AnchoredExpr |
|
||||
SmoothedExpr |
|
||||
ParenExpr |
|
||||
StringLiteral |
|
||||
SubqueryExpr |
|
||||
@ -39,6 +41,14 @@ expr[@isGroup=Expr] {
|
||||
StepInvariantExpr
|
||||
}
|
||||
|
||||
AnchoredExpr {
|
||||
expr Anchored
|
||||
}
|
||||
|
||||
SmoothedExpr {
|
||||
expr Smoothed
|
||||
}
|
||||
|
||||
AggregateExpr {
|
||||
AggregateOp AggregateModifier FunctionCallBody |
|
||||
AggregateOp FunctionCallBody AggregateModifier |
|
||||
@ -354,7 +364,9 @@ NumberDurationLiteralInDurationContext {
|
||||
Or,
|
||||
Unless,
|
||||
Start,
|
||||
End
|
||||
End,
|
||||
Smoothed,
|
||||
Anchored
|
||||
}
|
||||
|
||||
@external propSource promQLHighLight from "./highlight"
|
||||
|
||||
@ -42,6 +42,8 @@ import {
|
||||
Topk,
|
||||
Unless,
|
||||
Without,
|
||||
Smoothed,
|
||||
Anchored,
|
||||
} from './parser.terms.js';
|
||||
|
||||
const keywordTokens = {
|
||||
@ -82,6 +84,8 @@ const contextualKeywordTokens = {
|
||||
unless: Unless,
|
||||
start: Start,
|
||||
end: End,
|
||||
smoothed: Smoothed,
|
||||
anchored: Anchored,
|
||||
};
|
||||
|
||||
export const extendIdentifier = (value, stack) => {
|
||||
|
||||
@ -702,3 +702,17 @@ PromQL(VectorSelector(LabelMatchers(QuotedLabelMatcher(QuotedLabelName(StringLit
|
||||
|
||||
==>
|
||||
PromQL(VectorSelector(LabelMatchers(QuotedLabelName(StringLiteral), QuotedLabelMatcher(QuotedLabelName(StringLiteral), MatchOp(EqlSingle), StringLiteral))))
|
||||
|
||||
# Testing anchored keyword
|
||||
|
||||
increase(caddy_http_requests_total[5m] anchored)
|
||||
|
||||
==>
|
||||
PromQL(FunctionCall(FunctionIdentifier(Increase),FunctionCallBody(AnchoredExpr(MatrixSelector(VectorSelector(Identifier),NumberDurationLiteralInDurationContext),Anchored))))
|
||||
|
||||
# Testing smoothed keyword
|
||||
|
||||
rate(caddy_http_requests_total[5m] smoothed)
|
||||
|
||||
==>
|
||||
PromQL(FunctionCall(FunctionIdentifier(Rate),FunctionCallBody(SmoothedExpr(MatrixSelector(VectorSelector(Identifier),NumberDurationLiteralInDurationContext),Smoothed))))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user