From d17b5be48a7005a81c73e00c20d64bce908fd81b Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Sun, 25 Dec 2016 00:42:52 +0100 Subject: [PATCH] storage/metric: remove package --- storage/metric/matcher.go | 201 --------------------------------- storage/metric/matcher_test.go | 73 ------------ storage/metric/metric.go | 63 ----------- storage/metric/metric_test.go | 70 ------------ storage/metric/sample.go | 22 ---- 5 files changed, 429 deletions(-) delete mode 100644 storage/metric/matcher.go delete mode 100644 storage/metric/matcher_test.go delete mode 100644 storage/metric/metric.go delete mode 100644 storage/metric/metric_test.go delete mode 100644 storage/metric/sample.go diff --git a/storage/metric/matcher.go b/storage/metric/matcher.go deleted file mode 100644 index 8b362db790..0000000000 --- a/storage/metric/matcher.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// 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 metric - -import ( - "fmt" - "regexp" - "strings" - - "github.com/prometheus/common/model" -) - -// MatchType is an enum for label matching types. -type MatchType int - -// Possible MatchTypes. -const ( - Equal MatchType = iota - NotEqual - RegexMatch - RegexNoMatch -) - -func (m MatchType) String() string { - typeToStr := map[MatchType]string{ - Equal: "=", - NotEqual: "!=", - RegexMatch: "=~", - RegexNoMatch: "!~", - } - if str, ok := typeToStr[m]; ok { - return str - } - panic("unknown match type") -} - -// LabelMatchers is a slice of LabelMatcher objects. By implementing the -// sort.Interface, it is sortable by cardinality score, i.e. after sorting, the -// LabelMatcher that is expected to yield the fewest matches is first in the -// slice, and LabelMatchers that match the empty string are last. -type LabelMatchers []*LabelMatcher - -func (lms LabelMatchers) Len() int { return len(lms) } -func (lms LabelMatchers) Swap(i, j int) { lms[i], lms[j] = lms[j], lms[i] } -func (lms LabelMatchers) Less(i, j int) bool { return lms[i].score < lms[j].score } - -// LabelMatcher models the matching of a label. Create with NewLabelMatcher. -type LabelMatcher struct { - Type MatchType - Name model.LabelName - Value model.LabelValue - re *regexp.Regexp - score float64 // Cardinality score, between 0 and 1, 0 is lowest cardinality. -} - -// NewLabelMatcher returns a LabelMatcher object ready to use. -func NewLabelMatcher(matchType MatchType, name model.LabelName, value model.LabelValue) (*LabelMatcher, error) { - m := &LabelMatcher{ - Type: matchType, - Name: name, - Value: value, - } - if matchType == RegexMatch || matchType == RegexNoMatch { - re, err := regexp.Compile("^(?:" + string(value) + ")$") - if err != nil { - return nil, err - } - m.re = re - } - m.calculateScore() - return m, nil -} - -// calculateScore is a helper method only called in the constructor. It -// calculates the cardinality score upfront, so that sorting by it is faster and -// doesn't change internal state of the matcher. -// -// The score is based on a pretty bad but still quite helpful heuristics for -// now. Note that this is an interim solution until the work in progress to -// properly intersect matchers is complete. We intend to not invest any further -// effort into tweaking the score calculation, as this could easily devolve into -// a rabbit hole. -// -// The heuristics works along the following lines: -// -// - A matcher that is known to match nothing would have a score of 0. (This -// case doesn't happen in the scope of this method.) -// -// - A matcher that matches the empty string has a score of 1. -// -// - Equal matchers have a score <= 0.5. The order in score for other matchers -// are RegexMatch, RegexNoMatch, NotEqual. -// -// - There are a number of score adjustments for known "magic" parts, like -// instance labels, metric names containing a colon (which are probably -// recording rules) and such. -// -// - On top, there is a tiny adjustment for the length of the matcher, following -// the blunt expectation that a long label name and/or value is more specific -// and will therefore have a lower cardinality. -// -// To reiterate on the above: PLEASE RESIST THE TEMPTATION TO TWEAK THIS -// METHOD. IT IS "MAGIC" ENOUGH ALREADY AND WILL GO AWAY WITH THE UPCOMING MORE -// POWERFUL INDEXING. -func (m *LabelMatcher) calculateScore() { - if m.Match("") { - m.score = 1 - return - } - // lengthCorrection is between 0 (for length 0) and 0.1 (for length +Inf). - lengthCorrection := 0.1 * (1 - 1/float64(len(m.Name)+len(m.Value)+1)) - switch m.Type { - case Equal: - m.score = 0.3 - lengthCorrection - case RegexMatch: - m.score = 0.6 - lengthCorrection - case RegexNoMatch: - m.score = 0.8 + lengthCorrection - case NotEqual: - m.score = 0.9 + lengthCorrection - } - if m.Type != Equal { - // Don't bother anymore in this case. - return - } - switch m.Name { - case model.InstanceLabel: - // Matches only metrics from a single instance, which clearly - // limits the damage. - m.score -= 0.2 - case model.JobLabel: - // The usual case is a relatively low number of jobs with many - // metrics each. - m.score += 0.1 - case model.BucketLabel, model.QuantileLabel: - // Magic labels for buckets and quantiles will match copiously. - m.score += 0.2 - case model.MetricNameLabel: - if strings.Contains(string(m.Value), ":") { - // Probably a recording rule with limited cardinality. - m.score -= 0.1 - return - } - if m.Value == "up" || m.Value == "scrape_duration_seconds" { - // Synthetic metrics which are contained in every scrape - // exactly once. There might be less frequent metric - // names, but the worst case is limited here, so give it - // a bump. - m.score -= 0.05 - return - } - } -} - -// MatchesEmptyString returns true if the LabelMatcher matches the empty string. -func (m *LabelMatcher) MatchesEmptyString() bool { - return m.score >= 1 -} - -func (m *LabelMatcher) String() string { - return fmt.Sprintf("%s%s%q", m.Name, m.Type, m.Value) -} - -// Match returns true if the label matcher matches the supplied label value. -func (m *LabelMatcher) Match(v model.LabelValue) bool { - switch m.Type { - case Equal: - return m.Value == v - case NotEqual: - return m.Value != v - case RegexMatch: - return m.re.MatchString(string(v)) - case RegexNoMatch: - return !m.re.MatchString(string(v)) - default: - panic("invalid match type") - } -} - -// Filter takes a list of label values and returns all label values which match -// the label matcher. -func (m *LabelMatcher) Filter(in model.LabelValues) model.LabelValues { - out := model.LabelValues{} - for _, v := range in { - if m.Match(v) { - out = append(out, v) - } - } - return out -} diff --git a/storage/metric/matcher_test.go b/storage/metric/matcher_test.go deleted file mode 100644 index 0038cee43a..0000000000 --- a/storage/metric/matcher_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// 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 metric - -import ( - "math/rand" - "reflect" - "sort" - "testing" - - "github.com/prometheus/common/model" -) - -func TestAnchoredMatcher(t *testing.T) { - m, err := NewLabelMatcher(RegexMatch, "", "foo|bar|baz") - if err != nil { - t.Fatal(err) - } - - if !m.Match("foo") { - t.Errorf("Expected match for %q but got none", "foo") - } - if m.Match("fooo") { - t.Errorf("Unexpected match for %q", "fooo") - } -} - -func TestLabelMatchersSort(t *testing.T) { - // Line up Matchers in expected order: - want := LabelMatchers{ - mustNewLabelMatcher(Equal, model.InstanceLabel, "not empty"), - mustNewLabelMatcher(Equal, model.MetricNameLabel, "a:recording:rule"), - mustNewLabelMatcher(Equal, model.MetricNameLabel, "up"), - mustNewLabelMatcher(Equal, "nothing_special but much longer", "not empty"), - mustNewLabelMatcher(Equal, "nothing_special", "not empty but longer"), - mustNewLabelMatcher(Equal, "nothing_special", "not empty"), - mustNewLabelMatcher(Equal, model.JobLabel, "not empty"), - mustNewLabelMatcher(Equal, model.BucketLabel, "not empty"), - mustNewLabelMatcher(RegexMatch, "irrelevant", "does not match empty string and is longer"), - mustNewLabelMatcher(RegexMatch, "irrelevant", "does not match empty string"), - mustNewLabelMatcher(RegexNoMatch, "irrelevant", "(matches empty string)?"), - mustNewLabelMatcher(RegexNoMatch, "irrelevant", "(matches empty string with a longer expression)?"), - mustNewLabelMatcher(NotEqual, "irrelevant", ""), - mustNewLabelMatcher(Equal, "irrelevant", ""), - } - got := make(LabelMatchers, len(want)) - for i, j := range rand.Perm(len(want)) { - got[i] = want[j] - } - sort.Sort(got) - if !reflect.DeepEqual(want, got) { - t.Errorf("unexpected sorting of matchers, got %v, want %v", got, want) - } -} - -func mustNewLabelMatcher(mt MatchType, name model.LabelName, val model.LabelValue) *LabelMatcher { - m, err := NewLabelMatcher(mt, name, val) - if err != nil { - panic(err) - } - return m -} diff --git a/storage/metric/metric.go b/storage/metric/metric.go deleted file mode 100644 index 7328ac7a88..0000000000 --- a/storage/metric/metric.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// 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 metric - -import "github.com/prometheus/common/model" - -// Metric wraps a model.Metric and copies it upon modification if Copied is false. -type Metric struct { - Copied bool - Metric model.Metric -} - -// Set sets a label name in the wrapped Metric to a given value and copies the -// Metric initially, if it is not already a copy. -func (m *Metric) Set(ln model.LabelName, lv model.LabelValue) { - m.Copy() - m.Metric[ln] = lv -} - -// Del deletes a given label name from the wrapped Metric and copies the -// Metric initially, if it is not already a copy. -func (m *Metric) Del(ln model.LabelName) { - m.Copy() - delete(m.Metric, ln) -} - -// Get the value for the given label name. An empty value is returned -// if the label does not exist in the metric. -func (m *Metric) Get(ln model.LabelName) model.LabelValue { - return m.Metric[ln] -} - -// Gets behaves as Get but the returned boolean is false iff the label -// does not exist. -func (m *Metric) Gets(ln model.LabelName) (model.LabelValue, bool) { - lv, ok := m.Metric[ln] - return lv, ok -} - -// Copy the underlying Metric if it is not already a copy. -func (m *Metric) Copy() *Metric { - if !m.Copied { - m.Metric = m.Metric.Clone() - m.Copied = true - } - return m -} - -// String implements fmt.Stringer. -func (m Metric) String() string { - return m.Metric.String() -} diff --git a/storage/metric/metric_test.go b/storage/metric/metric_test.go deleted file mode 100644 index f33a51e40a..0000000000 --- a/storage/metric/metric_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// 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 metric - -import ( - "testing" - - "github.com/prometheus/common/model" -) - -func TestMetric(t *testing.T) { - testMetric := model.Metric{ - "to_delete": "test1", - "to_change": "test2", - } - - scenarios := []struct { - fn func(*Metric) - out model.Metric - }{ - { - fn: func(cm *Metric) { - cm.Del("to_delete") - }, - out: model.Metric{ - "to_change": "test2", - }, - }, - { - fn: func(cm *Metric) { - cm.Set("to_change", "changed") - }, - out: model.Metric{ - "to_delete": "test1", - "to_change": "changed", - }, - }, - } - - for i, s := range scenarios { - orig := testMetric.Clone() - cm := &Metric{ - Metric: orig, - Copied: false, - } - - s.fn(cm) - - // Test that the original metric was not modified. - if !orig.Equal(testMetric) { - t.Fatalf("%d. original metric changed; expected %v, got %v", i, testMetric, orig) - } - - // Test that the new metric has the right changes. - if !cm.Metric.Equal(s.out) { - t.Fatalf("%d. copied metric doesn't contain expected changes; expected %v, got %v", i, s.out, cm.Metric) - } - } -} diff --git a/storage/metric/sample.go b/storage/metric/sample.go deleted file mode 100644 index a30c2b4564..0000000000 --- a/storage/metric/sample.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// 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 metric - -import "github.com/prometheus/common/model" - -// Interval describes the inclusive interval between two Timestamps. -type Interval struct { - OldestInclusive model.Time - NewestInclusive model.Time -}