mirror of https://github.com/prometheus/prometheus
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
9.1 KiB
250 lines
9.1 KiB
// Copyright 2013 Prometheus Team |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
|
|
%{ |
|
package rules |
|
|
|
import ( |
|
clientmodel "github.com/prometheus/client_golang/model" |
|
|
|
"github.com/prometheus/prometheus/rules/ast" |
|
"github.com/prometheus/prometheus/storage/metric" |
|
) |
|
%} |
|
|
|
%union { |
|
num clientmodel.SampleValue |
|
str string |
|
ruleNode ast.Node |
|
ruleNodeSlice []ast.Node |
|
boolean bool |
|
labelNameSlice clientmodel.LabelNames |
|
labelSet clientmodel.LabelSet |
|
labelMatcher *metric.LabelMatcher |
|
labelMatchers metric.LabelMatchers |
|
} |
|
|
|
/* We simulate multiple start symbols for closely-related grammars via dummy tokens. See |
|
http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html |
|
Reason: we want to be able to parse lists of named rules as well as single expressions. |
|
*/ |
|
%token START_RULES START_EXPRESSION |
|
|
|
%token <str> IDENTIFIER STRING DURATION METRICNAME |
|
%token <num> NUMBER |
|
%token PERMANENT GROUP_OP KEEPING_EXTRA |
|
%token <str> AGGR_OP CMP_OP ADDITIVE_OP MULT_OP |
|
%token ALERT IF FOR WITH SUMMARY DESCRIPTION |
|
|
|
%type <ruleNodeSlice> func_arg_list |
|
%type <labelNameSlice> label_list grouping_opts |
|
%type <labelSet> label_assign label_assign_list rule_labels |
|
%type <labelMatcher> label_match |
|
%type <labelMatchers> label_match_list label_matches |
|
%type <ruleNode> rule_expr func_arg |
|
%type <boolean> qualifier extra_labels_opts |
|
%type <str> for_duration metric_name label_match_type |
|
|
|
%right '=' |
|
%left CMP_OP |
|
%left ADDITIVE_OP |
|
%left MULT_OP |
|
%start start |
|
|
|
%% |
|
start : START_RULES rules_stat_list |
|
| START_EXPRESSION saved_rule_expr |
|
; |
|
|
|
rules_stat_list : /* empty */ |
|
| rules_stat_list rules_stat |
|
; |
|
|
|
saved_rule_expr : rule_expr |
|
{ yylex.(*RulesLexer).parsedExpr = $1 } |
|
; |
|
|
|
|
|
rules_stat : qualifier metric_name rule_labels '=' rule_expr |
|
{ |
|
rule, err := CreateRecordingRule($2, $3, $5, $1) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) |
|
} |
|
| ALERT IDENTIFIER IF rule_expr for_duration WITH rule_labels SUMMARY STRING DESCRIPTION STRING |
|
{ |
|
rule, err := CreateAlertingRule($2, $4, $5, $7, $9, $11) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) |
|
} |
|
; |
|
|
|
for_duration : /* empty */ |
|
{ $$ = "0s" } |
|
| FOR DURATION |
|
{ $$ = $2 } |
|
; |
|
|
|
qualifier : /* empty */ |
|
{ $$ = false } |
|
| PERMANENT |
|
{ $$ = true } |
|
; |
|
|
|
metric_name : METRICNAME |
|
{ $$ = $1 } |
|
| IDENTIFIER |
|
{ $$ = $1 } |
|
; |
|
|
|
rule_labels : /* empty */ |
|
{ $$ = clientmodel.LabelSet{} } |
|
| '{' label_assign_list '}' |
|
{ $$ = $2 } |
|
| '{' '}' |
|
{ $$ = clientmodel.LabelSet{} } |
|
|
|
label_assign_list : label_assign |
|
{ $$ = $1 } |
|
| label_assign_list ',' label_assign |
|
{ for k, v := range $3 { $$[k] = v } } |
|
; |
|
|
|
label_assign : IDENTIFIER '=' STRING |
|
{ $$ = clientmodel.LabelSet{ clientmodel.LabelName($1): clientmodel.LabelValue($3) } } |
|
; |
|
|
|
label_matches : /* empty */ |
|
{ $$ = metric.LabelMatchers{} } |
|
| '{' '}' |
|
{ $$ = metric.LabelMatchers{} } |
|
| '{' label_match_list '}' |
|
{ $$ = $2 } |
|
; |
|
|
|
label_match_list : label_match |
|
{ $$ = metric.LabelMatchers{$1} } |
|
| label_match_list ',' label_match |
|
{ $$ = append($$, $3) } |
|
; |
|
|
|
label_match : IDENTIFIER label_match_type STRING |
|
{ |
|
var err error |
|
$$, err = newLabelMatcher($2, clientmodel.LabelName($1), clientmodel.LabelValue($3)) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
; |
|
|
|
label_match_type : '=' |
|
{ $$ = "=" } |
|
| CMP_OP |
|
{ $$ = $1 } |
|
; |
|
|
|
rule_expr : '(' rule_expr ')' |
|
{ $$ = $2 } |
|
| '{' label_match_list '}' |
|
{ $$ = ast.NewVectorSelector($2) } |
|
| metric_name label_matches |
|
{ |
|
var err error |
|
m, err := metric.NewLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, clientmodel.LabelValue($1)) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
$2 = append($2, m) |
|
$$ = ast.NewVectorSelector($2) |
|
} |
|
| IDENTIFIER '(' func_arg_list ')' |
|
{ |
|
var err error |
|
$$, err = NewFunctionCall($1, $3) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| IDENTIFIER '(' ')' |
|
{ |
|
var err error |
|
$$, err = NewFunctionCall($1, []ast.Node{}) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| rule_expr '[' DURATION ']' |
|
{ |
|
var err error |
|
$$, err = NewMatrixSelector($1, $3) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| AGGR_OP '(' rule_expr ')' grouping_opts extra_labels_opts |
|
{ |
|
var err error |
|
$$, err = NewVectorAggregation($1, $3, $5, $6) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| AGGR_OP grouping_opts extra_labels_opts '(' rule_expr ')' |
|
{ |
|
var err error |
|
$$, err = NewVectorAggregation($1, $5, $2, $3) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
/* Yacc can only attach associativity to terminals, so we |
|
* have to list all operators here. */ |
|
| rule_expr ADDITIVE_OP rule_expr |
|
{ |
|
var err error |
|
$$, err = NewArithExpr($2, $1, $3) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| rule_expr MULT_OP rule_expr |
|
{ |
|
var err error |
|
$$, err = NewArithExpr($2, $1, $3) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| rule_expr CMP_OP rule_expr |
|
{ |
|
var err error |
|
$$, err = NewArithExpr($2, $1, $3) |
|
if err != nil { yylex.Error(err.Error()); return 1 } |
|
} |
|
| NUMBER |
|
{ $$ = ast.NewScalarLiteral($1)} |
|
; |
|
|
|
extra_labels_opts : |
|
{ $$ = false } |
|
| KEEPING_EXTRA |
|
{ $$ = true } |
|
; |
|
|
|
grouping_opts : |
|
{ $$ = clientmodel.LabelNames{} } |
|
| GROUP_OP '(' label_list ')' |
|
{ $$ = $3 } |
|
; |
|
|
|
label_list : IDENTIFIER |
|
{ $$ = clientmodel.LabelNames{clientmodel.LabelName($1)} } |
|
| label_list ',' IDENTIFIER |
|
{ $$ = append($$, clientmodel.LabelName($3)) } |
|
; |
|
|
|
func_arg_list : func_arg |
|
{ $$ = []ast.Node{$1} } |
|
| func_arg_list ',' func_arg |
|
{ $$ = append($$, $3) } |
|
; |
|
|
|
func_arg : rule_expr |
|
{ $$ = $1 } |
|
| STRING |
|
{ $$ = ast.NewStringLiteral($1) } |
|
; |
|
%%
|
|
|