Implement Stringer interface for rules and all their children.

This commit is contained in:
Julius Volz 2013-06-06 15:12:37 +02:00
parent 757ab938db
commit 74cb676537
11 changed files with 177 additions and 129 deletions

View file

@ -13,6 +13,10 @@
package model package model
import (
"strings"
)
const ( const (
// The label name indicating the metric name of a timeseries. // The label name indicating the metric name of a timeseries.
MetricNameLabel = LabelName("name") MetricNameLabel = LabelName("name")
@ -50,3 +54,11 @@ func (l LabelNames) Less(i, j int) bool {
func (l LabelNames) Swap(i, j int) { func (l LabelNames) Swap(i, j int) {
l[i], l[j] = l[j], l[i] l[i], l[j] = l[j], l[i]
} }
func (l LabelNames) String() string {
labelStrings := make([]string, 0, len(l))
for _, label := range l {
labelStrings = append(labelStrings, string(label))
}
return strings.Join(labelStrings, ", ")
}

View file

@ -19,6 +19,7 @@ import (
"fmt" "fmt"
dto "github.com/prometheus/prometheus/model/generated" dto "github.com/prometheus/prometheus/model/generated"
"sort" "sort"
"strings"
"time" "time"
) )
@ -50,36 +51,14 @@ func (l LabelSet) Merge(other LabelSet) LabelSet {
} }
func (l LabelSet) String() string { func (l LabelSet) String() string {
var ( labelStrings := make([]string, 0, len(l))
buffer bytes.Buffer for label, value := range l {
labels LabelNames labelStrings = append(labelStrings, fmt.Sprintf("%s='%s'", label, value))
labelCount int = len(l)
)
for name := range l {
labels = append(labels, name)
} }
sort.Sort(labels) sort.Strings(labelStrings)
fmt.Fprintf(&buffer, "{") return fmt.Sprintf("{%s}", strings.Join(labelStrings, ", "))
for i := 0; i < labelCount; i++ {
var (
label = labels[i]
value = l[label]
)
switch i {
case labelCount - 1:
fmt.Fprintf(&buffer, "%s=%s", label, value)
default:
fmt.Fprintf(&buffer, "%s=%s, ", label, value)
}
}
fmt.Fprintf(&buffer, "}")
return buffer.String()
} }
func (l LabelSet) ToMetric() Metric { func (l LabelSet) ToMetric() Metric {

View file

@ -147,6 +147,10 @@ func (rule AlertingRule) ToDotGraph() string {
return graph return graph
} }
func (rule AlertingRule) String() string {
return fmt.Sprintf("ALERT %s IF %s FOR %s WITH %s\n", rule.name, rule.vector, utility.DurationToString(rule.holdDuration), rule.labels)
}
// Construct a new AlertingRule. // Construct a new AlertingRule.
func NewAlertingRule(name string, vector ast.VectorNode, holdDuration time.Duration, labels model.LabelSet) *AlertingRule { func NewAlertingRule(name string, vector ast.VectorNode, holdDuration time.Duration, labels model.LabelSet) *AlertingRule {
return &AlertingRule{ return &AlertingRule{

View file

@ -85,10 +85,13 @@ const (
// Interfaces. // Interfaces.
// All node interfaces include the Node interface. // All node interfaces include the Node interface.
type Nodes []Node
type Node interface { type Node interface {
Type() ExprType Type() ExprType
Children() Nodes
NodeTreeToDotGraph() string NodeTreeToDotGraph() string
Children() []Node String() string
} }
// All node types implement one of the following interfaces. The name of the // All node types implement one of the following interfaces. The name of the
@ -126,7 +129,7 @@ type (
// A function of numeric return type. // A function of numeric return type.
ScalarFunctionCall struct { ScalarFunctionCall struct {
function *Function function *Function
args []Node args Nodes
} }
// An arithmetic expression of numeric type. // An arithmetic expression of numeric type.
@ -151,13 +154,13 @@ type (
// A function of vector return type. // A function of vector return type.
VectorFunctionCall struct { VectorFunctionCall struct {
function *Function function *Function
args []Node args Nodes
} }
// A vector aggregation with vector return type. // A vector aggregation with vector return type.
VectorAggregation struct { VectorAggregation struct {
aggrType AggrType aggrType AggrType
groupBy []model.LabelName groupBy model.LabelNames
vector VectorNode vector VectorNode
} }
@ -194,7 +197,7 @@ type (
// A function of string return type. // A function of string return type.
StringFunctionCall struct { StringFunctionCall struct {
function *Function function *Function
args []Node args Nodes
} }
) )
@ -214,16 +217,16 @@ func (node StringLiteral) Type() ExprType { return STRING }
func (node StringFunctionCall) Type() ExprType { return STRING } func (node StringFunctionCall) Type() ExprType { return STRING }
// Node.Children() methods. // Node.Children() methods.
func (node ScalarLiteral) Children() []Node { return []Node{} } func (node ScalarLiteral) Children() Nodes { return Nodes{} }
func (node ScalarFunctionCall) Children() []Node { return node.args } func (node ScalarFunctionCall) Children() Nodes { return node.args }
func (node ScalarArithExpr) Children() []Node { return []Node{node.lhs, node.rhs} } func (node ScalarArithExpr) Children() Nodes { return Nodes{node.lhs, node.rhs} }
func (node VectorLiteral) Children() []Node { return []Node{} } func (node VectorLiteral) Children() Nodes { return Nodes{} }
func (node VectorFunctionCall) Children() []Node { return node.args } func (node VectorFunctionCall) Children() Nodes { return node.args }
func (node VectorAggregation) Children() []Node { return []Node{node.vector} } func (node VectorAggregation) Children() Nodes { return Nodes{node.vector} }
func (node VectorArithExpr) Children() []Node { return []Node{node.lhs, node.rhs} } func (node VectorArithExpr) Children() Nodes { return Nodes{node.lhs, node.rhs} }
func (node MatrixLiteral) Children() []Node { return []Node{} } func (node MatrixLiteral) Children() Nodes { return Nodes{} }
func (node StringLiteral) Children() []Node { return []Node{} } func (node StringLiteral) Children() Nodes { return Nodes{} }
func (node StringFunctionCall) Children() []Node { return node.args } func (node StringFunctionCall) Children() Nodes { return node.args }
func (node *ScalarLiteral) Eval(timestamp time.Time, view *viewAdapter) model.SampleValue { func (node *ScalarLiteral) Eval(timestamp time.Time, view *viewAdapter) model.SampleValue {
return node.value return node.value
@ -622,7 +625,7 @@ func NewVectorLiteral(labels model.LabelSet) *VectorLiteral {
} }
} }
func NewVectorAggregation(aggrType AggrType, vector VectorNode, groupBy []model.LabelName) *VectorAggregation { func NewVectorAggregation(aggrType AggrType, vector VectorNode, groupBy model.LabelNames) *VectorAggregation {
return &VectorAggregation{ return &VectorAggregation{
aggrType: aggrType, aggrType: aggrType,
groupBy: groupBy, groupBy: groupBy,
@ -630,7 +633,7 @@ func NewVectorAggregation(aggrType AggrType, vector VectorNode, groupBy []model.
} }
} }
func NewFunctionCall(function *Function, args []Node) (Node, error) { func NewFunctionCall(function *Function, args Nodes) (Node, error) {
if err := function.CheckArgTypes(args); err != nil { if err := function.CheckArgTypes(args); err != nil {
return nil, err return nil, err
} }
@ -654,7 +657,7 @@ func NewFunctionCall(function *Function, args []Node) (Node, error) {
panic("Function with invalid return type") panic("Function with invalid return type")
} }
func nodesHaveTypes(nodes []Node, exprTypes []ExprType) bool { func nodesHaveTypes(nodes Nodes, exprTypes []ExprType) bool {
for _, node := range nodes { for _, node := range nodes {
correctType := false correctType := false
for _, exprType := range exprTypes { for _, exprType := range exprTypes {
@ -670,7 +673,7 @@ func nodesHaveTypes(nodes []Node, exprTypes []ExprType) bool {
} }
func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) { func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) {
if !nodesHaveTypes([]Node{lhs, rhs}, []ExprType{SCALAR, VECTOR}) { if !nodesHaveTypes(Nodes{lhs, rhs}, []ExprType{SCALAR, VECTOR}) {
return nil, errors.New("Binary operands must be of vector or scalar type") return nil, errors.New("Binary operands must be of vector or scalar type")
} }
if lhs.Type() == SCALAR && rhs.Type() == VECTOR { if lhs.Type() == SCALAR && rhs.Type() == VECTOR {

View file

@ -23,7 +23,8 @@ type emptyRangeNode struct{}
func (node emptyRangeNode) Type() ExprType { return MATRIX } func (node emptyRangeNode) Type() ExprType { return MATRIX }
func (node emptyRangeNode) NodeTreeToDotGraph() string { return "" } func (node emptyRangeNode) NodeTreeToDotGraph() string { return "" }
func (node emptyRangeNode) Children() []Node { return []Node{} } func (node emptyRangeNode) String() string { return "" }
func (node emptyRangeNode) Children() Nodes { return Nodes{} }
func (node emptyRangeNode) Eval(timestamp time.Time, view *viewAdapter) Matrix { func (node emptyRangeNode) Eval(timestamp time.Time, view *viewAdapter) Matrix {
return Matrix{ return Matrix{

View file

@ -45,6 +45,8 @@ func (opType BinOpType) String() string {
NE: "!=", NE: "!=",
GE: ">=", GE: ">=",
LE: "<=", LE: "<=",
AND: "AND",
OR: "OR",
} }
return opTypeMap[opType] return opTypeMap[opType]
} }
@ -71,13 +73,13 @@ func (exprType ExprType) String() string {
} }
func (vector Vector) String() string { func (vector Vector) String() string {
metricStrings := []string{} metricStrings := make([]string, 0, len(vector))
for _, sample := range vector { for _, sample := range vector {
metricName, ok := sample.Metric[model.MetricNameLabel] metricName, ok := sample.Metric[model.MetricNameLabel]
if !ok { if !ok {
panic("Tried to print vector without metric name") panic("Tried to print vector without metric name")
} }
labelStrings := []string{} labelStrings := make([]string, 0, len(sample.Metric)-1)
for label, value := range sample.Metric { for label, value := range sample.Metric {
if label != model.MetricNameLabel { if label != model.MetricNameLabel {
// TODO escape special chars in label values here and elsewhere. // TODO escape special chars in label values here and elsewhere.
@ -95,20 +97,20 @@ func (vector Vector) String() string {
} }
func (matrix Matrix) String() string { func (matrix Matrix) String() string {
metricStrings := []string{} metricStrings := make([]string, 0, len(matrix))
for _, sampleSet := range matrix { for _, sampleSet := range matrix {
metricName, ok := sampleSet.Metric[model.MetricNameLabel] metricName, ok := sampleSet.Metric[model.MetricNameLabel]
if !ok { if !ok {
panic("Tried to print matrix without metric name") panic("Tried to print matrix without metric name")
} }
labelStrings := []string{} labelStrings := make([]string, 0, len(sampleSet.Metric)-1)
for label, value := range sampleSet.Metric { for label, value := range sampleSet.Metric {
if label != model.MetricNameLabel { if label != model.MetricNameLabel {
labelStrings = append(labelStrings, fmt.Sprintf("%s='%s'", label, value)) labelStrings = append(labelStrings, fmt.Sprintf("%s='%s'", label, value))
} }
} }
sort.Strings(labelStrings) sort.Strings(labelStrings)
valueStrings := []string{} valueStrings := make([]string, 0, len(sampleSet.Values))
for _, value := range sampleSet.Values { for _, value := range sampleSet.Values {
valueStrings = append(valueStrings, valueStrings = append(valueStrings,
fmt.Sprintf("\n%v @[%v]", value.Value, value.Timestamp)) fmt.Sprintf("\n%v @[%v]", value.Value, value.Timestamp))
@ -204,27 +206,6 @@ func EvalToString(node Node, timestamp time.Time, format OutputFormat, storage *
panic("Switch didn't cover all node types") panic("Switch didn't cover all node types")
} }
func (node *VectorLiteral) String() string {
metricName, ok := node.labels[model.MetricNameLabel]
if !ok {
panic("Tried to print vector without metric name")
}
labelStrings := []string{}
for label, value := range node.labels {
if label != model.MetricNameLabel {
labelStrings = append(labelStrings, fmt.Sprintf("%s='%s'", label, value))
}
}
sort.Strings(labelStrings)
return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ","))
}
func (node *MatrixLiteral) String() string {
vectorString := (&VectorLiteral{labels: node.labels}).String()
intervalString := fmt.Sprintf("['%s']", utility.DurationToString(node.interval))
return vectorString + intervalString
}
func (node *ScalarLiteral) NodeTreeToDotGraph() string { func (node *ScalarLiteral) NodeTreeToDotGraph() string {
return fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.value) return fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.value)
} }
@ -268,7 +249,7 @@ func (node *VectorFunctionCall) NodeTreeToDotGraph() string {
} }
func (node *VectorAggregation) NodeTreeToDotGraph() string { func (node *VectorAggregation) NodeTreeToDotGraph() string {
groupByStrings := []string{} groupByStrings := make([]string, 0, len(node.groupBy))
for _, label := range node.groupBy { for _, label := range node.groupBy {
groupByStrings = append(groupByStrings, string(label)) groupByStrings = append(groupByStrings, string(label))
} }
@ -306,3 +287,64 @@ func (node *StringFunctionCall) NodeTreeToDotGraph() string {
graph += functionArgsToDotGraph(node, node.args) graph += functionArgsToDotGraph(node, node.args)
return graph return graph
} }
func (nodes Nodes) String() string {
nodeStrings := make([]string, 0, len(nodes))
for _, node := range nodes {
nodeStrings = append(nodeStrings, node.String())
}
return strings.Join(nodeStrings, ", ")
}
func (node *ScalarLiteral) String() string {
return fmt.Sprint(node.value)
}
func (node *ScalarFunctionCall) String() string {
return fmt.Sprintf("%s(%s)", node.function.name, node.args)
}
func (node *ScalarArithExpr) String() string {
return fmt.Sprintf("(%s %s %s)", node.lhs, node.opType, node.rhs)
}
func (node *VectorLiteral) String() string {
metricName, ok := node.labels[model.MetricNameLabel]
if !ok {
panic("Tried to print vector without metric name")
}
labelStrings := make([]string, 0, len(node.labels)-1)
for label, value := range node.labels {
if label != model.MetricNameLabel {
labelStrings = append(labelStrings, fmt.Sprintf("%s='%s'", label, value))
}
}
sort.Strings(labelStrings)
return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ","))
}
func (node *VectorFunctionCall) String() string {
return fmt.Sprintf("%s(%s)", node.function.name, node.args)
}
func (node *VectorAggregation) String() string {
return fmt.Sprintf("%s(%s) BY (%s)", node.aggrType, node.vector, node.groupBy)
}
func (node *VectorArithExpr) String() string {
return fmt.Sprintf("(%s %s %s)", node.lhs, node.opType, node.rhs)
}
func (node *MatrixLiteral) String() string {
vectorString := (&VectorLiteral{labels: node.labels}).String()
intervalString := fmt.Sprintf("[%s]", utility.DurationToString(node.interval))
return vectorString + intervalString
}
func (node *StringLiteral) String() string {
return fmt.Sprintf("'%s'", node.str)
}
func (node *StringFunctionCall) String() string {
return fmt.Sprintf("%s(%s)", node.function.name, node.args)
}

View file

@ -50,7 +50,7 @@ func NewFunctionCall(name string, args []ast.Node) (ast.Node, error) {
return functionCall, nil return functionCall, nil
} }
func NewVectorAggregation(aggrTypeStr string, vector ast.Node, groupBy []model.LabelName) (*ast.VectorAggregation, error) { func NewVectorAggregation(aggrTypeStr string, vector ast.Node, groupBy model.LabelNames) (*ast.VectorAggregation, error) {
if _, ok := vector.(ast.VectorNode); !ok { if _, ok := vector.(ast.VectorNode); !ok {
return nil, fmt.Errorf("Operand of %v aggregation must be of vector type", aggrTypeStr) return nil, fmt.Errorf("Operand of %v aggregation must be of vector type", aggrTypeStr)
} }

View file

@ -14,7 +14,6 @@
%{ %{
package rules package rules
import "fmt"
import "github.com/prometheus/prometheus/model" import "github.com/prometheus/prometheus/model"
import "github.com/prometheus/prometheus/rules/ast" import "github.com/prometheus/prometheus/rules/ast"
%} %}
@ -25,7 +24,7 @@
ruleNode ast.Node ruleNode ast.Node
ruleNodeSlice []ast.Node ruleNodeSlice []ast.Node
boolean bool boolean bool
labelNameSlice []model.LabelName labelNameSlice model.LabelNames
labelSet model.LabelSet labelSet model.LabelSet
} }
@ -164,13 +163,13 @@ rule_expr : '(' rule_expr ')'
; ;
grouping_opts : grouping_opts :
{ $$ = []model.LabelName{} } { $$ = model.LabelNames{} }
| GROUP_OP '(' label_list ')' | GROUP_OP '(' label_list ')'
{ $$ = $3 } { $$ = $3 }
; ;
label_list : IDENTIFIER label_list : IDENTIFIER
{ $$ = []model.LabelName{model.LabelName($1)} } { $$ = model.LabelNames{model.LabelName($1)} }
| label_list ',' IDENTIFIER | label_list ',' IDENTIFIER
{ $$ = append($$, model.LabelName($3)) } { $$ = append($$, model.LabelName($3)) }
; ;

View file

@ -1,12 +1,13 @@
//line parser.y:15 //line parser.y:15
package rules package rules
import __yyfmt__ "fmt"
import "fmt" //line parser.y:15
import "github.com/prometheus/prometheus/model" import "github.com/prometheus/prometheus/model"
import "github.com/prometheus/prometheus/rules/ast" import "github.com/prometheus/prometheus/rules/ast"
//line parser.y:22 //line parser.y:21
type yySymType struct { type yySymType struct {
yys int yys int
num model.SampleValue num model.SampleValue
@ -14,7 +15,7 @@ type yySymType struct {
ruleNode ast.Node ruleNode ast.Node
ruleNodeSlice []ast.Node ruleNodeSlice []ast.Node
boolean bool boolean bool
labelNameSlice []model.LabelName labelNameSlice model.LabelNames
labelSet model.LabelSet labelSet model.LabelSet
} }
@ -60,7 +61,7 @@ const yyEofCode = 1
const yyErrCode = 2 const yyErrCode = 2
const yyMaxDepth = 200 const yyMaxDepth = 200
//line parser.y:189 //line parser.y:188
//line yacctab:1 //line yacctab:1
@ -182,12 +183,13 @@ type yyLexer interface {
const yyFlag = -1000 const yyFlag = -1000
func yyTokname(c int) string { func yyTokname(c int) string {
if c > 0 && c <= len(yyToknames) { // 4 is TOKSTART above
if yyToknames[c-1] != "" { if c >= 4 && c-4 < len(yyToknames) {
return yyToknames[c-1] if yyToknames[c-4] != "" {
return yyToknames[c-4]
} }
} }
return fmt.Sprintf("tok-%v", c) return __yyfmt__.Sprintf("tok-%v", c)
} }
func yyStatname(s int) string { func yyStatname(s int) string {
@ -196,7 +198,7 @@ func yyStatname(s int) string {
return yyStatenames[s] return yyStatenames[s]
} }
} }
return fmt.Sprintf("state-%v", s) return __yyfmt__.Sprintf("state-%v", s)
} }
func yylex1(lex yyLexer, lval *yySymType) int { func yylex1(lex yyLexer, lval *yySymType) int {
@ -229,7 +231,7 @@ out:
c = yyTok2[1] /* unknown char */ c = yyTok2[1] /* unknown char */
} }
if yyDebug >= 3 { if yyDebug >= 3 {
fmt.Printf("lex %U %s\n", uint(char), yyTokname(c)) __yyfmt__.Printf("lex %U %s\n", uint(char), yyTokname(c))
} }
return c return c
} }
@ -256,7 +258,7 @@ ret1:
yystack: yystack:
/* put a state and value onto the stack */ /* put a state and value onto the stack */
if yyDebug >= 4 { if yyDebug >= 4 {
fmt.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate)) __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
} }
yyp++ yyp++
@ -325,8 +327,8 @@ yydefault:
yylex.Error("syntax error") yylex.Error("syntax error")
Nerrs++ Nerrs++
if yyDebug >= 1 { if yyDebug >= 1 {
fmt.Printf("%s", yyStatname(yystate)) __yyfmt__.Printf("%s", yyStatname(yystate))
fmt.Printf("saw %s\n", yyTokname(yychar)) __yyfmt__.Printf("saw %s\n", yyTokname(yychar))
} }
fallthrough fallthrough
@ -345,7 +347,7 @@ yydefault:
/* the current p has no shift on "error", pop stack */ /* the current p has no shift on "error", pop stack */
if yyDebug >= 2 { if yyDebug >= 2 {
fmt.Printf("error recovery pops state %d\n", yyS[yyp].yys) __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
} }
yyp-- yyp--
} }
@ -354,7 +356,7 @@ yydefault:
case 3: /* no shift yet; clobber input char */ case 3: /* no shift yet; clobber input char */
if yyDebug >= 2 { if yyDebug >= 2 {
fmt.Printf("error recovery discards %s\n", yyTokname(yychar)) __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
} }
if yychar == yyEofCode { if yychar == yyEofCode {
goto ret1 goto ret1
@ -366,7 +368,7 @@ yydefault:
/* reduction by production yyn */ /* reduction by production yyn */
if yyDebug >= 2 { if yyDebug >= 2 {
fmt.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
} }
yynt := yyn yynt := yyn
@ -393,133 +395,133 @@ yydefault:
switch yynt { switch yynt {
case 5: case 5:
//line parser.y:67 //line parser.y:66
{ yylex.(*RulesLexer).parsedExpr = yyS[yypt-0].ruleNode } { yylex.(*RulesLexer).parsedExpr = yyS[yypt-0].ruleNode }
case 6: case 6:
//line parser.y:71 //line parser.y:70
{ {
rule, err := CreateRecordingRule(yyS[yypt-3].str, yyS[yypt-2].labelSet, yyS[yypt-0].ruleNode, yyS[yypt-4].boolean) rule, err := CreateRecordingRule(yyS[yypt-3].str, yyS[yypt-2].labelSet, yyS[yypt-0].ruleNode, yyS[yypt-4].boolean)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule)
} }
case 7: case 7:
//line parser.y:77 //line parser.y:76
{ {
rule, err := CreateAlertingRule(yyS[yypt-5].str, yyS[yypt-3].ruleNode, yyS[yypt-2].str, yyS[yypt-0].labelSet) rule, err := CreateAlertingRule(yyS[yypt-5].str, yyS[yypt-3].ruleNode, yyS[yypt-2].str, yyS[yypt-0].labelSet)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule)
} }
case 8: case 8:
//line parser.y:85 //line parser.y:84
{ yyVAL.str = "0s" } { yyVAL.str = "0s" }
case 9: case 9:
//line parser.y:87 //line parser.y:86
{ yyVAL.str = yyS[yypt-0].str } { yyVAL.str = yyS[yypt-0].str }
case 10: case 10:
//line parser.y:91 //line parser.y:90
{ yyVAL.boolean = false } { yyVAL.boolean = false }
case 11: case 11:
//line parser.y:93 //line parser.y:92
{ yyVAL.boolean = true } { yyVAL.boolean = true }
case 12: case 12:
//line parser.y:97 //line parser.y:96
{ yyVAL.labelSet = model.LabelSet{} } { yyVAL.labelSet = model.LabelSet{} }
case 13: case 13:
//line parser.y:99 //line parser.y:98
{ yyVAL.labelSet = yyS[yypt-1].labelSet } { yyVAL.labelSet = yyS[yypt-1].labelSet }
case 14: case 14:
//line parser.y:101 //line parser.y:100
{ yyVAL.labelSet = model.LabelSet{} } { yyVAL.labelSet = model.LabelSet{} }
case 15: case 15:
//line parser.y:104 //line parser.y:103
{ yyVAL.labelSet = yyS[yypt-0].labelSet } { yyVAL.labelSet = yyS[yypt-0].labelSet }
case 16: case 16:
//line parser.y:106 //line parser.y:105
{ for k, v := range yyS[yypt-0].labelSet { yyVAL.labelSet[k] = v } } { for k, v := range yyS[yypt-0].labelSet { yyVAL.labelSet[k] = v } }
case 17: case 17:
//line parser.y:110 //line parser.y:109
{ yyVAL.labelSet = model.LabelSet{ model.LabelName(yyS[yypt-2].str): model.LabelValue(yyS[yypt-0].str) } } { yyVAL.labelSet = model.LabelSet{ model.LabelName(yyS[yypt-2].str): model.LabelValue(yyS[yypt-0].str) } }
case 18: case 18:
//line parser.y:115 //line parser.y:114
{ yyVAL.ruleNode = yyS[yypt-1].ruleNode } { yyVAL.ruleNode = yyS[yypt-1].ruleNode }
case 19: case 19:
//line parser.y:117 //line parser.y:116
{ yyS[yypt-0].labelSet[model.MetricNameLabel] = model.LabelValue(yyS[yypt-1].str); yyVAL.ruleNode = ast.NewVectorLiteral(yyS[yypt-0].labelSet) } { yyS[yypt-0].labelSet[model.MetricNameLabel] = model.LabelValue(yyS[yypt-1].str); yyVAL.ruleNode = ast.NewVectorLiteral(yyS[yypt-0].labelSet) }
case 20: case 20:
//line parser.y:119 //line parser.y:118
{ {
var err error var err error
yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-3].str, yyS[yypt-1].ruleNodeSlice) yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-3].str, yyS[yypt-1].ruleNodeSlice)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 21: case 21:
//line parser.y:125 //line parser.y:124
{ {
var err error var err error
yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-2].str, []ast.Node{}) yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-2].str, []ast.Node{})
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 22: case 22:
//line parser.y:131 //line parser.y:130
{ {
var err error var err error
yyVAL.ruleNode, err = NewMatrix(yyS[yypt-3].ruleNode, yyS[yypt-1].str) yyVAL.ruleNode, err = NewMatrix(yyS[yypt-3].ruleNode, yyS[yypt-1].str)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 23: case 23:
//line parser.y:137 //line parser.y:136
{ {
var err error var err error
yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-4].str, yyS[yypt-2].ruleNode, yyS[yypt-0].labelNameSlice) yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-4].str, yyS[yypt-2].ruleNode, yyS[yypt-0].labelNameSlice)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 24: case 24:
//line parser.y:145 //line parser.y:144
{ {
var err error var err error
yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 25: case 25:
//line parser.y:151 //line parser.y:150
{ {
var err error var err error
yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 26: case 26:
//line parser.y:157 //line parser.y:156
{ {
var err error var err error
yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode)
if err != nil { yylex.Error(err.Error()); return 1 } if err != nil { yylex.Error(err.Error()); return 1 }
} }
case 27: case 27:
//line parser.y:163 //line parser.y:162
{ yyVAL.ruleNode = ast.NewScalarLiteral(yyS[yypt-0].num)} { yyVAL.ruleNode = ast.NewScalarLiteral(yyS[yypt-0].num)}
case 28: case 28:
//line parser.y:167 //line parser.y:166
{ yyVAL.labelNameSlice = []model.LabelName{} } { yyVAL.labelNameSlice = model.LabelNames{} }
case 29: case 29:
//line parser.y:169 //line parser.y:168
{ yyVAL.labelNameSlice = yyS[yypt-1].labelNameSlice } { yyVAL.labelNameSlice = yyS[yypt-1].labelNameSlice }
case 30: case 30:
//line parser.y:173 //line parser.y:172
{ yyVAL.labelNameSlice = []model.LabelName{model.LabelName(yyS[yypt-0].str)} } { yyVAL.labelNameSlice = model.LabelNames{model.LabelName(yyS[yypt-0].str)} }
case 31: case 31:
//line parser.y:175 //line parser.y:174
{ yyVAL.labelNameSlice = append(yyVAL.labelNameSlice, model.LabelName(yyS[yypt-0].str)) } { yyVAL.labelNameSlice = append(yyVAL.labelNameSlice, model.LabelName(yyS[yypt-0].str)) }
case 32: case 32:
//line parser.y:179 //line parser.y:178
{ yyVAL.ruleNodeSlice = []ast.Node{yyS[yypt-0].ruleNode} } { yyVAL.ruleNodeSlice = []ast.Node{yyS[yypt-0].ruleNode} }
case 33: case 33:
//line parser.y:181 //line parser.y:180
{ yyVAL.ruleNodeSlice = append(yyVAL.ruleNodeSlice, yyS[yypt-0].ruleNode) } { yyVAL.ruleNodeSlice = append(yyVAL.ruleNodeSlice, yyS[yypt-0].ruleNode) }
case 34: case 34:
//line parser.y:185 //line parser.y:184
{ yyVAL.ruleNode = yyS[yypt-0].ruleNode } { yyVAL.ruleNode = yyS[yypt-0].ruleNode }
case 35: case 35:
//line parser.y:187 //line parser.y:186
{ yyVAL.ruleNode = ast.NewStringLiteral(yyS[yypt-0].str) } { yyVAL.ruleNode = ast.NewStringLiteral(yyS[yypt-0].str) }
} }
goto yystack /* stack new state and value */ goto yystack /* stack new state and value */

View file

@ -67,6 +67,10 @@ func (rule RecordingRule) ToDotGraph() string {
return graph return graph
} }
func (rule RecordingRule) String() string {
return fmt.Sprintf("%s%s = %s\n", rule.name, rule.labels, rule.vector)
}
// Construct a new RecordingRule. // Construct a new RecordingRule.
func NewRecordingRule(name string, labels model.LabelSet, vector ast.VectorNode, permanent bool) *RecordingRule { func NewRecordingRule(name string, labels model.LabelSet, vector ast.VectorNode, permanent bool) *RecordingRule {
return &RecordingRule{ return &RecordingRule{

View file

@ -31,4 +31,6 @@ type Rule interface {
Eval(timestamp time.Time, storage *metric.TieredStorage) (ast.Vector, error) Eval(timestamp time.Time, storage *metric.TieredStorage) (ast.Vector, error)
// ToDotGraph returns a Graphviz dot graph of the rule. // ToDotGraph returns a Graphviz dot graph of the rule.
ToDotGraph() string ToDotGraph() string
// String returns a human-readable string representation of the rule.
String() string
} }