From d9b165220e57f011ab95a054b02a74995f4d93f3 Mon Sep 17 00:00:00 2001 From: "Matt T. Proud" Date: Sun, 13 Jan 2013 11:15:01 +0100 Subject: [PATCH] ``GetFingerprintsForLabelSet`` uses intersection. This implementation needs to be cleaned up considerably, but it should hopefully provide some breathing room. Ultimately this will be extracted out of the storage layer---specifically the LevelDB hierarchy---to interface with a generic set of abstractions for a storage system, but this will be where it remains for now. --- storage/metric/leveldb/reading.go | 24 ++++++- storage/metric/leveldb/regressions_test.go | 76 ++++++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 storage/metric/leveldb/regressions_test.go diff --git a/storage/metric/leveldb/reading.go b/storage/metric/leveldb/reading.go index 48912013f..56549f366 100644 --- a/storage/metric/leveldb/reading.go +++ b/storage/metric/leveldb/reading.go @@ -22,6 +22,7 @@ import ( "github.com/matttproud/prometheus/model" dto "github.com/matttproud/prometheus/model/generated" "github.com/matttproud/prometheus/storage/metric" + "github.com/matttproud/prometheus/utility" "time" ) @@ -170,7 +171,7 @@ func (l *LevelDBMetricPersistence) GetFingerprintsForLabelSet(labelSet *model.La m.Increment() }() - fps = make([]*model.Fingerprint, 0, 0) + sets := []utility.Set{} for _, labelSetDTO := range model.LabelSetToDTOs(labelSet) { f, err := l.labelSetToFingerprints.Get(coding.NewProtocolBufferEncoder(labelSetDTO)) @@ -184,10 +185,29 @@ func (l *LevelDBMetricPersistence) GetFingerprintsForLabelSet(labelSet *model.La return fps, err } + set := utility.Set{} + for _, m := range unmarshaled.Member { fp := model.Fingerprint(*m.Signature) - fps = append(fps, &fp) + set.Add(fp) } + + sets = append(sets, set) + } + + numberOfSets := len(sets) + if numberOfSets == 0 { + return + } + + base := sets[0] + for i := 1; i < numberOfSets; i++ { + base = base.Intersection(sets[i]) + } + fps = []*model.Fingerprint{} + for _, e := range base.Elements() { + fingerprint := e.(model.Fingerprint) + fps = append(fps, &fingerprint) } return diff --git a/storage/metric/leveldb/regressions_test.go b/storage/metric/leveldb/regressions_test.go new file mode 100644 index 000000000..e89985127 --- /dev/null +++ b/storage/metric/leveldb/regressions_test.go @@ -0,0 +1,76 @@ +// Copyright 2012 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package leveldb + +import ( + "github.com/matttproud/prometheus/model" + "io/ioutil" + "os" + "testing" + "time" +) + +func TestGetFingerprintsForLabelSetUsesAnd(t *testing.T) { + temporaryDirectory, _ := ioutil.TempDir("", "test_get_fingerprints_for_label_set_uses_and") + + defer func() { + err := os.RemoveAll(temporaryDirectory) + if err != nil { + t.Errorf("could not remove temporary directory: %f", err) + } + }() + + persistence, _ := NewLevelDBMetricPersistence(temporaryDirectory) + defer persistence.Close() + + metrics := []map[string]string{ + {"name": "request_metrics_latency_equal_tallying_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, + {"name": "requests_metrics_latency_equal_accumulating_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, + {"name": "requests_metrics_latency_logarithmic_accumulating_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, + {"name": "requests_metrics_latency_logarithmic_tallying_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, + {"name": "targets_healthy_scrape_latency_ms", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, + } + + for _, metric := range metrics { + m := model.Metric{} + + for k, v := range metric { + m[model.LabelName(k)] = model.LabelValue(v) + } + + err := persistence.AppendSample(&model.Sample{ + Value: model.SampleValue(0.0), + Timestamp: time.Now(), + Metric: m, + }) + + if err != nil { + t.Errorf("could not create base sample: %s", err) + } + } + + labelSet := model.LabelSet{ + "name": "targets_healthy_scrape_latency_ms", + "percentile": "0.010000", + } + + fingerprints, err := persistence.GetFingerprintsForLabelSet(&labelSet) + if err != nil { + t.Errorf("could not get labels: %s", err) + } + + if len(fingerprints) != 1 { + t.Errorf("did not get a single metric as is expected, got %s", fingerprints) + } +}