mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-12 06:17:27 -08:00
Make rules/ast golint clean.
Mostly, that means adding compliant doc strings to exported items. Also, remove 'go vet' warnings where possible. (Some are unfortunately not to avoid, arguably bugs in 'go vet'.) Change-Id: I2827b6dd317492864c1383c3de1ea9eac5a219bb
This commit is contained in:
parent
5e8026779f
commit
fd63500ed3
231
rules/ast/ast.go
231
rules/ast/ast.go
|
@ -32,8 +32,12 @@ import (
|
|||
// ----------------------------------------------------------------------------
|
||||
// Raw data value types.
|
||||
|
||||
// Vector is basically only an alias for clientmodel.Samples, but the
|
||||
// contract is that in a Vector, all Samples have the same timestamp.
|
||||
type Vector clientmodel.Samples
|
||||
|
||||
// Matrix is a slice of SampleSets that implements sort.Interface and
|
||||
// has a String method.
|
||||
// BUG(julius): Pointerize this.
|
||||
type Matrix []metric.SampleSet
|
||||
|
||||
|
@ -46,9 +50,10 @@ type groupedAggregation struct {
|
|||
// ----------------------------------------------------------------------------
|
||||
// Enums.
|
||||
|
||||
// Rule language expression types.
|
||||
// ExprType is an enum for the rule language expression types.
|
||||
type ExprType int
|
||||
|
||||
// Possible language expression types.
|
||||
const (
|
||||
SCALAR ExprType = iota
|
||||
VECTOR
|
||||
|
@ -56,9 +61,10 @@ const (
|
|||
STRING
|
||||
)
|
||||
|
||||
// Binary operator types.
|
||||
// BinOpType is an enum for binary operator types.
|
||||
type BinOpType int
|
||||
|
||||
// Possible binary operator types.
|
||||
const (
|
||||
ADD BinOpType = iota
|
||||
SUB
|
||||
|
@ -75,9 +81,10 @@ const (
|
|||
OR
|
||||
)
|
||||
|
||||
// Aggregation types.
|
||||
// AggrType is an enum for aggregation types.
|
||||
type AggrType int
|
||||
|
||||
// Possible aggregation types.
|
||||
const (
|
||||
SUM AggrType = iota
|
||||
AVG
|
||||
|
@ -89,9 +96,13 @@ const (
|
|||
// ----------------------------------------------------------------------------
|
||||
// Interfaces.
|
||||
|
||||
// All node interfaces include the Node interface.
|
||||
// Nodes is a slice of any mix of node types as all node types
|
||||
// implement the Node interface.
|
||||
type Nodes []Node
|
||||
|
||||
// Node is the top-level interface for any kind of nodes. Each node
|
||||
// type implements one of the ...Node interfaces, each of which embeds
|
||||
// this Node interface.
|
||||
type Node interface {
|
||||
Type() ExprType
|
||||
Children() Nodes
|
||||
|
@ -99,26 +110,37 @@ type Node interface {
|
|||
String() string
|
||||
}
|
||||
|
||||
// All node types implement one of the following interfaces. The name of the
|
||||
// interface represents the type returned to the parent node.
|
||||
// ScalarNode is a Node for scalar values.
|
||||
type ScalarNode interface {
|
||||
Node
|
||||
// Eval evaluates and returns the value of the scalar represented by this node.
|
||||
Eval(timestamp clientmodel.Timestamp, view *viewAdapter) clientmodel.SampleValue
|
||||
}
|
||||
|
||||
// VectorNode is a Node for vector values.
|
||||
type VectorNode interface {
|
||||
Node
|
||||
// Eval evaluates the node recursively and returns the result
|
||||
// as a Vector (i.e. a slice of Samples all at the given
|
||||
// Timestamp).
|
||||
Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Vector
|
||||
}
|
||||
|
||||
// MatrixNode is a Node for matrix values.
|
||||
type MatrixNode interface {
|
||||
Node
|
||||
// Eval evaluates the node recursively and returns the result as a Matrix.
|
||||
Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Matrix
|
||||
// Eval evaluates the node recursively and returns the result
|
||||
// as a Matrix that only contains the boundary values.
|
||||
EvalBoundaries(timestamp clientmodel.Timestamp, view *viewAdapter) Matrix
|
||||
}
|
||||
|
||||
// StringNode is a Node for string values.
|
||||
type StringNode interface {
|
||||
Node
|
||||
// Eval evaluates and returns the value of the string
|
||||
// represented by this node.
|
||||
Eval(timestamp clientmodel.Timestamp, view *viewAdapter) string
|
||||
}
|
||||
|
||||
|
@ -126,18 +148,20 @@ type StringNode interface {
|
|||
// ScalarNode types.
|
||||
|
||||
type (
|
||||
// A numeric literal.
|
||||
// ScalarLiteral represents a numeric literal.
|
||||
ScalarLiteral struct {
|
||||
value clientmodel.SampleValue
|
||||
}
|
||||
|
||||
// A function of numeric return type.
|
||||
// ScalarFunctionCall represents a function with a numeric
|
||||
// return type.
|
||||
ScalarFunctionCall struct {
|
||||
function *Function
|
||||
args Nodes
|
||||
}
|
||||
|
||||
// An arithmetic expression of numeric type.
|
||||
// ScalarArithExpr represents an arithmetic expression of
|
||||
// numeric type.
|
||||
ScalarArithExpr struct {
|
||||
opType BinOpType
|
||||
lhs ScalarNode
|
||||
|
@ -149,20 +173,21 @@ type (
|
|||
// VectorNode types.
|
||||
|
||||
type (
|
||||
// Vector literal, i.e. metric name plus labelset.
|
||||
// A VectorLiteral represents a metric name plus labelset.
|
||||
VectorLiteral struct {
|
||||
labels clientmodel.LabelSet
|
||||
// Fingerprints are populated from labels at query analysis time.
|
||||
fingerprints clientmodel.Fingerprints
|
||||
}
|
||||
|
||||
// A function of vector return type.
|
||||
// VectorFunctionCall represents a function with vector return
|
||||
// type.
|
||||
VectorFunctionCall struct {
|
||||
function *Function
|
||||
args Nodes
|
||||
}
|
||||
|
||||
// A vector aggregation with vector return type.
|
||||
// A VectorAggregation with vector return type.
|
||||
VectorAggregation struct {
|
||||
aggrType AggrType
|
||||
groupBy clientmodel.LabelNames
|
||||
|
@ -170,7 +195,8 @@ type (
|
|||
vector VectorNode
|
||||
}
|
||||
|
||||
// An arithmetic expression of vector type.
|
||||
// VectorArithExpr represents an arithmetic expression of
|
||||
// vector type.
|
||||
VectorArithExpr struct {
|
||||
opType BinOpType
|
||||
lhs VectorNode
|
||||
|
@ -182,10 +208,12 @@ type (
|
|||
// MatrixNode types.
|
||||
|
||||
type (
|
||||
// Matrix literal, i.e. metric name plus labelset and timerange.
|
||||
// A MatrixLiteral represents a metric name plus labelset and
|
||||
// timerange.
|
||||
MatrixLiteral struct {
|
||||
labels clientmodel.LabelSet
|
||||
// Fingerprints are populated from labels at query analysis time.
|
||||
// Fingerprints are populated from labels at query
|
||||
// analysis time.
|
||||
fingerprints clientmodel.Fingerprints
|
||||
interval time.Duration
|
||||
}
|
||||
|
@ -195,12 +223,13 @@ type (
|
|||
// StringNode types.
|
||||
|
||||
type (
|
||||
// String literal.
|
||||
// A StringLiteral is what you think it is.
|
||||
StringLiteral struct {
|
||||
str string
|
||||
}
|
||||
|
||||
// A function of string return type.
|
||||
// StringFunctionCall represents a function with string return
|
||||
// type.
|
||||
StringFunctionCall struct {
|
||||
function *Function
|
||||
args Nodes
|
||||
|
@ -210,40 +239,88 @@ type (
|
|||
// ----------------------------------------------------------------------------
|
||||
// Implementations.
|
||||
|
||||
// Node.Type() methods.
|
||||
func (node ScalarLiteral) Type() ExprType { return SCALAR }
|
||||
// Type implements the Node interface.
|
||||
func (node ScalarLiteral) Type() ExprType { return SCALAR }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node ScalarFunctionCall) Type() ExprType { return SCALAR }
|
||||
func (node ScalarArithExpr) Type() ExprType { return SCALAR }
|
||||
func (node VectorLiteral) Type() ExprType { return VECTOR }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node ScalarArithExpr) Type() ExprType { return SCALAR }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node VectorLiteral) Type() ExprType { return VECTOR }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node VectorFunctionCall) Type() ExprType { return VECTOR }
|
||||
func (node VectorAggregation) Type() ExprType { return VECTOR }
|
||||
func (node VectorArithExpr) Type() ExprType { return VECTOR }
|
||||
func (node MatrixLiteral) Type() ExprType { return MATRIX }
|
||||
func (node StringLiteral) Type() ExprType { return STRING }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node VectorAggregation) Type() ExprType { return VECTOR }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node VectorArithExpr) Type() ExprType { return VECTOR }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node MatrixLiteral) Type() ExprType { return MATRIX }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node StringLiteral) Type() ExprType { return STRING }
|
||||
|
||||
// Type implements the Node interface.
|
||||
func (node StringFunctionCall) Type() ExprType { return STRING }
|
||||
|
||||
// Node.Children() methods.
|
||||
func (node ScalarLiteral) Children() Nodes { return Nodes{} }
|
||||
// Children implements the Node interface and returns an empty slice.
|
||||
func (node ScalarLiteral) Children() Nodes { return Nodes{} }
|
||||
|
||||
// Children implements the Node interface and returns the args of the
|
||||
// function call.
|
||||
func (node ScalarFunctionCall) Children() Nodes { return node.args }
|
||||
func (node ScalarArithExpr) Children() Nodes { return Nodes{node.lhs, node.rhs} }
|
||||
func (node VectorLiteral) Children() Nodes { return Nodes{} }
|
||||
|
||||
// Children implements the Node interface and returns the LHS and the RHS
|
||||
// of the expression.
|
||||
func (node ScalarArithExpr) Children() Nodes { return Nodes{node.lhs, node.rhs} }
|
||||
|
||||
// Children implements the Node interface and returns an empty slice.
|
||||
func (node VectorLiteral) Children() Nodes { return Nodes{} }
|
||||
|
||||
// Children implements the Node interface and returns the args of the
|
||||
// function call.
|
||||
func (node VectorFunctionCall) Children() Nodes { return node.args }
|
||||
func (node VectorAggregation) Children() Nodes { return Nodes{node.vector} }
|
||||
func (node VectorArithExpr) Children() Nodes { return Nodes{node.lhs, node.rhs} }
|
||||
func (node MatrixLiteral) Children() Nodes { return Nodes{} }
|
||||
func (node StringLiteral) Children() Nodes { return Nodes{} }
|
||||
|
||||
// Children implements the Node interface and returns the vector to be
|
||||
// aggregated.
|
||||
func (node VectorAggregation) Children() Nodes { return Nodes{node.vector} }
|
||||
|
||||
// Children implements the Node interface and returns the LHS and the RHS
|
||||
// of the expression.
|
||||
func (node VectorArithExpr) Children() Nodes { return Nodes{node.lhs, node.rhs} }
|
||||
|
||||
// Children implements the Node interface and returns an empty slice.
|
||||
func (node MatrixLiteral) Children() Nodes { return Nodes{} }
|
||||
|
||||
// Children implements the Node interface and returns an empty slice.
|
||||
func (node StringLiteral) Children() Nodes { return Nodes{} }
|
||||
|
||||
// Children implements the Node interface and returns the args of the
|
||||
// function call.
|
||||
func (node StringFunctionCall) Children() Nodes { return node.args }
|
||||
|
||||
// Eval implements the ScalarNode interface and returns the literal
|
||||
// value.
|
||||
func (node *ScalarLiteral) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) clientmodel.SampleValue {
|
||||
return node.value
|
||||
}
|
||||
|
||||
// Eval implements the ScalarNode interface and returns the result of
|
||||
// the expression.
|
||||
func (node *ScalarArithExpr) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) clientmodel.SampleValue {
|
||||
lhs := node.lhs.Eval(timestamp, view)
|
||||
rhs := node.rhs.Eval(timestamp, view)
|
||||
return evalScalarBinop(node.opType, lhs, rhs)
|
||||
}
|
||||
|
||||
// Eval implements the ScalarNode interface and returns the result of
|
||||
// the function call.
|
||||
func (node *ScalarFunctionCall) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) clientmodel.SampleValue {
|
||||
return node.function.callFn(timestamp, view, node.args).(clientmodel.SampleValue)
|
||||
}
|
||||
|
@ -278,6 +355,7 @@ func labelsToKey(labels clientmodel.Metric) uint64 {
|
|||
return summer.Sum64()
|
||||
}
|
||||
|
||||
// EvalVectorInstant evaluates a VectorNode with an instant query.
|
||||
func EvalVectorInstant(node VectorNode, timestamp clientmodel.Timestamp, storage *metric.TieredStorage, queryStats *stats.TimerGroup) (vector Vector, err error) {
|
||||
viewAdapter, err := viewAdapterForInstantQuery(node, timestamp, storage, queryStats)
|
||||
if err != nil {
|
||||
|
@ -287,6 +365,7 @@ func EvalVectorInstant(node VectorNode, timestamp clientmodel.Timestamp, storage
|
|||
return
|
||||
}
|
||||
|
||||
// EvalVectorRange evaluates a VectorNode with a range query.
|
||||
func EvalVectorRange(node VectorNode, start clientmodel.Timestamp, end clientmodel.Timestamp, interval time.Duration, storage *metric.TieredStorage, queryStats *stats.TimerGroup) (Matrix, error) {
|
||||
// Explicitly initialize to an empty matrix since a nil Matrix encodes to
|
||||
// null in JSON.
|
||||
|
@ -362,6 +441,8 @@ func (node *VectorAggregation) groupedAggregationsToVector(aggregations map[uint
|
|||
return vector
|
||||
}
|
||||
|
||||
// Eval implements the VectorNode interface and returns the aggregated
|
||||
// Vector.
|
||||
func (node *VectorAggregation) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Vector {
|
||||
vector := node.vector.Eval(timestamp, view)
|
||||
result := map[uint64]*groupedAggregation{}
|
||||
|
@ -414,6 +495,8 @@ func (node *VectorAggregation) Eval(timestamp clientmodel.Timestamp, view *viewA
|
|||
return node.groupedAggregationsToVector(result, timestamp)
|
||||
}
|
||||
|
||||
// Eval implements the VectorNode interface and returns the value of
|
||||
// the literal.
|
||||
func (node *VectorLiteral) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Vector {
|
||||
values, err := view.GetValueAtTime(node.fingerprints, timestamp)
|
||||
if err != nil {
|
||||
|
@ -423,6 +506,8 @@ func (node *VectorLiteral) Eval(timestamp clientmodel.Timestamp, view *viewAdapt
|
|||
return values
|
||||
}
|
||||
|
||||
// Eval implements the VectorNode interface and returns the result of
|
||||
// the function call.
|
||||
func (node *VectorFunctionCall) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Vector {
|
||||
return node.function.callFn(timestamp, view, node.args).(Vector)
|
||||
}
|
||||
|
@ -440,51 +525,43 @@ func evalScalarBinop(opType BinOpType,
|
|||
case DIV:
|
||||
if rhs != 0 {
|
||||
return lhs / rhs
|
||||
} else {
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs)))
|
||||
}
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs)))
|
||||
case MOD:
|
||||
if rhs != 0 {
|
||||
return clientmodel.SampleValue(int(lhs) % int(rhs))
|
||||
} else {
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs)))
|
||||
}
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs)))
|
||||
case EQ:
|
||||
if lhs == rhs {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
case NE:
|
||||
if lhs != rhs {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
case GT:
|
||||
if lhs > rhs {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
case LT:
|
||||
if lhs < rhs {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
case GE:
|
||||
if lhs >= rhs {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
case LE:
|
||||
if lhs <= rhs {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
panic("Not all enum values enumerated in switch")
|
||||
}
|
||||
|
@ -502,51 +579,43 @@ func evalVectorBinop(opType BinOpType,
|
|||
case DIV:
|
||||
if rhs != 0 {
|
||||
return lhs / rhs, true
|
||||
} else {
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs))), true
|
||||
}
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs))), true
|
||||
case MOD:
|
||||
if rhs != 0 {
|
||||
return clientmodel.SampleValue(int(lhs) % int(rhs)), true
|
||||
} else {
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs))), true
|
||||
}
|
||||
return clientmodel.SampleValue(math.Inf(int(rhs))), true
|
||||
case EQ:
|
||||
if lhs == rhs {
|
||||
return lhs, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
return 0, false
|
||||
case NE:
|
||||
if lhs != rhs {
|
||||
return lhs, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
return 0, false
|
||||
case GT:
|
||||
if lhs > rhs {
|
||||
return lhs, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
return 0, false
|
||||
case LT:
|
||||
if lhs < rhs {
|
||||
return lhs, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
return 0, false
|
||||
case GE:
|
||||
if lhs >= rhs {
|
||||
return lhs, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
return 0, false
|
||||
case LE:
|
||||
if lhs <= rhs {
|
||||
return lhs, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
return 0, false
|
||||
case AND:
|
||||
return lhs, true
|
||||
case OR:
|
||||
|
@ -567,6 +636,8 @@ func labelsEqual(labels1, labels2 clientmodel.Metric) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Eval implements the VectorNode interface and returns the result of
|
||||
// the expression.
|
||||
func (node *VectorArithExpr) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Vector {
|
||||
lhs := node.lhs.Eval(timestamp, view)
|
||||
result := Vector{}
|
||||
|
@ -598,6 +669,8 @@ func (node *VectorArithExpr) Eval(timestamp clientmodel.Timestamp, view *viewAda
|
|||
panic("Invalid vector arithmetic expression operands")
|
||||
}
|
||||
|
||||
// Eval implements the MatrixNode interface and returns the value of
|
||||
// the literal.
|
||||
func (node *MatrixLiteral) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Matrix {
|
||||
interval := &metric.Interval{
|
||||
OldestInclusive: timestamp.Add(-node.interval),
|
||||
|
@ -611,6 +684,8 @@ func (node *MatrixLiteral) Eval(timestamp clientmodel.Timestamp, view *viewAdapt
|
|||
return values
|
||||
}
|
||||
|
||||
// EvalBoundaries implements the MatrixNode interface and returns the
|
||||
// boundary values of the literal.
|
||||
func (node *MatrixLiteral) EvalBoundaries(timestamp clientmodel.Timestamp, view *viewAdapter) Matrix {
|
||||
interval := &metric.Interval{
|
||||
OldestInclusive: timestamp.Add(-node.interval),
|
||||
|
@ -624,22 +699,29 @@ func (node *MatrixLiteral) EvalBoundaries(timestamp clientmodel.Timestamp, view
|
|||
return values
|
||||
}
|
||||
|
||||
// Len implements sort.Interface.
|
||||
func (matrix Matrix) Len() int {
|
||||
return len(matrix)
|
||||
}
|
||||
|
||||
// Less implements sort.Interface.
|
||||
func (matrix Matrix) Less(i, j int) bool {
|
||||
return matrix[i].Metric.String() < matrix[j].Metric.String()
|
||||
}
|
||||
|
||||
// Swap implements sort.Interface.
|
||||
func (matrix Matrix) Swap(i, j int) {
|
||||
matrix[i], matrix[j] = matrix[j], matrix[i]
|
||||
}
|
||||
|
||||
// Eval implements the StringNode interface and returns the value of
|
||||
// the literal.
|
||||
func (node *StringLiteral) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) string {
|
||||
return node.str
|
||||
}
|
||||
|
||||
// Eval implements the StringNode interface and returns the result of
|
||||
// the function call.
|
||||
func (node *StringFunctionCall) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) string {
|
||||
return node.function.callFn(timestamp, view, node.args).(string)
|
||||
}
|
||||
|
@ -647,18 +729,24 @@ func (node *StringFunctionCall) Eval(timestamp clientmodel.Timestamp, view *view
|
|||
// ----------------------------------------------------------------------------
|
||||
// Constructors.
|
||||
|
||||
// NewScalarLiteral returns a ScalarLiteral with the given value.
|
||||
func NewScalarLiteral(value clientmodel.SampleValue) *ScalarLiteral {
|
||||
return &ScalarLiteral{
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// NewVectorLiteral returns a (not yet evaluated) VectorLiteral with
|
||||
// the given LabelSet.
|
||||
func NewVectorLiteral(labels clientmodel.LabelSet) *VectorLiteral {
|
||||
return &VectorLiteral{
|
||||
labels: labels,
|
||||
}
|
||||
}
|
||||
|
||||
// NewVectorAggregation returns a (not yet evaluated)
|
||||
// VectorAggregation, aggregating the given VectorNode using the given
|
||||
// AggrType, grouping by the given LabelNames.
|
||||
func NewVectorAggregation(aggrType AggrType, vector VectorNode, groupBy clientmodel.LabelNames, keepExtraLabels bool) *VectorAggregation {
|
||||
return &VectorAggregation{
|
||||
aggrType: aggrType,
|
||||
|
@ -668,6 +756,9 @@ func NewVectorAggregation(aggrType AggrType, vector VectorNode, groupBy clientmo
|
|||
}
|
||||
}
|
||||
|
||||
// NewFunctionCall returns a (not yet evaluated) function call node
|
||||
// (of type ScalarFunctionCall, VectorFunctionCall, or
|
||||
// StringFunctionCall).
|
||||
func NewFunctionCall(function *Function, args Nodes) (Node, error) {
|
||||
if err := function.CheckArgTypes(args); err != nil {
|
||||
return nil, err
|
||||
|
@ -707,12 +798,14 @@ func nodesHaveTypes(nodes Nodes, exprTypes []ExprType) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// NewArithExpr returns a (not yet evaluated) expression node (of type
|
||||
// VectorArithExpr or ScalarArithExpr).
|
||||
func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) {
|
||||
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 {
|
||||
return nil, errors.New("Left side of vector binary operation must be of vector type")
|
||||
return nil, errors.New("left side of vector binary operation must be of vector type")
|
||||
}
|
||||
|
||||
if opType == AND || opType == OR {
|
||||
|
@ -736,6 +829,8 @@ func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// NewMatrixLiteral returns a (not yet evaluated) MatrixLiteral with
|
||||
// the given VectorLiteral and Duration.
|
||||
func NewMatrixLiteral(vector *VectorLiteral, interval time.Duration) *MatrixLiteral {
|
||||
return &MatrixLiteral{
|
||||
labels: vector.labels,
|
||||
|
@ -743,6 +838,8 @@ func NewMatrixLiteral(vector *VectorLiteral, interval time.Duration) *MatrixLite
|
|||
}
|
||||
}
|
||||
|
||||
// NewStringLiteral returns a StringLiteral with the given string as
|
||||
// value.
|
||||
func NewStringLiteral(str string) *StringLiteral {
|
||||
return &StringLiteral{
|
||||
str: str,
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
@ -25,6 +24,8 @@ import (
|
|||
"github.com/prometheus/prometheus/utility"
|
||||
)
|
||||
|
||||
// Function represents a function of the expression language and is
|
||||
// used by function nodes.
|
||||
type Function struct {
|
||||
name string
|
||||
argTypes []ExprType
|
||||
|
@ -32,11 +33,14 @@ type Function struct {
|
|||
callFn func(timestamp clientmodel.Timestamp, view *viewAdapter, args []Node) interface{}
|
||||
}
|
||||
|
||||
// CheckArgTypes returns a non-nil error if the number or types of
|
||||
// passed in arg nodes do not match the function's expectations.
|
||||
func (function *Function) CheckArgTypes(args []Node) error {
|
||||
if len(function.argTypes) != len(args) {
|
||||
return errors.New(
|
||||
fmt.Sprintf("Wrong number of arguments to function %v(): %v expected, %v given",
|
||||
function.name, len(function.argTypes), len(args)))
|
||||
return fmt.Errorf(
|
||||
"wrong number of arguments to function %v(): %v expected, %v given",
|
||||
function.name, len(function.argTypes), len(args),
|
||||
)
|
||||
}
|
||||
for idx, argType := range function.argTypes {
|
||||
invalidType := false
|
||||
|
@ -59,9 +63,10 @@ func (function *Function) CheckArgTypes(args []Node) error {
|
|||
}
|
||||
|
||||
if invalidType {
|
||||
return errors.New(
|
||||
fmt.Sprintf("Wrong type for argument %v in function %v(), expected %v",
|
||||
idx, function.name, expectedType))
|
||||
return fmt.Errorf(
|
||||
"wrong type for argument %v in function %v(), expected %v",
|
||||
idx, function.name, expectedType,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -175,7 +180,7 @@ func sortImpl(timestamp clientmodel.Timestamp, view *viewAdapter, args []Node) i
|
|||
// === sortDesc(node *VectorNode) Vector ===
|
||||
func sortDescImpl(timestamp clientmodel.Timestamp, view *viewAdapter, args []Node) interface{} {
|
||||
descByValueSorter := utility.ReverseSorter{
|
||||
vectorByValueSorter{
|
||||
Interface: vectorByValueSorter{
|
||||
vector: args[0].(VectorNode).Eval(timestamp, view),
|
||||
},
|
||||
}
|
||||
|
@ -321,10 +326,12 @@ var functions = map[string]*Function{
|
|||
},
|
||||
}
|
||||
|
||||
// GetFunction returns a predefined Function object for the given
|
||||
// name.
|
||||
func GetFunction(name string) (*Function, error) {
|
||||
function, ok := functions[name]
|
||||
if !ok {
|
||||
return nil, errors.New(fmt.Sprintf("Couldn't find function %v()", name))
|
||||
return nil, fmt.Errorf("couldn't find function %v()", name)
|
||||
}
|
||||
return function, nil
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@ import (
|
|||
|
||||
var defaultStalenessDelta = flag.Int("defaultStalenessDelta", 300, "Default staleness delta allowance in seconds during expression evaluations.")
|
||||
|
||||
// Describes the lenience limits to apply to values from the materialized view.
|
||||
// StalenessPolicy describes the lenience limits to apply to values
|
||||
// from the materialized view.
|
||||
type StalenessPolicy struct {
|
||||
// Describes the inclusive limit at which individual points if requested will
|
||||
// be matched and subject to interpolation.
|
||||
|
@ -181,6 +182,8 @@ func (v *viewAdapter) GetRangeValues(fingerprints clientmodel.Fingerprints, inte
|
|||
return sampleSets, nil
|
||||
}
|
||||
|
||||
// NewViewAdapter returns an initialized view adapter with a default
|
||||
// staleness policy (based on the --defaultStalenessDelta flag).
|
||||
func NewViewAdapter(view metric.View, storage *metric.TieredStorage, queryStats *stats.TimerGroup) *viewAdapter {
|
||||
stalenessPolicy := StalenessPolicy{
|
||||
DeltaAllowance: time.Duration(*defaultStalenessDelta) * time.Second,
|
||||
|
|
|
@ -26,8 +26,10 @@ import (
|
|||
"github.com/prometheus/prometheus/utility"
|
||||
)
|
||||
|
||||
// OutputFormat is an enum for the possible output formats.
|
||||
type OutputFormat int
|
||||
|
||||
// Possible output formats.
|
||||
const (
|
||||
TEXT OutputFormat = iota
|
||||
JSON
|
||||
|
@ -113,6 +115,7 @@ func (matrix Matrix) String() string {
|
|||
return strings.Join(metricStrings, "\n")
|
||||
}
|
||||
|
||||
// ErrorToJSON converts the given error into JSON.
|
||||
func ErrorToJSON(err error) string {
|
||||
errorStruct := struct {
|
||||
Type string
|
||||
|
@ -129,6 +132,8 @@ func ErrorToJSON(err error) string {
|
|||
return string(errorJSON)
|
||||
}
|
||||
|
||||
// TypedValueToJSON converts the given data of type 'scalar',
|
||||
// 'vector', or 'matrix' into its JSON representation.
|
||||
func TypedValueToJSON(data interface{}, typeStr string) string {
|
||||
dataStruct := struct {
|
||||
Type string
|
||||
|
@ -144,6 +149,7 @@ func TypedValueToJSON(data interface{}, typeStr string) string {
|
|||
return string(dataJSON)
|
||||
}
|
||||
|
||||
// EvalToString evaluates the given node into a string of the given format.
|
||||
func EvalToString(node Node, timestamp clientmodel.Timestamp, format OutputFormat, storage *metric.TieredStorage, queryStats *stats.TimerGroup) string {
|
||||
viewTimer := queryStats.GetTimer(stats.TotalViewBuildingTime).Start()
|
||||
viewAdapter, err := viewAdapterForInstantQuery(node, timestamp, storage, queryStats)
|
||||
|
@ -194,6 +200,8 @@ func EvalToString(node Node, timestamp clientmodel.Timestamp, format OutputForma
|
|||
panic("Switch didn't cover all node types")
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the scalar
|
||||
// literal.
|
||||
func (node *ScalarLiteral) NodeTreeToDotGraph() string {
|
||||
return fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.value)
|
||||
}
|
||||
|
@ -209,12 +217,15 @@ func functionArgsToDotGraph(node Node, args []Node) string {
|
|||
return graph
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the function
|
||||
// call.
|
||||
func (node *ScalarFunctionCall) NodeTreeToDotGraph() string {
|
||||
graph := fmt.Sprintf("%#p[label=\"%s\"];\n", node, node.function.name)
|
||||
graph += functionArgsToDotGraph(node, node.args)
|
||||
return graph
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the expression.
|
||||
func (node *ScalarArithExpr) NodeTreeToDotGraph() string {
|
||||
graph := fmt.Sprintf(`
|
||||
%#p[label="%s"];
|
||||
|
@ -226,16 +237,21 @@ func (node *ScalarArithExpr) NodeTreeToDotGraph() string {
|
|||
return graph
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the vector literal.
|
||||
func (node *VectorLiteral) NodeTreeToDotGraph() string {
|
||||
return fmt.Sprintf("%#p[label=\"%s\"];\n", node, node)
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the function
|
||||
// call.
|
||||
func (node *VectorFunctionCall) NodeTreeToDotGraph() string {
|
||||
graph := fmt.Sprintf("%#p[label=\"%s\"];\n", node, node.function.name)
|
||||
graph += functionArgsToDotGraph(node, node.args)
|
||||
return graph
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the vector
|
||||
// aggregation.
|
||||
func (node *VectorAggregation) NodeTreeToDotGraph() string {
|
||||
groupByStrings := make([]string, 0, len(node.groupBy))
|
||||
for _, label := range node.groupBy {
|
||||
|
@ -251,6 +267,7 @@ func (node *VectorAggregation) NodeTreeToDotGraph() string {
|
|||
return graph
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the expression.
|
||||
func (node *VectorArithExpr) NodeTreeToDotGraph() string {
|
||||
graph := fmt.Sprintf(`
|
||||
%#p[label="%s"];
|
||||
|
@ -262,14 +279,20 @@ func (node *VectorArithExpr) NodeTreeToDotGraph() string {
|
|||
return graph
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the matrix
|
||||
// literal.
|
||||
func (node *MatrixLiteral) NodeTreeToDotGraph() string {
|
||||
return fmt.Sprintf("%#p[label=\"%s\"];\n", node, node)
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the string
|
||||
// literal.
|
||||
func (node *StringLiteral) NodeTreeToDotGraph() string {
|
||||
return fmt.Sprintf("%#p[label=\"'%q'\"];\n", node, node.str)
|
||||
}
|
||||
|
||||
// NodeTreeToDotGraph returns a DOT representation of the function
|
||||
// call.
|
||||
func (node *StringFunctionCall) NodeTreeToDotGraph() string {
|
||||
graph := fmt.Sprintf("%#p[label=\"%s\"];\n", node, node.function.name)
|
||||
graph += functionArgsToDotGraph(node, node.args)
|
||||
|
@ -325,9 +348,8 @@ func (node *VectorAggregation) String() string {
|
|||
aggrString := fmt.Sprintf("%s(%s)", node.aggrType, node.vector)
|
||||
if len(node.groupBy) > 0 {
|
||||
return fmt.Sprintf("%s BY (%s)", aggrString, node.groupBy)
|
||||
} else {
|
||||
return aggrString
|
||||
}
|
||||
return aggrString
|
||||
}
|
||||
|
||||
func (node *VectorArithExpr) String() string {
|
||||
|
|
|
@ -24,9 +24,16 @@ import (
|
|||
"github.com/prometheus/prometheus/storage/metric"
|
||||
)
|
||||
|
||||
// FullRangeMap maps the fingerprint of a full range to the duration
|
||||
// of the matrix literal it resulted from.
|
||||
type FullRangeMap map[clientmodel.Fingerprint]time.Duration
|
||||
|
||||
// IntervalRangeMap is a set of fingerprints of interval ranges.
|
||||
type IntervalRangeMap map[clientmodel.Fingerprint]bool
|
||||
|
||||
// A QueryAnalyzer recursively traverses the AST to look for any nodes
|
||||
// which will need data from the datastore. Instantiate with
|
||||
// NewQueryAnalyzer.
|
||||
type QueryAnalyzer struct {
|
||||
// Values collected by query analysis.
|
||||
//
|
||||
|
@ -37,13 +44,16 @@ type QueryAnalyzer struct {
|
|||
// This is because full ranges can only result from matrix literals (like
|
||||
// "foo[5m]"), which have said time-spanning behavior during a ranged query.
|
||||
FullRanges FullRangeMap
|
||||
// Interval ranges always implicitly span the whole query interval.
|
||||
// Interval ranges always implicitly span the whole query range.
|
||||
IntervalRanges IntervalRangeMap
|
||||
// The underlying storage to which the query will be applied. Needed for
|
||||
// extracting timeseries fingerprint information during query analysis.
|
||||
storage *metric.TieredStorage
|
||||
}
|
||||
|
||||
// NewQueryAnalyzer returns a pointer to a newly instantiated
|
||||
// QueryAnalyzer. The storage is needed to extract timeseries
|
||||
// fingerprint information during query analysis.
|
||||
func NewQueryAnalyzer(storage *metric.TieredStorage) *QueryAnalyzer {
|
||||
return &QueryAnalyzer{
|
||||
FullRanges: FullRangeMap{},
|
||||
|
@ -52,6 +62,7 @@ func NewQueryAnalyzer(storage *metric.TieredStorage) *QueryAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
// Visit implements the Visitor interface.
|
||||
func (analyzer *QueryAnalyzer) Visit(node Node) {
|
||||
switch n := node.(type) {
|
||||
case *VectorLiteral:
|
||||
|
@ -79,6 +90,8 @@ func (analyzer *QueryAnalyzer) Visit(node Node) {
|
|||
}
|
||||
}
|
||||
|
||||
// AnalyzeQueries walks the AST, starting at node, calling Visit on
|
||||
// each node to collect fingerprints.
|
||||
func (analyzer *QueryAnalyzer) AnalyzeQueries(node Node) {
|
||||
Walk(analyzer, node)
|
||||
// Find and dedupe overlaps between full and stepped ranges. Full ranges
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
|
||||
package ast
|
||||
|
||||
// Visitor is the interface for a Node visitor.
|
||||
type Visitor interface {
|
||||
Visit(node Node)
|
||||
}
|
||||
|
||||
// Walk() does a depth-first traversal of the AST, calling visitor.Visit() for
|
||||
// each encountered node in the tree.
|
||||
// Walk does a depth-first traversal of the AST, starting at node,
|
||||
// calling visitor.Visit for each encountered Node in the tree.
|
||||
func Walk(visitor Visitor, node Node) {
|
||||
visitor.Visit(node)
|
||||
for _, childNode := range node.Children() {
|
||||
|
|
Loading…
Reference in a new issue