mirror of
https://github.com/prometheus/prometheus.git
synced 2025-12-09 19:41:29 +01:00
WIP fill() operator
Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
61f64a4cb1
commit
fcd8db67c1
@ -2824,7 +2824,8 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
|||||||
if matching.Card == parser.CardManyToMany {
|
if matching.Card == parser.CardManyToMany {
|
||||||
panic("many-to-many only allowed for set operators")
|
panic("many-to-many only allowed for set operators")
|
||||||
}
|
}
|
||||||
if len(lhs) == 0 || len(rhs) == 0 {
|
if (len(lhs) == 0 && len(rhs) == 0) ||
|
||||||
|
((len(lhs) == 0 || len(rhs) == 0) && matching.FillValues.Rhs == nil && matching.FillValues.Lhs == nil) {
|
||||||
return nil, nil // Short-circuit: nothing is going to match.
|
return nil, nil // Short-circuit: nothing is going to match.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2872,17 +2873,9 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
|||||||
}
|
}
|
||||||
matchedSigs := enh.matchedSigs
|
matchedSigs := enh.matchedSigs
|
||||||
|
|
||||||
// For all lhs samples find a respective rhs sample and perform
|
|
||||||
// the binary operation.
|
|
||||||
var lastErr error
|
var lastErr error
|
||||||
for i, ls := range lhs {
|
|
||||||
sigOrd := lhsh[i].sigOrdinal
|
|
||||||
|
|
||||||
rs, found := rightSigs[sigOrd] // Look for a match in the rhs Vector.
|
|
||||||
if !found {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
|
doBinOp := func(ls Sample, rs Sample, sigOrd int) {
|
||||||
// Account for potentially swapped sidedness.
|
// Account for potentially swapped sidedness.
|
||||||
fl, fr := ls.F, rs.F
|
fl, fr := ls.F, rs.F
|
||||||
hl, hr := ls.H, rs.H
|
hl, hr := ls.H, rs.H
|
||||||
@ -2893,7 +2886,7 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
|||||||
floatValue, histogramValue, keep, info, err := vectorElemBinop(op, fl, fr, hl, hr, pos)
|
floatValue, histogramValue, keep, info, err := vectorElemBinop(op, fl, fr, hl, hr, pos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lastErr = err
|
lastErr = err
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
if info != nil {
|
if info != nil {
|
||||||
lastErr = info
|
lastErr = info
|
||||||
@ -2907,7 +2900,7 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
|||||||
floatValue = 0.0
|
floatValue = 0.0
|
||||||
}
|
}
|
||||||
case !keep:
|
case !keep:
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
metric := resultMetric(ls.Metric, rs.Metric, op, matching, enh)
|
metric := resultMetric(ls.Metric, rs.Metric, op, matching, enh)
|
||||||
if !ev.enableDelayedNameRemoval && returnBool {
|
if !ev.enableDelayedNameRemoval && returnBool {
|
||||||
@ -2941,6 +2934,44 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
|||||||
DropName: returnBool,
|
DropName: returnBool,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For all lhs samples find a respective rhs sample and perform
|
||||||
|
// the binary operation.
|
||||||
|
for i, ls := range lhs {
|
||||||
|
fmt.Println("processing lhs sample:", ls.Metric.String())
|
||||||
|
sigOrd := lhsh[i].sigOrdinal
|
||||||
|
|
||||||
|
rs, found := rightSigs[sigOrd] // Look for a match in the rhs Vector.
|
||||||
|
if !found {
|
||||||
|
if fill := matching.FillValues.Rhs; fill != nil {
|
||||||
|
fmt.Println("using fill rhs value")
|
||||||
|
rs = ls
|
||||||
|
// TODO: Handle histogram fallback values?
|
||||||
|
rs.F = *fill
|
||||||
|
} else {
|
||||||
|
fmt.Println("no match found, continuing")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doBinOp(ls, rs, sigOrd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For any rhs samples which have not been matched, check if we need to
|
||||||
|
// perform the operation with a fill value from the lhs.
|
||||||
|
if fill := matching.FillValues.Lhs; fill != nil {
|
||||||
|
for sigOrd, rs := range rightSigs {
|
||||||
|
if _, matched := matchedSigs[sigOrd]; matched {
|
||||||
|
continue // Already matched.
|
||||||
|
}
|
||||||
|
ls := rs
|
||||||
|
// TODO: Handle histogram fallback values?
|
||||||
|
ls.F = *fill
|
||||||
|
|
||||||
|
doBinOp(ls, rs, sigOrd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return enh.Out, lastErr
|
return enh.Out, lastErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -318,6 +318,19 @@ type VectorMatching struct {
|
|||||||
// Include contains additional labels that should be included in
|
// Include contains additional labels that should be included in
|
||||||
// the result from the side with the lower cardinality.
|
// the result from the side with the lower cardinality.
|
||||||
Include []string
|
Include []string
|
||||||
|
// Fill-in values to use when a series from one side does not find a match on the other side.
|
||||||
|
FillValues VectorMatchFillValues
|
||||||
|
}
|
||||||
|
|
||||||
|
// VectorMatchFillValues contains the fill values to use for Vector matching
|
||||||
|
// when one side does not find a match on the other side.
|
||||||
|
// When a fill value is nil, no fill is applied for that side, and there
|
||||||
|
// is no output for the match group if there is no match.
|
||||||
|
type VectorMatchFillValues struct {
|
||||||
|
// Rhs is the fill value to use for the right-hand side.
|
||||||
|
Rhs *float64
|
||||||
|
// Lhs is the fill value to use for the left-hand side.
|
||||||
|
Lhs *float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visitor allows visiting a Node and its child nodes. The Visit method is
|
// Visitor allows visiting a Node and its child nodes. The Visit method is
|
||||||
|
|||||||
@ -139,6 +139,9 @@ BOOL
|
|||||||
BY
|
BY
|
||||||
GROUP_LEFT
|
GROUP_LEFT
|
||||||
GROUP_RIGHT
|
GROUP_RIGHT
|
||||||
|
FILL
|
||||||
|
LFILL
|
||||||
|
RFILL
|
||||||
IGNORING
|
IGNORING
|
||||||
OFFSET
|
OFFSET
|
||||||
SMOOTHED
|
SMOOTHED
|
||||||
@ -189,7 +192,7 @@ START_METRIC_SELECTOR
|
|||||||
%type <int> int
|
%type <int> int
|
||||||
%type <uint> uint
|
%type <uint> uint
|
||||||
%type <float> number series_value signed_number signed_or_unsigned_number
|
%type <float> number series_value signed_number signed_or_unsigned_number
|
||||||
%type <node> step_invariant_expr aggregate_expr aggregate_modifier bin_modifier binary_expr bool_modifier expr function_call function_call_args function_call_body group_modifiers label_matchers matrix_selector number_duration_literal offset_expr anchored_expr smoothed_expr on_or_ignoring paren_expr string_literal subquery_expr unary_expr vector_selector duration_expr paren_duration_expr positive_duration_expr offset_duration_expr
|
%type <node> step_invariant_expr aggregate_expr aggregate_modifier bin_modifier fallback_modifiers binary_expr bool_modifier expr function_call function_call_args function_call_body group_modifiers label_matchers matrix_selector number_duration_literal offset_expr anchored_expr smoothed_expr on_or_ignoring paren_expr string_literal subquery_expr unary_expr vector_selector duration_expr paren_duration_expr positive_duration_expr offset_duration_expr
|
||||||
|
|
||||||
%start start
|
%start start
|
||||||
|
|
||||||
@ -301,7 +304,7 @@ binary_expr : expr ADD bin_modifier expr { $$ = yylex.(*parser).newBinar
|
|||||||
|
|
||||||
// Using left recursion for the modifier rules, helps to keep the parser stack small and
|
// Using left recursion for the modifier rules, helps to keep the parser stack small and
|
||||||
// reduces allocations.
|
// reduces allocations.
|
||||||
bin_modifier : group_modifiers;
|
bin_modifier : fallback_modifiers;
|
||||||
|
|
||||||
bool_modifier : /* empty */
|
bool_modifier : /* empty */
|
||||||
{ $$ = &BinaryExpr{
|
{ $$ = &BinaryExpr{
|
||||||
@ -345,6 +348,28 @@ group_modifiers: bool_modifier /* empty */
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
fallback_modifiers: group_modifiers /* empty */
|
||||||
|
| group_modifiers FILL LEFT_PAREN NUMBER RIGHT_PAREN
|
||||||
|
{
|
||||||
|
$$ = $1
|
||||||
|
fill := yylex.(*parser).number($4.Val)
|
||||||
|
$$.(*BinaryExpr).VectorMatching.FillValues.Lhs = &fill
|
||||||
|
$$.(*BinaryExpr).VectorMatching.FillValues.Rhs = &fill
|
||||||
|
}
|
||||||
|
| group_modifiers LFILL LEFT_PAREN NUMBER RIGHT_PAREN
|
||||||
|
{
|
||||||
|
$$ = $1
|
||||||
|
fill := yylex.(*parser).number($4.Val)
|
||||||
|
$$.(*BinaryExpr).VectorMatching.FillValues.Lhs = &fill
|
||||||
|
}
|
||||||
|
| group_modifiers RFILL LEFT_PAREN NUMBER RIGHT_PAREN
|
||||||
|
{
|
||||||
|
$$ = $1
|
||||||
|
fill := yylex.(*parser).number($4.Val)
|
||||||
|
$$.(*BinaryExpr).VectorMatching.FillValues.Rhs = &fill
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
grouping_labels : LEFT_PAREN grouping_label_list RIGHT_PAREN
|
grouping_labels : LEFT_PAREN grouping_label_list RIGHT_PAREN
|
||||||
{ $$ = $2 }
|
{ $$ = $2 }
|
||||||
@ -953,7 +978,7 @@ counter_reset_hint : UNKNOWN_COUNTER_RESET | COUNTER_RESET | NOT_COUNTER_RESET |
|
|||||||
aggregate_op : AVG | BOTTOMK | COUNT | COUNT_VALUES | GROUP | MAX | MIN | QUANTILE | STDDEV | STDVAR | SUM | TOPK | LIMITK | LIMIT_RATIO;
|
aggregate_op : AVG | BOTTOMK | COUNT | COUNT_VALUES | GROUP | MAX | MIN | QUANTILE | STDDEV | STDVAR | SUM | TOPK | LIMITK | LIMIT_RATIO;
|
||||||
|
|
||||||
// Inside of grouping options label names can be recognized as keywords by the lexer. This is a list of keywords that could also be a label name.
|
// Inside of grouping options label names can be recognized as keywords by the lexer. This is a list of keywords that could also be a label name.
|
||||||
maybe_label : AVG | BOOL | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | GROUP_LEFT | GROUP_RIGHT | IDENTIFIER | IGNORING | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | ON | QUANTILE | STDDEV | STDVAR | SUM | TOPK | START | END | ATAN2 | LIMITK | LIMIT_RATIO | STEP | ANCHORED | SMOOTHED;
|
maybe_label : AVG | BOOL | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | GROUP_LEFT | GROUP_RIGHT | FILL | LFILL | RFILL | IDENTIFIER | IGNORING | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | ON | QUANTILE | STDDEV | STDVAR | SUM | TOPK | START | END | ATAN2 | LIMITK | LIMIT_RATIO | STEP | ANCHORED | SMOOTHED;
|
||||||
|
|
||||||
unary_op : ADD | SUB;
|
unary_op : ADD | SUB;
|
||||||
|
|
||||||
@ -1141,7 +1166,7 @@ offset_duration_expr : number_duration_literal
|
|||||||
}
|
}
|
||||||
| duration_expr
|
| duration_expr
|
||||||
;
|
;
|
||||||
|
|
||||||
min_max: MIN | MAX ;
|
min_max: MIN | MAX ;
|
||||||
|
|
||||||
duration_expr : number_duration_literal
|
duration_expr : number_duration_literal
|
||||||
@ -1248,14 +1273,14 @@ duration_expr : number_duration_literal
|
|||||||
;
|
;
|
||||||
|
|
||||||
paren_duration_expr : LEFT_PAREN duration_expr RIGHT_PAREN
|
paren_duration_expr : LEFT_PAREN duration_expr RIGHT_PAREN
|
||||||
{
|
{
|
||||||
yylex.(*parser).experimentalDurationExpr($2.(Expr))
|
yylex.(*parser).experimentalDurationExpr($2.(Expr))
|
||||||
if durationExpr, ok := $2.(*DurationExpr); ok {
|
if durationExpr, ok := $2.(*DurationExpr); ok {
|
||||||
durationExpr.Wrapped = true
|
durationExpr.Wrapped = true
|
||||||
$$ = durationExpr
|
$$ = durationExpr
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
$$ = $2
|
$$ = $2
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -137,6 +137,9 @@ var key = map[string]ItemType{
|
|||||||
"ignoring": IGNORING,
|
"ignoring": IGNORING,
|
||||||
"group_left": GROUP_LEFT,
|
"group_left": GROUP_LEFT,
|
||||||
"group_right": GROUP_RIGHT,
|
"group_right": GROUP_RIGHT,
|
||||||
|
"fill": FILL,
|
||||||
|
"lfill": LFILL,
|
||||||
|
"rfill": RFILL,
|
||||||
"bool": BOOL,
|
"bool": BOOL,
|
||||||
|
|
||||||
// Preprocessors.
|
// Preprocessors.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user