Improve the Metric.Equal and Metric.Before methods.

This commit is contained in:
beorn7 2015-05-05 22:16:17 +02:00
parent 0e0e6bff80
commit 41ecb6c6b2
3 changed files with 83 additions and 43 deletions

View File

@ -26,16 +26,68 @@ var separator = []byte{0}
// a singleton and refers to one and only one stream of samples. // a singleton and refers to one and only one stream of samples.
type Metric map[LabelName]LabelValue type Metric map[LabelName]LabelValue
// Equal compares the fingerprints of both metrics. // Equal compares the metrics.
func (m Metric) Equal(o Metric) bool { func (m Metric) Equal(o Metric) bool {
// TODO do an actual map comparison if len(m) != len(o) {
return m.Fingerprint().Equal(o.Fingerprint()) return false
}
for ln, lv := range m {
olv, ok := o[ln]
if !ok {
return false
}
if olv != lv {
return false
}
}
return true
} }
// Before compares the fingerprints of both metrics. // Before compares the metrics, using the following criteria:
//
// If m has fewer labels than o, it is before o. If it has more, it is not.
//
// If the number of labels is the same, the superset of all label names is
// sorted alphanumerically. The first differing label pair found in that order
// determines the outcome: If the label does not exist at all in m, then m is
// before o, and vice versa. Otherwise the label value is compared
// alphanumerically.
//
// If m and o are equal, the method returns false.
func (m Metric) Before(o Metric) bool { func (m Metric) Before(o Metric) bool {
// TODO do an actual map comparison if len(m) < len(o) {
return m.Fingerprint().Less(o.Fingerprint()) return true
}
if len(m) > len(o) {
return false
}
lns := make(LabelNames, 0, len(m)+len(o))
for ln := range m {
lns = append(lns, ln)
}
for ln := range o {
lns = append(lns, ln)
}
// It's probably not worth it to de-dup lns.
sort.Sort(lns)
for _, ln := range lns {
mlv, ok := m[ln]
if !ok {
return true
}
olv, ok := o[ln]
if !ok {
return false
}
if mlv < olv {
return true
}
if mlv > olv {
return false
}
}
return false
} }
// String implements Stringer. // String implements Stringer.

View File

@ -21,42 +21,36 @@ import (
func TestSamplesSort(t *testing.T) { func TestSamplesSort(t *testing.T) {
input := Samples{ input := Samples{
&Sample{ &Sample{
// Fingerprint: 81f9c9ed24563f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "A", MetricNameLabel: "A",
}, },
Timestamp: 1, Timestamp: 1,
}, },
&Sample{ &Sample{
// Fingerprint: 81f9c9ed24563f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "A", MetricNameLabel: "A",
}, },
Timestamp: 2, Timestamp: 2,
}, },
&Sample{ &Sample{
// Fingerprint: 1bf6c9ed24543f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "C", MetricNameLabel: "C",
}, },
Timestamp: 1, Timestamp: 1,
}, },
&Sample{ &Sample{
// Fingerprint: 1bf6c9ed24543f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "C", MetricNameLabel: "C",
}, },
Timestamp: 2, Timestamp: 2,
}, },
&Sample{ &Sample{
// Fingerprint: 68f4c9ed24533f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "B", MetricNameLabel: "B",
}, },
Timestamp: 1, Timestamp: 1,
}, },
&Sample{ &Sample{
// Fingerprint: 68f4c9ed24533f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "B", MetricNameLabel: "B",
}, },
@ -66,47 +60,41 @@ func TestSamplesSort(t *testing.T) {
expected := Samples{ expected := Samples{
&Sample{ &Sample{
// Fingerprint: 1bf6c9ed24543f8f.
Metric: Metric{
MetricNameLabel: "C",
},
Timestamp: 1,
},
&Sample{
// Fingerprint: 1bf6c9ed24543f8f.
Metric: Metric{
MetricNameLabel: "C",
},
Timestamp: 2,
},
&Sample{
// Fingerprint: 68f4c9ed24533f8f.
Metric: Metric{
MetricNameLabel: "B",
},
Timestamp: 1,
},
&Sample{
// Fingerprint: 68f4c9ed24533f8f.
Metric: Metric{
MetricNameLabel: "B",
},
Timestamp: 2,
},
&Sample{
// Fingerprint: 81f9c9ed24563f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "A", MetricNameLabel: "A",
}, },
Timestamp: 1, Timestamp: 1,
}, },
&Sample{ &Sample{
// Fingerprint: 81f9c9ed24563f8f.
Metric: Metric{ Metric: Metric{
MetricNameLabel: "A", MetricNameLabel: "A",
}, },
Timestamp: 2, Timestamp: 2,
}, },
&Sample{
Metric: Metric{
MetricNameLabel: "B",
},
Timestamp: 1,
},
&Sample{
Metric: Metric{
MetricNameLabel: "B",
},
Timestamp: 2,
},
&Sample{
Metric: Metric{
MetricNameLabel: "C",
},
Timestamp: 1,
},
&Sample{
Metric: Metric{
MetricNameLabel: "C",
},
Timestamp: 2,
},
} }
sort.Sort(input) sort.Sort(input)

View File

@ -52,7 +52,7 @@ func putHashAndBuf(hb *hashAndBuf) {
hashAndBufPool.Put(hb) hashAndBufPool.Put(hb)
} }
// LabelsToSignature returns an quasi-unique signature (i.e., fingerprint) for a // LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
// given label set. (Collisions are possible but unlikely if the number of label // given label set. (Collisions are possible but unlikely if the number of label
// sets the function is applied to is small.) // sets the function is applied to is small.)
func LabelsToSignature(labels map[string]string) uint64 { func LabelsToSignature(labels map[string]string) uint64 {