From 41ecb6c6b2df1e3e2e1dbbe57524445ec015350d Mon Sep 17 00:00:00 2001 From: beorn7 Date: Tue, 5 May 2015 22:16:17 +0200 Subject: [PATCH] Improve the Metric.Equal and Metric.Before methods. --- model/metric.go | 64 +++++++++++++++++++++++++++++++++++++++----- model/sample_test.go | 60 +++++++++++++++++------------------------ model/signature.go | 2 +- 3 files changed, 83 insertions(+), 43 deletions(-) diff --git a/model/metric.go b/model/metric.go index b43ddaf..0870f23 100644 --- a/model/metric.go +++ b/model/metric.go @@ -26,16 +26,68 @@ var separator = []byte{0} // a singleton and refers to one and only one stream of samples. type Metric map[LabelName]LabelValue -// Equal compares the fingerprints of both metrics. +// Equal compares the metrics. func (m Metric) Equal(o Metric) bool { - // TODO do an actual map comparison - return m.Fingerprint().Equal(o.Fingerprint()) + if len(m) != len(o) { + 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 { - // TODO do an actual map comparison - return m.Fingerprint().Less(o.Fingerprint()) + if len(m) < len(o) { + 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. diff --git a/model/sample_test.go b/model/sample_test.go index 3dc4ad2..d5e065d 100644 --- a/model/sample_test.go +++ b/model/sample_test.go @@ -21,42 +21,36 @@ import ( func TestSamplesSort(t *testing.T) { input := Samples{ &Sample{ - // Fingerprint: 81f9c9ed24563f8f. Metric: Metric{ MetricNameLabel: "A", }, Timestamp: 1, }, &Sample{ - // Fingerprint: 81f9c9ed24563f8f. Metric: Metric{ MetricNameLabel: "A", }, Timestamp: 2, }, &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", }, @@ -66,47 +60,41 @@ func TestSamplesSort(t *testing.T) { expected := Samples{ &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{ MetricNameLabel: "A", }, Timestamp: 1, }, &Sample{ - // Fingerprint: 81f9c9ed24563f8f. Metric: Metric{ MetricNameLabel: "A", }, 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) diff --git a/model/signature.go b/model/signature.go index 3f7abec..7bd58f4 100644 --- a/model/signature.go +++ b/model/signature.go @@ -52,7 +52,7 @@ func putHashAndBuf(hb *hashAndBuf) { 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 // sets the function is applied to is small.) func LabelsToSignature(labels map[string]string) uint64 {