Change on+group_* to take copy from the one side.

If the label doesn't exist on the one side, it's not copied.

All labels on the many inside are included, this is a breaking change
but likely low impact.
This commit is contained in:
Brian Brazil 2016-04-21 18:41:27 +01:00
parent d1edfb25b3
commit 768d09fd2a
2 changed files with 20 additions and 17 deletions

View file

@ -902,23 +902,20 @@ func signatureFunc(ignoring bool, labels ...model.LabelName) func(m metric.Metri
// resultMetric returns the metric for the given sample(s) based on the vector // resultMetric returns the metric for the given sample(s) based on the vector
// binary operation and the matching options. // binary operation and the matching options.
func resultMetric(lhs, rhs metric.Metric, op itemType, matching *VectorMatching) metric.Metric { func resultMetric(lhs, rhs metric.Metric, op itemType, matching *VectorMatching) metric.Metric {
if shouldDropMetricName(op) {
lhs.Del(model.MetricNameLabel)
}
if len(matching.On)+len(matching.Include) == 0 { if len(matching.On)+len(matching.Include) == 0 {
if shouldDropMetricName(op) {
lhs.Del(model.MetricNameLabel)
}
return lhs return lhs
} }
if matching.Ignoring { if matching.Ignoring {
if shouldDropMetricName(op) {
lhs.Del(model.MetricNameLabel)
}
if matching.Card == CardOneToOne { if matching.Card == CardOneToOne {
for _, l := range matching.On { for _, l := range matching.On {
lhs.Del(l) lhs.Del(l)
} }
} }
for _, ln := range matching.Include { for _, ln := range matching.Include {
// Included labels from the `group_x` modifier are taken from the one side with Ignoring. // Included labels from the `group_x` modifier are taken from the "one"-side.
value := rhs.Metric[ln] value := rhs.Metric[ln]
if value != "" { if value != "" {
lhs.Set(ln, rhs.Metric[ln]) lhs.Set(ln, rhs.Metric[ln])
@ -930,14 +927,20 @@ func resultMetric(lhs, rhs metric.Metric, op itemType, matching *VectorMatching)
} }
// As we definitely write, creating a new metric is the easiest solution. // As we definitely write, creating a new metric is the easiest solution.
m := model.Metric{} m := model.Metric{}
for _, ln := range matching.On { if matching.Card == CardOneToOne {
if v, ok := lhs.Metric[ln]; ok { for _, ln := range matching.On {
m[ln] = v if v, ok := lhs.Metric[ln]; ok {
m[ln] = v
}
}
} else {
for k, v := range lhs.Metric {
m[k] = v
} }
} }
for _, ln := range matching.Include { for _, ln := range matching.Include {
// Included labels from the `group_x` modifier are taken from the "many"-side with On. // Included labels from the `group_x` modifier are taken from the "one"-side .
if v, ok := lhs.Metric[ln]; ok { if v, ok := rhs.Metric[ln]; ok {
m[ln] = v m[ln] = v
} }
} }

View file

@ -281,8 +281,8 @@ eval instant at 5m sum(sum without (instance)(node_cpu) / ignoring (mode) group_
# Copy over label from metric with no matching labels, without having to list cross-job target labels ('job' here). # Copy over label from metric with no matching labels, without having to list cross-job target labels ('job' here).
#eval instant at 5m node_cpu + on(dummy) group_left(foo) random eval instant at 5m node_cpu + on(dummy) group_left(foo) random*0
# {instance="abc",job="node",mode="idle",foo="bar"} 3 {instance="abc",job="node",mode="idle",foo="bar"} 3
# {instance="abc",job="node",mode="user",foo="bar"} 1 {instance="abc",job="node",mode="user",foo="bar"} 1
# {instance="def",job="node",mode="idle",foo="bar"} 8 {instance="def",job="node",mode="idle",foo="bar"} 8
# {instance="def",job="node",mode="user",foo="bar"} 2 {instance="def",job="node",mode="user",foo="bar"} 2