Merge pull request #1765 from prometheus/on-dummy

Support on()
pull/1767/head
Brian Brazil 2016-06-24 14:15:23 +01:00 committed by GitHub
commit ba9fbb9ea2
7 changed files with 119 additions and 34 deletions

View File

@ -231,9 +231,9 @@ type VectorMatching struct {
// MatchingLabels contains the labels which define equality of a pair of
// elements from the vectors.
MatchingLabels model.LabelNames
// Ignoring excludes the given label names from matching,
// rather than only using them.
Ignoring bool
// On includes the given label names from matching,
// rather than excluding them.
On bool
// Include contains additional labels that should be included in
// the result from the side with the lower cardinality.
Include model.LabelNames

View File

@ -728,7 +728,7 @@ func (ev *evaluator) vectorAnd(lhs, rhs vector, matching *VectorMatching) vector
if matching.Card != CardManyToMany {
panic("set operations must only use many-to-many matching")
}
sigf := signatureFunc(matching.Ignoring, matching.MatchingLabels...)
sigf := signatureFunc(matching.On, matching.MatchingLabels...)
var result vector
// The set of signatures for the right-hand side vector.
@ -751,7 +751,7 @@ func (ev *evaluator) vectorOr(lhs, rhs vector, matching *VectorMatching) vector
if matching.Card != CardManyToMany {
panic("set operations must only use many-to-many matching")
}
sigf := signatureFunc(matching.Ignoring, matching.MatchingLabels...)
sigf := signatureFunc(matching.On, matching.MatchingLabels...)
var result vector
leftSigs := map[uint64]struct{}{}
@ -773,7 +773,7 @@ func (ev *evaluator) vectorUnless(lhs, rhs vector, matching *VectorMatching) vec
if matching.Card != CardManyToMany {
panic("set operations must only use many-to-many matching")
}
sigf := signatureFunc(matching.Ignoring, matching.MatchingLabels...)
sigf := signatureFunc(matching.On, matching.MatchingLabels...)
rightSigs := map[uint64]struct{}{}
for _, rs := range rhs {
@ -796,7 +796,7 @@ func (ev *evaluator) vectorBinop(op itemType, lhs, rhs vector, matching *VectorM
}
var (
result = vector{}
sigf = signatureFunc(matching.Ignoring, matching.MatchingLabels...)
sigf = signatureFunc(matching.On, matching.MatchingLabels...)
)
// The control flow below handles one-to-one or many-to-one matching.
@ -882,9 +882,9 @@ func (ev *evaluator) vectorBinop(op itemType, lhs, rhs vector, matching *VectorM
}
// signatureFunc returns a function that calculates the signature for a metric
// based on the provided labels. If ignoring, then the given labels are ignored instead.
func signatureFunc(ignoring bool, labels ...model.LabelName) func(m metric.Metric) uint64 {
if len(labels) == 0 || ignoring {
// ignoring the provided labels. If on, then the given labels are only used instead.
func signatureFunc(on bool, labels ...model.LabelName) func(m metric.Metric) uint64 {
if !on {
return func(m metric.Metric) uint64 {
tmp := m.Metric.Clone()
for _, l := range labels {
@ -905,10 +905,7 @@ func resultMetric(lhs, rhs metric.Metric, op itemType, matching *VectorMatching)
if shouldDropMetricName(op) {
lhs.Del(model.MetricNameLabel)
}
if len(matching.MatchingLabels)+len(matching.Include) == 0 {
return lhs
}
if matching.Ignoring {
if !matching.On {
if matching.Card == CardOneToOne {
for _, l := range matching.MatchingLabels {
lhs.Del(l)

View File

@ -463,8 +463,8 @@ func (p *parser) expr() Expr {
// Parse ON/IGNORING clause.
if p.peek().typ == itemOn || p.peek().typ == itemIgnoring {
if p.peek().typ == itemIgnoring {
vecMatching.Ignoring = true
if p.peek().typ == itemOn {
vecMatching.On = true
}
p.next()
vecMatching.MatchingLabels = p.labels()
@ -485,7 +485,7 @@ func (p *parser) expr() Expr {
for _, ln := range vecMatching.MatchingLabels {
for _, ln2 := range vecMatching.Include {
if ln == ln2 && !vecMatching.Ignoring {
if ln == ln2 && vecMatching.On {
p.errorf("label %q must not occur in ON and GROUP clause at once", ln)
}
}
@ -671,14 +671,16 @@ func (p *parser) labels() model.LabelNames {
p.expect(itemLeftParen, ctx)
labels := model.LabelNames{}
for {
id := p.expect(itemIdentifier, ctx)
labels = append(labels, model.LabelName(id.val))
if p.peek().typ != itemRightParen {
for {
id := p.expect(itemIdentifier, ctx)
labels = append(labels, model.LabelName(id.val))
if p.peek().typ != itemComma {
break
if p.peek().typ != itemComma {
break
}
p.next()
}
p.next()
}
p.expect(itemRightParen, ctx)

View File

@ -471,12 +471,14 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardOneToMany,
MatchingLabels: model.LabelNames{"baz", "buz"},
On: true,
Include: model.LabelNames{"test"},
},
},
VectorMatching: &VectorMatching{
Card: CardOneToOne,
MatchingLabels: model.LabelNames{"foo"},
On: true,
},
},
}, {
@ -498,6 +500,7 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardOneToOne,
MatchingLabels: model.LabelNames{"test", "blub"},
On: true,
},
},
}, {
@ -519,6 +522,7 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardManyToOne,
MatchingLabels: model.LabelNames{"test", "blub"},
On: true,
},
},
}, {
@ -540,6 +544,29 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardManyToMany,
MatchingLabels: model.LabelNames{"test", "blub"},
On: true,
},
},
}, {
input: "foo and on() bar",
expected: &BinaryExpr{
Op: itemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: model.MetricNameLabel, Value: "foo"},
},
},
RHS: &VectorSelector{
Name: "bar",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: model.MetricNameLabel, Value: "bar"},
},
},
VectorMatching: &VectorMatching{
Card: CardManyToMany,
MatchingLabels: model.LabelNames{},
On: true,
},
},
}, {
@ -561,7 +588,27 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardManyToMany,
MatchingLabels: model.LabelNames{"test", "blub"},
Ignoring: true,
},
},
}, {
input: "foo and ignoring() bar",
expected: &BinaryExpr{
Op: itemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: model.MetricNameLabel, Value: "foo"},
},
},
RHS: &VectorSelector{
Name: "bar",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: model.MetricNameLabel, Value: "bar"},
},
},
VectorMatching: &VectorMatching{
Card: CardManyToMany,
MatchingLabels: model.LabelNames{},
},
},
}, {
@ -583,6 +630,7 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardManyToMany,
MatchingLabels: model.LabelNames{"bar"},
On: true,
},
},
}, {
@ -604,6 +652,7 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{
Card: CardManyToOne,
MatchingLabels: model.LabelNames{"test", "blub"},
On: true,
Include: model.LabelNames{"bar"},
},
},
@ -627,7 +676,6 @@ var testExpr = []struct {
Card: CardManyToOne,
MatchingLabels: model.LabelNames{"test", "blub"},
Include: model.LabelNames{"blub"},
Ignoring: true,
},
},
}, {
@ -650,7 +698,6 @@ var testExpr = []struct {
Card: CardManyToOne,
MatchingLabels: model.LabelNames{"test", "blub"},
Include: model.LabelNames{"bar"},
Ignoring: true,
},
},
}, {
@ -673,6 +720,7 @@ var testExpr = []struct {
Card: CardOneToMany,
MatchingLabels: model.LabelNames{"test", "blub"},
Include: model.LabelNames{"bar", "foo"},
On: true,
},
},
}, {
@ -695,7 +743,6 @@ var testExpr = []struct {
Card: CardOneToMany,
MatchingLabels: model.LabelNames{"test", "blub"},
Include: model.LabelNames{"bar", "foo"},
Ignoring: true,
},
},
}, {
@ -1142,6 +1189,18 @@ var testExpr = []struct {
},
Grouping: model.LabelNames{"foo"},
},
}, {
input: "sum by ()(some_metric)",
expected: &AggregateExpr{
Op: itemSum,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: model.MetricNameLabel, Value: "some_metric"},
},
},
Grouping: model.LabelNames{},
},
}, {
input: `sum some_metric by (test)`,
fail: true,
@ -1150,10 +1209,6 @@ var testExpr = []struct {
input: `sum (some_metric) by test`,
fail: true,
errMsg: "unexpected identifier \"test\" in grouping opts, expected \"(\"",
}, {
input: `sum (some_metric) by ()`,
fail: true,
errMsg: "unexpected \")\" in grouping opts, expected identifier",
}, {
input: `sum (some_metric) by test`,
fail: true,

View File

@ -160,10 +160,10 @@ func (node *BinaryExpr) String() string {
matching := ""
vm := node.VectorMatching
if vm != nil && len(vm.MatchingLabels) > 0 {
if vm.Ignoring {
matching = fmt.Sprintf(" IGNORING(%s)", vm.MatchingLabels)
} else {
if vm.On {
matching = fmt.Sprintf(" ON(%s)", vm.MatchingLabels)
} else {
matching = fmt.Sprintf(" IGNORING(%s)", vm.MatchingLabels)
}
if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
matching += " GROUP_"

View File

@ -37,6 +37,19 @@ eval instant at 50m sum without (instance) (http_requests{job="api-server"})
{group="canary",job="api-server"} 700
{group="production",job="api-server"} 300
# Empty by.
eval instant at 50m sum by () (http_requests{job="api-server"})
{} 1000
# No by/without.
eval instant at 50m sum (http_requests{job="api-server"})
{} 1000
# Empty without.
eval instant at 50m sum without () (http_requests{job="api-server",group="production"})
{group="production",job="api-server",instance="0"} 100
{group="production",job="api-server",instance="1"} 200
# Without with mismatched and missing labels. Do not do this.
eval instant at 50m sum without (instance) (http_requests{job="api-server"} or foo)
{group="canary",job="api-server"} 700

View File

@ -329,3 +329,21 @@ eval instant at 5m node_cpu > on(job, instance) group_left(target) (threshold or
node_cpu{instance="abc",job="node",mode="user",target="a@b.com"} 1
node_cpu{instance="def",job="node",mode="idle"} 8
node_cpu{instance="def",job="node",mode="user"} 2
clear
load 5m
random{foo="bar"} 2
metricA{baz="meh"} 3
metricB{baz="meh"} 4
# On with no labels, for metrics with no common labels.
eval instant at 5m random + on() metricA
{} 5
# Ignoring with no labels is the same as no ignoring.
eval instant at 5m metricA + ignoring() metricB
{baz="meh"} 7
eval instant at 5m metricA + metricB
{baz="meh"} 7