// maybeAddMapping adds a fingerprint mapping to fpm if the FastFingerprint of m is different from fp. func maybeAddMapping(fp clientmodel.Fingerprint, m clientmodel.Metric, fpm fpMappings) { if rawFP := m.FastFingerprint(); rawFP != fp { log.Warnf( "Metric %v with fingerprint %v is mapped from raw fingerprint %v.", m, fp, rawFP, ) if mappedFPs, ok := fpm[rawFP]; ok { mappedFPs[metricToUniqueString(m)] = fp } else { fpm[rawFP] = map[string]clientmodel.Fingerprint{ metricToUniqueString(m): fp, } } } }
func TestAppendOutOfOrder(t *testing.T) { s, closer := NewTestStorage(t, 1) defer closer.Close() m := clientmodel.Metric{ clientmodel.MetricNameLabel: "out_of_order", } for i, t := range []int{0, 2, 2, 1} { s.Append(&clientmodel.Sample{ Metric: m, Timestamp: clientmodel.Timestamp(t), Value: clientmodel.SampleValue(i), }) } fp, err := s.mapper.mapFP(m.FastFingerprint(), m) if err != nil { t.Fatal(err) } pl := s.NewPreloader() defer pl.Close() err = pl.PreloadRange(fp, 0, 2, 5*time.Minute) if err != nil { t.Fatalf("Error preloading chunks: %s", err) } it := s.NewIterator(fp) want := metric.Values{ { Timestamp: 0, Value: 0, }, { Timestamp: 2, Value: 1, }, } got := it.RangeValues(metric.Interval{OldestInclusive: 0, NewestInclusive: 2}) if !reflect.DeepEqual(want, got) { t.Fatalf("want %v, got %v", want, got) } }
func TestMatches(t *testing.T) { storage, closer := NewTestStorage(t, 1) defer closer.Close() samples := make([]*clientmodel.Sample, 100) fingerprints := make(clientmodel.Fingerprints, 100) for i := range samples { metric := clientmodel.Metric{ clientmodel.MetricNameLabel: clientmodel.LabelValue(fmt.Sprintf("test_metric_%d", i)), "label1": clientmodel.LabelValue(fmt.Sprintf("test_%d", i/10)), "label2": clientmodel.LabelValue(fmt.Sprintf("test_%d", (i+5)/10)), "all": "const", } samples[i] = &clientmodel.Sample{ Metric: metric, Timestamp: clientmodel.Timestamp(i), Value: clientmodel.SampleValue(i), } fingerprints[i] = metric.FastFingerprint() } for _, s := range samples { storage.Append(s) } storage.WaitForIndexing() newMatcher := func(matchType metric.MatchType, name clientmodel.LabelName, value clientmodel.LabelValue) *metric.LabelMatcher { lm, err := metric.NewLabelMatcher(matchType, name, value) if err != nil { t.Fatalf("error creating label matcher: %s", err) } return lm } var matcherTests = []struct { matchers metric.LabelMatchers expected clientmodel.Fingerprints }{ { matchers: metric.LabelMatchers{newMatcher(metric.Equal, "label1", "x")}, expected: clientmodel.Fingerprints{}, }, { matchers: metric.LabelMatchers{newMatcher(metric.Equal, "label1", "test_0")}, expected: fingerprints[:10], }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "label1", "test_0"), newMatcher(metric.Equal, "label2", "test_1"), }, expected: fingerprints[5:10], }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "all", "const"), newMatcher(metric.NotEqual, "label1", "x"), }, expected: fingerprints, }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "all", "const"), newMatcher(metric.NotEqual, "label1", "test_0"), }, expected: fingerprints[10:], }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "all", "const"), newMatcher(metric.NotEqual, "label1", "test_0"), newMatcher(metric.NotEqual, "label1", "test_1"), newMatcher(metric.NotEqual, "label1", "test_2"), }, expected: fingerprints[30:], }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "label1", ""), }, expected: fingerprints[:0], }, { matchers: metric.LabelMatchers{ newMatcher(metric.NotEqual, "label1", "test_0"), newMatcher(metric.Equal, "label1", ""), }, expected: fingerprints[:0], }, { matchers: metric.LabelMatchers{ newMatcher(metric.NotEqual, "label1", "test_0"), newMatcher(metric.Equal, "label2", ""), }, expected: fingerprints[:0], }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "all", "const"), newMatcher(metric.NotEqual, "label1", "test_0"), newMatcher(metric.Equal, "not_existant", ""), }, expected: fingerprints[10:], }, { matchers: metric.LabelMatchers{ newMatcher(metric.RegexMatch, "label1", `test_[3-5]`), }, expected: fingerprints[30:60], }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "all", "const"), newMatcher(metric.RegexNoMatch, "label1", `test_[3-5]`), }, expected: append(append(clientmodel.Fingerprints{}, fingerprints[:30]...), fingerprints[60:]...), }, { matchers: metric.LabelMatchers{ newMatcher(metric.RegexMatch, "label1", `test_[3-5]`), newMatcher(metric.RegexMatch, "label2", `test_[4-6]`), }, expected: fingerprints[35:60], }, { matchers: metric.LabelMatchers{ newMatcher(metric.RegexMatch, "label1", `test_[3-5]`), newMatcher(metric.NotEqual, "label2", `test_4`), }, expected: append(append(clientmodel.Fingerprints{}, fingerprints[30:35]...), fingerprints[45:60]...), }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "label1", `nonexistent`), newMatcher(metric.RegexMatch, "label2", `test`), }, expected: clientmodel.Fingerprints{}, }, { matchers: metric.LabelMatchers{ newMatcher(metric.Equal, "label1", `test_0`), newMatcher(metric.RegexMatch, "label2", `nonexistent`), }, expected: clientmodel.Fingerprints{}, }, } for _, mt := range matcherTests { res := storage.MetricsForLabelMatchers(mt.matchers...) if len(mt.expected) != len(res) { t.Fatalf("expected %d matches for %q, found %d", len(mt.expected), mt.matchers, len(res)) } for fp1 := range res { found := false for _, fp2 := range mt.expected { if fp1 == fp2 { found = true break } } if !found { t.Errorf("expected fingerprint %s for %q not in result", fp1, mt.matchers) } } } }
func TestFingerprintsForLabels(t *testing.T) { storage, closer := NewTestStorage(t, 1) defer closer.Close() samples := make([]*clientmodel.Sample, 100) fingerprints := make(clientmodel.Fingerprints, 100) for i := range samples { metric := clientmodel.Metric{ clientmodel.MetricNameLabel: clientmodel.LabelValue(fmt.Sprintf("test_metric_%d", i)), "label1": clientmodel.LabelValue(fmt.Sprintf("test_%d", i/10)), "label2": clientmodel.LabelValue(fmt.Sprintf("test_%d", (i+5)/10)), } samples[i] = &clientmodel.Sample{ Metric: metric, Timestamp: clientmodel.Timestamp(i), Value: clientmodel.SampleValue(i), } fingerprints[i] = metric.FastFingerprint() } for _, s := range samples { storage.Append(s) } storage.WaitForIndexing() var matcherTests = []struct { pairs []metric.LabelPair expected clientmodel.Fingerprints }{ { pairs: []metric.LabelPair{{"label1", "x"}}, expected: fingerprints[:0], }, { pairs: []metric.LabelPair{{"label1", "test_0"}}, expected: fingerprints[:10], }, { pairs: []metric.LabelPair{ {"label1", "test_0"}, {"label1", "test_1"}, }, expected: fingerprints[:0], }, { pairs: []metric.LabelPair{ {"label1", "test_0"}, {"label2", "test_1"}, }, expected: fingerprints[5:10], }, { pairs: []metric.LabelPair{ {"label1", "test_1"}, {"label2", "test_2"}, }, expected: fingerprints[15:20], }, } for _, mt := range matcherTests { resfps := storage.fingerprintsForLabelPairs(mt.pairs...) if len(mt.expected) != len(resfps) { t.Fatalf("expected %d matches for %q, found %d", len(mt.expected), mt.pairs, len(resfps)) } for fp1 := range resfps { found := false for _, fp2 := range mt.expected { if fp1 == fp2 { found = true break } } if !found { t.Errorf("expected fingerprint %s for %q not in result", fp1, mt.pairs) } } } }