func AppendRepeatingValuesTests(p metric.Persistence, t test.Tester) { m := clientmodel.Metric{ clientmodel.MetricNameLabel: "errors_total", "controller": "foo", "operation": "bar", } increments := 10 repetitions := 500 for i := 0; i < increments; i++ { for j := 0; j < repetitions; j++ { time := clientmodel.Timestamp(0).Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second) testAppendSamples(p, &clientmodel.Sample{ Value: clientmodel.SampleValue(i), Timestamp: time, Metric: m, }, t) } } v, ok := p.(metric.View) if !ok { // It's purely a benchmark for a Persistence that is not viewable. return } matchers := labelMatchersFromLabelSet(clientmodel.LabelSet{ clientmodel.MetricNameLabel: "errors_total", "controller": "foo", "operation": "bar", }) for i := 0; i < increments; i++ { for j := 0; j < repetitions; j++ { fingerprints, err := p.GetFingerprintsForLabelMatchers(matchers) if err != nil { t.Fatal(err) } if len(fingerprints) != 1 { t.Fatalf("expected %d fingerprints, got %d", 1, len(fingerprints)) } time := clientmodel.Timestamp(0).Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second) samples := v.GetValueAtTime(fingerprints[0], time) if len(samples) == 0 { t.Fatal("expected at least one sample.") } expected := clientmodel.SampleValue(i) for _, sample := range samples { if sample.Value != expected { t.Fatalf("expected %v value, got %v", expected, sample.Value) } } } } }
func newTestStorage(t test.Tester) (storage *tiered.TieredStorage, closer test.Closer) { storage, closer = NewTestTieredStorage(t) if storage == nil { t.Fatal("storage == nil") } storeMatrix(storage, testMatrix) return }
func AppendRepeatingValuesTests(p MetricPersistence, t test.Tester) { metric := model.Metric{ model.MetricNameLabel: "errors_total", "controller": "foo", "operation": "bar", } increments := 10 repetitions := 500 for i := 0; i < increments; i++ { for j := 0; j < repetitions; j++ { time := time.Time{}.Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second) testAppendSample(p, model.Sample{ Value: model.SampleValue(i), Timestamp: time, Metric: metric, }, t) } } if true { // XXX: Purely a benchmark. return } labelSet := model.LabelSet{ model.MetricNameLabel: "errors_total", "controller": "foo", "operation": "bar", } for i := 0; i < increments; i++ { for j := 0; j < repetitions; j++ { fingerprints, err := p.GetFingerprintsForLabelSet(labelSet) if err != nil { t.Fatal(err) } if len(fingerprints) != 1 { t.Fatalf("expected %d fingerprints, got %d", 1, len(fingerprints)) } time := time.Time{}.Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second) sample, err := p.GetValueAtTime(fingerprints[0], time, StalenessPolicy{}) if err != nil { t.Fatal(err) } if sample == nil { t.Fatal("expected non-nil sample.") } expected := model.SampleValue(i) if sample.Value != expected { t.Fatalf("expected %d value, got %d", expected, sample.Value) } } } }
func GetMetricForFingerprintTests(p metric.Persistence, t test.Tester) { testAppendSamples(p, &clientmodel.Sample{ Value: 0, Timestamp: 0, Metric: clientmodel.Metric{ "request_type": "your_mom", }, }, t) testAppendSamples(p, &clientmodel.Sample{ Value: 0, Timestamp: 0, Metric: clientmodel.Metric{ "request_type": "your_dad", "one-off": "value", }, }, t) result, err := p.GetFingerprintsForLabelMatchers(metric.LabelMatchers{{ Type: metric.Equal, Name: "request_type", Value: "your_mom", }}) if err != nil { t.Error(err) } if len(result) != 1 { t.Errorf("Expected one element.") } m, err := p.GetMetricForFingerprint(result[0]) if err != nil { t.Error(err) } if m == nil { t.Fatal("Did not expect nil.") } if len(m) != 1 { t.Errorf("Expected one-dimensional metric.") } if m["request_type"] != "your_mom" { t.Errorf("Expected metric to match.") } result, err = p.GetFingerprintsForLabelMatchers(metric.LabelMatchers{{ Type: metric.Equal, Name: "request_type", Value: "your_dad", }}) if err != nil { t.Error(err) } if len(result) != 1 { t.Errorf("Expected one element.") } m, err = p.GetMetricForFingerprint(result[0]) if m == nil { t.Fatal("Did not expect nil.") } if err != nil { t.Error(err) } if len(m) != 2 { t.Errorf("Expected two-dimensional metric.") } if m["request_type"] != "your_dad" { t.Errorf("Expected metric to match.") } if m["one-off"] != "value" { t.Errorf("Expected metric to match.") } // Verify that mutating a returned metric does not result in the mutated // metric to be returned at the next GetMetricForFingerprint() call. m["one-off"] = "new value" m, err = p.GetMetricForFingerprint(result[0]) if m == nil { t.Fatal("Did not expect nil.") } if err != nil { t.Error(err) } if len(m) != 2 { t.Errorf("Expected two-dimensional metric.") } if m["request_type"] != "your_dad" { t.Errorf("Expected metric to match.") } if m["one-off"] != "value" { t.Errorf("Expected metric to match.") } }
func GetMetricForFingerprintTests(p MetricPersistence, t test.Tester) { testAppendSample(p, model.Sample{ Value: 0, Timestamp: time.Time{}, Metric: model.Metric{ "request_type": "your_mom", }, }, t) testAppendSample(p, model.Sample{ Value: 0, Timestamp: time.Time{}, Metric: model.Metric{ "request_type": "your_dad", "one-off": "value", }, }, t) result, err := p.GetFingerprintsForLabelSet(model.LabelSet{ model.LabelName("request_type"): model.LabelValue("your_mom"), }) if err != nil { t.Error(err) } if len(result) != 1 { t.Errorf("Expected one element.") } v, e := p.GetMetricForFingerprint(result[0]) if e != nil { t.Error(e) } if v == nil { t.Fatal("Did not expect nil.") } metric := *v if len(metric) != 1 { t.Errorf("Expected one-dimensional metric.") } if metric["request_type"] != "your_mom" { t.Errorf("Expected metric to match.") } result, err = p.GetFingerprintsForLabelSet(model.LabelSet{ model.LabelName("request_type"): model.LabelValue("your_dad"), }) if err != nil { t.Error(err) } if len(result) != 1 { t.Errorf("Expected one element.") } v, e = p.GetMetricForFingerprint(result[0]) if v == nil { t.Fatal("Did not expect nil.") } metric = *v if e != nil { t.Error(e) } if len(metric) != 2 { t.Errorf("Expected one-dimensional metric.") } if metric["request_type"] != "your_dad" { t.Errorf("Expected metric to match.") } if metric["one-off"] != "value" { t.Errorf("Expected metric to match.") } }
func testAppendSample(p MetricPersistence, s model.Sample, t test.Tester) { err := p.AppendSample(s) if err != nil { t.Fatal(err) } }
func StochasticTests(persistenceMaker func() (metric.Persistence, test.Closer), t test.Tester) { stochastic := func(x int) (success bool) { p, closer := persistenceMaker() defer closer.Close() defer p.Close() seed := rand.NewSource(int64(x)) random := rand.New(seed) numberOfMetrics := random.Intn(stochasticMaximumVariance) + 1 numberOfSharedLabels := random.Intn(stochasticMaximumVariance) numberOfUnsharedLabels := random.Intn(stochasticMaximumVariance) numberOfSamples := random.Intn(stochasticMaximumVariance) + 2 numberOfRangeScans := random.Intn(stochasticMaximumVariance) metricTimestamps := map[int]map[int64]bool{} metricEarliestSample := map[int]int64{} metricNewestSample := map[int]int64{} for metricIndex := 0; metricIndex < numberOfMetrics; metricIndex++ { sample := &clientmodel.Sample{ Metric: clientmodel.Metric{}, } v := clientmodel.LabelValue(fmt.Sprintf("metric_index_%d", metricIndex)) sample.Metric[clientmodel.MetricNameLabel] = v for sharedLabelIndex := 0; sharedLabelIndex < numberOfSharedLabels; sharedLabelIndex++ { l := clientmodel.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex)) v := clientmodel.LabelValue(fmt.Sprintf("label_%d", sharedLabelIndex)) sample.Metric[l] = v } for unsharedLabelIndex := 0; unsharedLabelIndex < numberOfUnsharedLabels; unsharedLabelIndex++ { l := clientmodel.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, unsharedLabelIndex)) v := clientmodel.LabelValue(fmt.Sprintf("private_label_%d", unsharedLabelIndex)) sample.Metric[l] = v } timestamps := map[int64]bool{} metricTimestamps[metricIndex] = timestamps var newestSample int64 = math.MinInt64 var oldestSample int64 = math.MaxInt64 var nextTimestamp func() int64 nextTimestamp = func() int64 { var candidate int64 candidate = random.Int63n(math.MaxInt32 - 1) if _, has := timestamps[candidate]; has { // WART candidate = nextTimestamp() } timestamps[candidate] = true if candidate < oldestSample { oldestSample = candidate } if candidate > newestSample { newestSample = candidate } return candidate } // BUG(matt): Invariant of the in-memory database assumes this. sortedTimestamps := timeslice{} for sampleIndex := 0; sampleIndex < numberOfSamples; sampleIndex++ { sortedTimestamps = append(sortedTimestamps, clientmodel.TimestampFromUnix(nextTimestamp())) } sort.Sort(sortedTimestamps) for sampleIndex := 0; sampleIndex < numberOfSamples; sampleIndex++ { sample.Timestamp = sortedTimestamps[sampleIndex] sample.Value = clientmodel.SampleValue(sampleIndex) err := p.AppendSamples(clientmodel.Samples{sample}) if err != nil { t.Error(err) return } } metricEarliestSample[metricIndex] = oldestSample metricNewestSample[metricIndex] = newestSample for sharedLabelIndex := 0; sharedLabelIndex < numberOfSharedLabels; sharedLabelIndex++ { matchers := metric.LabelMatchers{{ Type: metric.Equal, Name: clientmodel.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex)), Value: clientmodel.LabelValue(fmt.Sprintf("label_%d", sharedLabelIndex)), }} fingerprints, err := p.GetFingerprintsForLabelMatchers(matchers) if err != nil { t.Error(err) return } if len(fingerprints) == 0 { t.Errorf("expected fingerprint count of %d, got %d", 0, len(fingerprints)) return } } } for metricIndex := 0; metricIndex < numberOfMetrics; metricIndex++ { for unsharedLabelIndex := 0; unsharedLabelIndex < numberOfUnsharedLabels; unsharedLabelIndex++ { labelName := clientmodel.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, unsharedLabelIndex)) labelValue := clientmodel.LabelValue(fmt.Sprintf("private_label_%d", unsharedLabelIndex)) matchers := metric.LabelMatchers{{ Type: metric.Equal, Name: labelName, Value: labelValue, }} fingerprints, err := p.GetFingerprintsForLabelMatchers(matchers) if err != nil { t.Error(err) return } if len(fingerprints) != 1 { t.Errorf("expected fingerprint count of %d, got %d", 1, len(fingerprints)) return } } m := clientmodel.Metric{} m[clientmodel.MetricNameLabel] = clientmodel.LabelValue(fmt.Sprintf("metric_index_%d", metricIndex)) for i := 0; i < numberOfSharedLabels; i++ { l := clientmodel.LabelName(fmt.Sprintf("shared_label_%d", i)) v := clientmodel.LabelValue(fmt.Sprintf("label_%d", i)) m[l] = v } for i := 0; i < numberOfUnsharedLabels; i++ { l := clientmodel.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, i)) v := clientmodel.LabelValue(fmt.Sprintf("private_label_%d", i)) m[l] = v } for i := 0; i < numberOfRangeScans; i++ { timestamps := metricTimestamps[metricIndex] var first int64 var second int64 for { firstCandidate := random.Int63n(int64(len(timestamps))) secondCandidate := random.Int63n(int64(len(timestamps))) smallest := int64(-1) largest := int64(-1) if firstCandidate == secondCandidate { continue } else if firstCandidate > secondCandidate { largest = firstCandidate smallest = secondCandidate } else { largest = secondCandidate smallest = firstCandidate } j := int64(0) for i := range timestamps { if j == smallest { first = i } else if j == largest { second = i break } j++ } break } begin := first end := second if second < first { begin, end = second, first } interval := metric.Interval{ OldestInclusive: clientmodel.TimestampFromUnix(begin), NewestInclusive: clientmodel.TimestampFromUnix(end), } samples := metric.Values{} fp := &clientmodel.Fingerprint{} fp.LoadFromMetric(m) switch persistence := p.(type) { case metric.View: samples = persistence.GetRangeValues(fp, interval) if len(samples) < 2 { t.Fatalf("expected sample count greater than %d, got %d", 2, len(samples)) } case *LevelDBPersistence: var err error samples, err = levelDBGetRangeValues(persistence, fp, interval) if err != nil { t.Fatal(err) } if len(samples) < 2 { t.Fatalf("expected sample count greater than %d, got %d", 2, len(samples)) } default: t.Error("Unexpected type of metric.Persistence.") } } } return true } if err := quick.Check(stochastic, nil); err != nil { t.Error(err) } }
func testAppendSamples(p metric.Persistence, s *clientmodel.Sample, t test.Tester) { err := p.AppendSamples(clientmodel.Samples{s}) if err != nil { t.Fatal(err) } }